Merge branch 'master' into frontmatter-defaults

This commit is contained in:
maul.esel 2013-10-14 19:44:06 +02:00
commit 20ea0c8d56
53 changed files with 856 additions and 203 deletions

View File

@ -9,6 +9,8 @@ rvm:
script: bundle exec rake script: bundle exec rake
notifications: notifications:
irc: irc:
on_success: change
on_failure: change
channels: channels:
- "irc.freenode.org#jekyll" - "irc.freenode.org#jekyll"
#on_success: change #on_success: change

View File

@ -11,14 +11,20 @@ following in mind:
[RR](http://github.com/btakita/rr/tree/master). [RR](http://github.com/btakita/rr/tree/master).
* If it's a brand new feature, make sure to create a new * If it's a brand new feature, make sure to create a new
[Cucumber](https://github.com/cucumber/cucumber/) feature and reuse steps [Cucumber](https://github.com/cucumber/cucumber/) feature and reuse steps
where appropriate. Also, whipping up some documentation in your fork's wiki where appropriate. Also, whipping up some documentation in your fork's `site`
would be appreciated, and once merged it will be transferred over to the main would be appreciated, and once merged it will be transferred over to the main
wiki. `site`, jekyllrb.com.
* If your contribution changes any Jekyll behavior, make sure to update the * If your contribution changes any Jekyll behavior, make sure to update the
documentation. It lives in `site/docs`. If the docs are missing information, documentation. It lives in `site/docs`. If the docs are missing information,
please feel free to add it in. Great docs make a great project! please feel free to add it in. Great docs make a great project!
* Please follow the [GitHub Ruby Styleguide](https://github.com/styleguide/ruby) * Please follow the [GitHub Ruby Styleguide](https://github.com/styleguide/ruby)
when modifying Ruby code. when modifying Ruby code.
* Please do your best to submit **small pull requests**. The easier the proposed
change is to review, the more likely it will be merged.
* When submitting a pull request, please make judicious use of the pull request
body. A description of what changes were made, the motivations behind the
changes and [any tasks completed or left to complete](http://git.io/gfm-tasks)
will also speed up review time.
Test Dependencies Test Dependencies
----------------- -----------------
@ -32,8 +38,8 @@ you're all set!
Before you start, run the tests and make sure that they pass (to confirm your Before you start, run the tests and make sure that they pass (to confirm your
environment is configured properly): environment is configured properly):
$ rake test $ bundle exec rake test
$ rake features $ bundle exec rake features
Workflow Workflow
-------- --------
@ -65,8 +71,7 @@ All documentation pull requests should be directed at `master`. Pull
requests directed at another branch will not be accepted. requests directed at another branch will not be accepted.
The [Jekyll wiki](https://github.com/mojombo/jekyll/wiki) on GitHub The [Jekyll wiki](https://github.com/mojombo/jekyll/wiki) on GitHub
can be freely updated without a pull request as all can be freely updated without a pull request as all GitHub users have access.
GitHub users have access.
Gotchas Gotchas
------- -------

View File

@ -1,23 +1,78 @@
## HEAD ## HEAD
### Major Enhancements ### Major Enhancements
* Add support for adding data as YAML files under a site's `_data`
directory (#1003)
* Allow variables to be used with `include` tags (#1495)
### Minor Enhancements ### Minor Enhancements
* Decrease the specificity in the site template CSS (#1574)
* Add `encoding` configuration option (#1449)
* Provide better error handling for Jekyll's custom Liquid tags
(#1514)
* If an included file causes a Liquid error, add the path to the
include file that caused the error to the error message (#1596)
* If a layout causes a Liquid error, change the error message so that
we know it comes from the layout (#1601)
* Update Kramdown dependency to `~> 1.2` (#1610)
* Update `safe_yaml` dependency to `~> 0.9.7` (#1602)
* Allow layouts to be in subfolders like includes (#1622)
### Bug Fixes
* Fix up matching against source and destination when the two
locations are similar (#1556)
* Fix the missing `pathname` require in certain cases (#1255)
* Use `+` instead of `Array#concat` when building `Post` attribute list (#1571)
* Print server address when launching a server (#1586)
* Downgrade to Maruku `~> 0.6.0` in order to avoid changes in rendering (#1598)
* Fix error with failing include tag when variable was file name (#1613)
* Downcase lexers before passing them to pygments (#1615)
### Development Fixes
* Add coverage reporting with Coveralls (#1539)
* Refactor the Liquid `include` tag (#1490)
* Update launchy dependency to `~> 2.3` (#1608)
* Update rr dependency to `~> 1.1` (#1604)
* Update cucumber dependency to `~> 1.3` (#1607)
* Update coveralls dependency to `~> 0.7.0` (#1606)
* Update rake dependency to `~> 10.1` (#1603)
* Clean up `site.rb` comments to be more concise/uniform (#1616)
### Site Enhancements
* Fix params for `JekyllImport::WordPress.process` arguments (#1554)
* Add `jekyll-suggested-tweet` to list of third-party plugins (#1555)
* Link to Liquid's docs for tags and filters (#1553)
* Add note about installing Xcode on the Mac in the Installation docs (#1561)
* Simplify/generalize pagination docs (#1577)
* Add documentation for the new data sources feature (#1503)
* Add more information on how to create generators (#1590, #1592)
* Improve the instructions for mimicking GitHub Flavored Markdown
(#1614)
* Add `jekyll-import` warning note of missing dependencies (#1626)
## 1.2.1 / 2013-09-14
### Minor Enhancements
* Print better messages for detached server. Mute output on detach. (#1518)
* Disable reverse lookup when running `jekyll serve` (#1363) * Disable reverse lookup when running `jekyll serve` (#1363)
* Upgrade RedCarpet dependency to `~> 2.3.0` (#1515) * Upgrade RedCarpet dependency to `~> 2.3.0` (#1515)
* Upgrade to Liquid `>= 2.5.2, < 2.6` (#1536)
### Bug Fixes ### Bug Fixes
* Fix file discrepancy in gemspec (#1522) * Fix file discrepancy in gemspec (#1522)
* Force rendering of Include tag (#1525)
### Development Fixes ### Development Fixes
* Add a rake task to generate a new release post (#1404) * Add a rake task to generate a new release post (#1404)
* Mute LSI output in tests (#1531)
* Update contributor documentation (#1537)
### Site Enhancements ### Site Enhancements
* Fix a couple of validation errors on the site (#1511) * Fix a couple of validation errors on the site (#1511)
* Make navigation menus reusable (#1507) * Make navigation menus reusable (#1507)
* Fix link to History page from Release v1.2.0 notes post. * Fix link to History page from Release v1.2.0 notes post.
* Fix markup in History file for command line options (#1512) * Fix markup in History file for command line options (#1512)
* Expand 1.2 release post title to 1.2.0 (#1516)
## 1.2.0 / 2013-09-06 ## 1.2.0 / 2013-09-06

View File

@ -5,6 +5,7 @@
[![Build Status](https://secure.travis-ci.org/mojombo/jekyll.png)](https://travis-ci.org/mojombo/jekyll) [![Build Status](https://secure.travis-ci.org/mojombo/jekyll.png)](https://travis-ci.org/mojombo/jekyll)
[![Code Climate](https://codeclimate.com/github/mojombo/jekyll.png)](https://codeclimate.com/github/mojombo/jekyll) [![Code Climate](https://codeclimate.com/github/mojombo/jekyll.png)](https://codeclimate.com/github/mojombo/jekyll)
[![Dependency Status](https://gemnasium.com/mojombo/jekyll.png)](https://gemnasium.com/mojombo/jekyll) [![Dependency Status](https://gemnasium.com/mojombo/jekyll.png)](https://gemnasium.com/mojombo/jekyll)
[![Coverage Status](https://coveralls.io/repos/mojombo/jekyll/badge.png)](https://coveralls.io/r/mojombo/jekyll)
By Tom Preston-Werner, Nick Quaranto, and many awesome contributors! By Tom Preston-Werner, Nick Quaranto, and many awesome contributors!

View File

@ -84,7 +84,14 @@ end
# #
############################################################################# #############################################################################
task :default => [:test, :features] if RUBY_VERSION > '1.9' && ENV["TRAVIS"] == "true"
require 'coveralls/rake/task'
Coveralls::RakeTask.new
task :default => [:test, :features, 'coveralls:push']
else
task :default => [:test, :features]
end
require 'rake/testtask' require 'rake/testtask'
Rake::TestTask.new(:test) do |test| Rake::TestTask.new(:test) do |test|
@ -217,6 +224,7 @@ namespace :site do
task :new, :version do |t, args| task :new, :version do |t, args|
raise "Specify a version: rake site:releases:new['1.2.3']" unless args.version raise "Specify a version: rake site:releases:new['1.2.3']" unless args.version
today = Time.new.strftime('%Y-%m-%d') today = Time.new.strftime('%Y-%m-%d')
release = args.version.to_s
filename = "site/_posts/#{today}-jekyll-#{release.split('.').join('-')}-released.markdown" filename = "site/_posts/#{today}-jekyll-#{release.split('.').join('-')}-released.markdown"
File.open(filename, "wb") do |post| File.open(filename, "wb") do |post|

View File

@ -65,6 +65,7 @@ command :build do |c|
c.option '-w', '--watch', 'Watch for changes and rebuild' c.option '-w', '--watch', 'Watch for changes and rebuild'
c.option '--lsi', 'Use LSI for improved related posts' c.option '--lsi', 'Use LSI for improved related posts'
c.option '-D', '--drafts', 'Render posts in the _drafts folder' c.option '-D', '--drafts', 'Render posts in the _drafts folder'
c.option '-v', '--verbose', 'Print verbose output.'
c.action do |args, options| c.action do |args, options|
options = normalize_options(options.__hash__) options = normalize_options(options.__hash__)
@ -84,6 +85,7 @@ command :serve do |c|
c.option '--lsi', 'Use LSI for improved related posts' c.option '--lsi', 'Use LSI for improved related posts'
c.option '-B', '--detach', 'Run the server in the background (detach)' c.option '-B', '--detach', 'Run the server in the background (detach)'
c.option '-D', '--drafts', 'Render posts in the _drafts folder' c.option '-D', '--drafts', 'Render posts in the _drafts folder'
c.option '-v', '--verbose', 'Print verbose output.'
c.option '-P', '--port [PORT]', 'Port to listen on' c.option '-P', '--port [PORT]', 'Port to listen on'
c.option '-H', '--host [HOST]', 'Host to bind to' c.option '-H', '--host [HOST]', 'Host to bind to'

View File

@ -44,6 +44,17 @@ Feature: Create sites
Then the _site directory should exist Then the _site directory should exist
And I should see "Post Layout: <p>The only winning move is not to play.</p>" in "_site/2009/03/27/wargames.html" And I should see "Post Layout: <p>The only winning move is not to play.</p>" in "_site/2009/03/27/wargames.html"
Scenario: Basic site with layout inside a subfolder and a post
Given I have a _layouts directory
And I have a _posts directory
And I have the following posts:
| title | date | layout | content |
| Wargames | 2009-03-27 | post/simple | The only winning move is not to play. |
And I have a post/simple layout that contains "Post Layout: {{ content }}"
When I run jekyll
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 Scenario: Basic site with layouts, pages, posts and files
Given I have a _layouts directory Given I have a _layouts directory
And I have a page layout that contains "Page {{ page.title }}: {{ content }}" And I have a page layout that contains "Page {{ page.title }}: {{ content }}"

65
features/data.feature Normal file
View File

@ -0,0 +1,65 @@
Feature: Data
In order to use well-formatted data in my blog
As a blog's user
I want to use _data directory in my site
Scenario: autoload *.yaml files in _data directory
Given I have a _data directory
And I have a "_data/products.yaml" file with content:
"""
- name: sugar
price: 5.3
- name: salt
price: 2.5
"""
And I have an "index.html" page that contains "{% for product in site.data.products %}{{product.name}}{% endfor %}"
When I run jekyll
Then the "_site/index.html" file should exist
And I should see "sugar" in "_site/index.html"
And I should see "salt" in "_site/index.html"
Scenario: autoload *.yml files in _data directory
Given I have a _data directory
And I have a "_data/members.yml" file with content:
"""
- name: Jack
age: 28
- name: Leon
age: 34
"""
And I have an "index.html" page that contains "{% for member in site.data.members %}{{member.name}}{% endfor %}"
When I run jekyll
Then the "_site/index.html" file should exist
And I should see "Jack" in "_site/index.html"
And I should see "Leon" in "_site/index.html"
Scenario: autoload *.yml files in _data directory with space in file name
Given I have a _data directory
And I have a "_data/team members.yml" file with content:
"""
- name: Jack
age: 28
- name: Leon
age: 34
"""
And I have an "index.html" page that contains "{% for member in site.data.team_members %}{{member.name}}{% endfor %}"
When I run jekyll
Then the "_site/index.html" file should exist
And I should see "Jack" in "_site/index.html"
And I should see "Leon" in "_site/index.html"
Scenario: should be backward compatible with site.data in _config.yml
Given I have a "_config.yml" file with content:
"""
data:
- name: Jack
age: 28
- name: Leon
age: 34
"""
And I have an "index.html" page that contains "{% for member in site.data %}{{member.name}}{% endfor %}"
When I run jekyll
Then the "_site/index.html" file should exist
And I should see "Jack" in "_site/index.html"
And I should see "Leon" in "_site/index.html"

View File

@ -33,3 +33,16 @@ Feature: Include tags
And I should see "<li>param1_or_2 = value</li>" in "_site/2013/04/12/parameter-syntax.html" And I should see "<li>param1_or_2 = value</li>" in "_site/2013/04/12/parameter-syntax.html"
And I should see "<li>local = some text</li>" in "_site/2013/06/22/pass-a-variable.html" And I should see "<li>local = some text</li>" in "_site/2013/06/22/pass-a-variable.html"
And I should see "<li>layout = default</li>" in "_site/2013/06/22/pass-a-variable.html" And I should see "<li>layout = default</li>" in "_site/2013/06/22/pass-a-variable.html"
Scenario: Include a file from a variable
Given I have an _includes directory
And I have an "_includes/snippet.html" file that contains "a snippet"
And I have an "_includes/parametrized.html" file that contains "works with {{include.what}}"
And I have a configuration file with:
| key | value |
| include_file1 | snippet.html |
| include_file2 | parametrized.html |
And I have an "index.html" page that contains "{% include {{site.include_file1}} %} that {% include {{site.include_file2}} what='parameters' %}"
When I run jekyll
Then the _site directory should exist
And I should see "a snippet that works with parameters" in "_site/index.html"

View File

@ -18,6 +18,27 @@ Feature: Site configuration
Then the _mysite directory should exist Then the _mysite directory should exist
And I should see "Changing destination directory" in "_mysite/index.html" And I should see "Changing destination directory" in "_mysite/index.html"
Scenario Outline: Similarly named source and destination
Given I have a blank site in "<source>"
And I have an "<source>/index.md" page that contains "markdown"
And I have a configuration file with:
| key | value |
| source | <source> |
| destination | <dest> |
When I run jekyll
Then the <source> directory should exist
And the "<dest>/index.html" file should <file_exist> exist
And I should see "markdown" in "<source>/index.md"
Examples:
| source | dest | file_exist |
| mysite_source | mysite | |
| mysite | mysite_dest | |
| mysite/ | mysite | not |
| mysite | ./mysite | not |
| mysite/source | mysite | not |
| mysite | mysite/dest | |
Scenario: Exclude files inline Scenario: Exclude files inline
Given I have an "Rakefile" file that contains "I want to be excluded" Given I have an "Rakefile" file that contains "I want to be excluded"
And I have an "README" file that contains "I want to be excluded" And I have an "README" file that contains "I want to be excluded"

View File

@ -7,7 +7,7 @@ end
World(Test::Unit::Assertions) World(Test::Unit::Assertions)
Given /^I have a blank site in "(.*)"$/ do |path| Given /^I have a blank site in "(.*)"$/ do |path|
FileUtils.mkdir(path) FileUtils.mkdir_p(path)
end end
Given /^I do not have a "(.*)" directory$/ do |path| Given /^I do not have a "(.*)" directory$/ do |path|
@ -38,7 +38,18 @@ Given /^I have an? (.*) (layout|theme) that contains "(.*)"$/ do |name, type, te
else else
'_theme' '_theme'
end end
File.open(File.join(folder, name + '.html'), 'w') do |f| destination_file = File.join(folder, name + '.html')
destination_path = File.dirname(destination_file)
unless File.exist?(destination_path)
FileUtils.mkdir_p(destination_path)
end
File.open(destination_file, 'w') do |f|
f.write(text)
end
end
Given /^I have an? "(.*)" file with content:$/ do |file, text|
File.open(file, 'w') do |f|
f.write(text) f.write(text)
end end
end end
@ -137,10 +148,14 @@ When /^I delete the file "(.*)"$/ do |file|
File.delete(file) File.delete(file)
end end
Then /^the (.*) directory should exist$/ do |dir| Then /^the (.*) directory should +exist$/ do |dir|
assert File.directory?(dir), "The directory \"#{dir}\" does not exist" assert File.directory?(dir), "The directory \"#{dir}\" does not exist"
end end
Then /^the (.*) directory should not exist$/ do |dir|
assert !File.directory?(dir), "The directory \"#{dir}\" exists"
end
Then /^I should see "(.*)" in "(.*)"$/ do |text, file| Then /^I should see "(.*)" in "(.*)"$/ do |text, file|
assert Regexp.new(text).match(File.open(file).readlines.join) assert Regexp.new(text).match(File.open(file).readlines.join)
end end
@ -157,12 +172,12 @@ Then /^I should see escaped "(.*)" in "(.*)"$/ do |text, file|
assert Regexp.new(Regexp.escape(text)).match(File.open(file).readlines.join) assert Regexp.new(Regexp.escape(text)).match(File.open(file).readlines.join)
end end
Then /^the "(.*)" file should exist$/ do |file| Then /^the "(.*)" file should +exist$/ do |file|
assert File.file?(file) assert File.file?(file), "The file \"#{file}\" does not exist"
end end
Then /^the "(.*)" file should not exist$/ do |file| Then /^the "(.*)" file should not exist$/ do |file|
assert !File.exists?(file) assert !File.exists?(file), "The file \"#{file}\" exists"
end end
Then /^I should see today's time in "(.*)"$/ do |file| Then /^I should see today's time in "(.*)"$/ do |file|

View File

@ -1,3 +1,8 @@
if RUBY_VERSION > '1.9'
require 'coveralls'
Coveralls.wear_merged!
end
require 'fileutils' require 'fileutils'
require 'rr' require 'rr'
require 'test/unit' require 'test/unit'

View File

@ -4,9 +4,9 @@ Gem::Specification.new do |s|
s.rubygems_version = '1.3.5' s.rubygems_version = '1.3.5'
s.name = 'jekyll' s.name = 'jekyll'
s.version = '1.2.0' s.version = '1.2.1'
s.license = 'MIT' s.license = 'MIT'
s.date = '2013-09-06' s.date = '2013-09-14'
s.rubyforge_project = 'jekyll' s.rubyforge_project = 'jekyll'
s.summary = "A simple, blog aware, static site generator." s.summary = "A simple, blog aware, static site generator."
@ -23,28 +23,29 @@ Gem::Specification.new do |s|
s.rdoc_options = ["--charset=UTF-8"] s.rdoc_options = ["--charset=UTF-8"]
s.extra_rdoc_files = %w[README.markdown LICENSE] s.extra_rdoc_files = %w[README.markdown LICENSE]
s.add_runtime_dependency('liquid', "~> 2.5.1") s.add_runtime_dependency('liquid', "~> 2.5.2")
s.add_runtime_dependency('classifier', "~> 1.3") s.add_runtime_dependency('classifier', "~> 1.3")
s.add_runtime_dependency('directory_watcher', "~> 1.4.1") s.add_runtime_dependency('directory_watcher', "~> 1.4.1")
s.add_runtime_dependency('maruku', "~> 0.5") s.add_runtime_dependency('maruku', "~> 0.6.0")
s.add_runtime_dependency('pygments.rb', "~> 0.5.0") s.add_runtime_dependency('pygments.rb', "~> 0.5.0")
s.add_runtime_dependency('commander', "~> 4.1.3") s.add_runtime_dependency('commander', "~> 4.1.3")
s.add_runtime_dependency('safe_yaml', "~> 0.7.0") s.add_runtime_dependency('safe_yaml', "~> 0.9.7")
s.add_runtime_dependency('colorator', "~> 0.1") s.add_runtime_dependency('colorator', "~> 0.1")
s.add_runtime_dependency('redcarpet', "~> 2.3.0") s.add_runtime_dependency('redcarpet', "~> 2.3.0")
s.add_development_dependency('rake', "~> 10.0.3") s.add_development_dependency('rake', "~> 10.1")
s.add_development_dependency('rdoc', "~> 3.11") s.add_development_dependency('rdoc', "~> 3.11")
s.add_development_dependency('redgreen', "~> 1.2") s.add_development_dependency('redgreen', "~> 1.2")
s.add_development_dependency('shoulda', "~> 3.3.2") s.add_development_dependency('shoulda', "~> 3.3.2")
s.add_development_dependency('rr', "~> 1.0.0") s.add_development_dependency('rr', "~> 1.1")
s.add_development_dependency('cucumber', "~> 1.2.1", '!= 1.2.4') s.add_development_dependency('cucumber', "~> 1.3")
s.add_development_dependency('RedCloth', "~> 4.2") s.add_development_dependency('RedCloth', "~> 4.2")
s.add_development_dependency('kramdown', "~> 1.0.2") s.add_development_dependency('kramdown', "~> 1.2")
s.add_development_dependency('rdiscount', "~> 1.6") s.add_development_dependency('rdiscount', "~> 1.6")
s.add_development_dependency('launchy', "~> 2.1.2") s.add_development_dependency('launchy', "~> 2.3")
s.add_development_dependency('simplecov', "~> 0.7") s.add_development_dependency('simplecov', "~> 0.7")
s.add_development_dependency('simplecov-gem-adapter', "~> 1.0.1") s.add_development_dependency('simplecov-gem-adapter', "~> 1.0.1")
s.add_development_dependency('coveralls', "~> 0.7.0")
s.add_development_dependency('activesupport', '~> 3.2.13') s.add_development_dependency('activesupport', '~> 3.2.13')
# = MANIFEST = # = MANIFEST =
@ -58,6 +59,7 @@ Gem::Specification.new do |s|
bin/jekyll bin/jekyll
cucumber.yml cucumber.yml
features/create_sites.feature features/create_sites.feature
features/data.feature
features/drafts.feature features/drafts.feature
features/embed_filters.feature features/embed_filters.feature
features/include_tag.feature features/include_tag.feature
@ -149,6 +151,7 @@ Gem::Specification.new do |s|
site/_posts/2013-07-25-jekyll-1-0-4-released.markdown site/_posts/2013-07-25-jekyll-1-0-4-released.markdown
site/_posts/2013-07-25-jekyll-1-1-2-released.markdown site/_posts/2013-07-25-jekyll-1-1-2-released.markdown
site/_posts/2013-09-06-jekyll-1-2-0-released.markdown site/_posts/2013-09-06-jekyll-1-2-0-released.markdown
site/_posts/2013-09-14-jekyll-1-2-1-released.markdown
site/css/gridism.css site/css/gridism.css
site/css/normalize.css site/css/normalize.css
site/css/pygments.css site/css/pygments.css
@ -201,6 +204,7 @@ Gem::Specification.new do |s|
test/helper.rb test/helper.rb
test/source/+/foo.md test/source/+/foo.md
test/source/.htaccess test/source/.htaccess
test/source/_data/members.yaml
test/source/_includes/params.html test/source/_includes/params.html
test/source/_includes/sig.markdown test/source/_includes/sig.markdown
test/source/_layouts/default.html test/source/_layouts/default.html

View File

@ -20,6 +20,7 @@ require 'fileutils'
require 'time' require 'time'
require 'safe_yaml' require 'safe_yaml'
require 'English' require 'English'
require 'pathname'
# 3rd party # 3rd party
require 'liquid' require 'liquid'
@ -61,7 +62,7 @@ require_all 'jekyll/tags'
SafeYAML::OPTIONS[:suppress_warnings] = true SafeYAML::OPTIONS[:suppress_warnings] = true
module Jekyll module Jekyll
VERSION = '1.2.0' VERSION = '1.2.1'
# Public: Generate a Jekyll configuration Hash by merging the default # Public: Generate a Jekyll configuration Hash by merging the default
# options with anything in _config.yml, and adding the given options on top. # options with anything in _config.yml, and adding the given options on top.

View File

@ -2,7 +2,7 @@ require 'set'
module Jekyll module Jekyll
class Site class Site
# Handles the cleanup of a site's destination before the site is built. # Handles the cleanup of a site's destination before it is built.
class Cleaner class Cleaner
def initialize(site) def initialize(site)
@site = site @site = site
@ -15,14 +15,14 @@ module Jekyll
private private
# Private: The list of files and directories to be deleted during the cleanup process # Private: The list of files and directories to be deleted during cleanup process
# #
# Returns an Array with the file and directory paths # Returns an Array of the file and directory paths
def obsolete_files def obsolete_files
(existing_files - new_files - new_dirs + replaced_files).to_a (existing_files - new_files - new_dirs + replaced_files).to_a
end end
# Private: The list of existing files, except those included in keep_files and hidden files. # Private: The list of existing files, apart from those included in keep_files and hidden files.
# #
# Returns a Set with the file paths # Returns a Set with the file paths
def existing_files def existing_files
@ -33,7 +33,7 @@ module Jekyll
files files
end end
# Private: The list of files to be created when the site is built. # Private: The list of files to be created when site is built.
# #
# Returns a Set with the file paths # Returns a Set with the file paths
def new_files def new_files
@ -42,7 +42,7 @@ module Jekyll
files files
end end
# Private: The list of directories to be created when the site is built. # Private: The list of directories to be created when site is built.
# These are the parent directories of the files in #new_files. # These are the parent directories of the files in #new_files.
# #
# Returns a Set with the directory paths # Returns a Set with the directory paths
@ -57,7 +57,7 @@ module Jekyll
new_dirs.select { |dir| File.file?(dir) }.to_set new_dirs.select { |dir| File.file?(dir) }.to_set
end end
# Private: creates a regular expression from the config's keep_files array # Private: Creates a regular expression from the config's keep_files array
# #
# Examples # Examples
# ['.git','.svn'] creates the following regex: /\/(\.git|\/.svn)/ # ['.git','.svn'] creates the following regex: /\/(\.git|\/.svn)/

View File

@ -1,4 +1,4 @@
# -*- coding: utf-8 -*- # -*- encoding: utf-8 -*-
module Jekyll module Jekyll
module Commands module Commands
class Serve < Command class Serve < Command
@ -10,32 +10,56 @@ module Jekyll
FileUtils.mkdir_p(destination) FileUtils.mkdir_p(destination)
mime_types_file = File.expand_path('../mime.types', File.dirname(__FILE__))
mime_types = WEBrick::HTTPUtils::load_mime_types(mime_types_file)
# recreate NondisclosureName under utf-8 circumstance # recreate NondisclosureName under utf-8 circumstance
fh_option = WEBrick::Config::FileHandler fh_option = WEBrick::Config::FileHandler
fh_option[:NondisclosureName] = ['.ht*','~*'] fh_option[:NondisclosureName] = ['.ht*','~*']
s = HTTPServer.new( s = HTTPServer.new(webrick_options(options))
:Port => options['port'],
:BindAddress => options['host'],
:MimeTypes => mime_types,
:DoNotReverseLookup => true
)
s.mount(options['baseurl'], HTTPServlet::FileHandler, destination, fh_option) s.mount(options['baseurl'], HTTPServlet::FileHandler, destination, fh_option)
Jekyll.logger.info "Server address:", "http://#{s.config[:BindAddress]}:#{s.config[:Port]}"
if options['detach'] # detach the server if options['detach'] # detach the server
pid = Process.fork {s.start} pid = Process.fork { s.start }
Process.detach(pid) Process.detach(pid)
pid Jekyll.logger.info "Server detatched with pid '#{pid}'.", "Run `kill -9 #{pid}' to stop the server."
else # create a new server thread, then join it with current terminal else # create a new server thread, then join it with current terminal
t = Thread.new { s.start } t = Thread.new { s.start }
trap("INT") { s.shutdown } trap("INT") { s.shutdown }
t.join() t.join()
end end
end end
def self.webrick_options(config)
opts = {
:Port => config['port'],
:BindAddress => config['host'],
:MimeTypes => self.mime_types,
:DoNotReverseLookup => true,
:StartCallback => start_callback(config['detach'])
}
if !config['verbose']
opts.merge!({
:AccessLog => [],
:Logger => Log::new([], Log::WARN)
})
end
opts
end
def self.start_callback(detached)
unless detached
Proc.new { Jekyll.logger.info "Server running...", "press ctrl-c to stop." }
end
end
def self.mime_types
mime_types_file = File.expand_path('../mime.types', File.dirname(__FILE__))
WEBrick::HTTPUtils::load_mime_types(mime_types_file)
end
end end
end end
end end

View File

@ -10,10 +10,13 @@ module Jekyll
'destination' => File.join(Dir.pwd, '_site'), 'destination' => File.join(Dir.pwd, '_site'),
'plugins' => '_plugins', 'plugins' => '_plugins',
'layouts' => '_layouts', 'layouts' => '_layouts',
'data_source' => '_data',
'keep_files' => ['.git','.svn'], 'keep_files' => ['.git','.svn'],
'timezone' => nil, # use the local timezone 'timezone' => nil, # use the local timezone
'encoding' => nil, # use the system encoding
'safe' => false, 'safe' => false,
'detach' => false, # default to not detaching the server 'detach' => false, # default to not detaching the server
'show_drafts' => nil, 'show_drafts' => nil,

View File

@ -21,16 +21,23 @@ module Jekyll
self.content || '' self.content || ''
end end
# Returns merged optin hash for File.read of self.site (if exists)
# and a given param
def merged_file_read_opts(opts)
(self.site ? self.site.file_read_opts : {}).merge(opts)
end
# Read the YAML frontmatter. # Read the YAML frontmatter.
# #
# base - The String path to the dir containing the file. # base - The String path to the dir containing the file.
# name - The String filename of the file. # name - The String filename of the file.
# opts - optional parameter to File.read, default at site configs
# #
# Returns nothing. # Returns nothing.
def read_yaml(base, name) def read_yaml(base, name, opts = {})
begin begin
self.content = File.read(File.join(base, name)) self.content = File.read_with_options(File.join(base, name),
merged_file_read_opts(opts))
if self.content =~ /\A(---\s*\n.*?\n?)^(---\s*$\n?)/m if self.content =~ /\A(---\s*\n.*?\n?)^(---\s*$\n?)/m
self.content = $POSTMATCH self.content = $POSTMATCH
self.data = YAML.safe_load($1) self.data = YAML.safe_load($1)
@ -78,10 +85,13 @@ module Jekyll
# info - the info for Liquid # info - the info for Liquid
# #
# Returns the converted content # Returns the converted content
def render_liquid(content, payload, info) def render_liquid(content, payload, info, path = nil)
Liquid::Template.parse(content).render!(payload, info) Liquid::Template.parse(content).render!(payload, info)
rescue Tags::IncludeTagError => e
Jekyll.logger.error "Liquid Exception:", "#{e.message} in #{e.path}"
raise e
rescue Exception => e rescue Exception => e
Jekyll.logger.error "Liquid Exception:", "#{e.message} in #{self.path}" Jekyll.logger.error "Liquid Exception:", "#{e.message} in #{path || self.path}"
raise e raise e
end end
@ -113,7 +123,8 @@ module Jekyll
self.output = self.render_liquid(layout.content, self.output = self.render_liquid(layout.content,
payload, payload,
info) info,
File.join(self.site.config['layouts'], layout.name))
if layout = layouts[layout.data["layout"]] if layout = layouts[layout.data["layout"]]
if used.include?(layout) if used.include?(layout)

View File

@ -83,3 +83,18 @@ module Enumerable
any? { |exp| File.fnmatch?(exp, e) } any? { |exp| File.fnmatch?(exp, e) }
end end
end end
# Ruby 1.8's File.read don't support option.
# read_with_options ignore optional parameter for 1.8,
# and act as alias for 1.9 or later.
class File
if RUBY_VERSION < '1.9'
def self.read_with_options(path, opts = {})
self.read(path)
end
else
def self.read_with_options(path, opts = {})
self.read(path, opts)
end
end
end

View File

@ -19,10 +19,10 @@ module Jekyll
] ]
# Attributes for Liquid templates # Attributes for Liquid templates
ATTRIBUTES_FOR_LIQUID = EXCERPT_ATTRIBUTES_FOR_LIQUID.concat(%w[ ATTRIBUTES_FOR_LIQUID = EXCERPT_ATTRIBUTES_FOR_LIQUID + %w[
content content
excerpt excerpt
]) ]
# Post name validator. Post filenames must be like: # Post name validator. Post filenames must be like:
# 2008-11-05-my-awesome-post.textile # 2008-11-05-my-awesome-post.textile

View File

@ -3,7 +3,7 @@ module Jekyll
attr_accessor :config, :layouts, :posts, :pages, :static_files, attr_accessor :config, :layouts, :posts, :pages, :static_files,
:categories, :exclude, :include, :source, :dest, :lsi, :pygments, :categories, :exclude, :include, :source, :dest, :lsi, :pygments,
:permalink_style, :tags, :time, :future, :safe, :plugins, :limit_posts, :permalink_style, :tags, :time, :future, :safe, :plugins, :limit_posts,
:show_drafts, :keep_files, :baseurl :show_drafts, :keep_files, :baseurl, :data, :file_read_opts
attr_accessor :converters, :generators attr_accessor :converters, :generators
@ -22,6 +22,9 @@ module Jekyll
self.plugins = plugins_path self.plugins = plugins_path
self.permalink_style = config['permalink'].to_sym self.permalink_style = config['permalink'].to_sym
self.file_read_opts = {}
self.file_read_opts[:encoding] = config['encoding'] if config['encoding']
self.reset self.reset
self.setup self.setup
end end
@ -53,6 +56,7 @@ module Jekyll
self.static_files = [] self.static_files = []
self.categories = Hash.new { |hash, key| hash[key] = [] } self.categories = Hash.new { |hash, key| hash[key] = [] }
self.tags = Hash.new { |hash, key| hash[key] = [] } self.tags = Hash.new { |hash, key| hash[key] = [] }
self.data = {}
if self.limit_posts < 0 if self.limit_posts < 0
raise ArgumentError, "limit_posts must be a non-negative number" raise ArgumentError, "limit_posts must be a non-negative number"
@ -63,11 +67,7 @@ module Jekyll
# #
# Returns nothing. # Returns nothing.
def setup def setup
# Check that the destination dir isn't the source dir or a directory ensure_not_in_dest
# parent to the source dir.
if self.source =~ /^#{self.dest}/
raise FatalException.new "Destination directory cannot be or contain the Source directory."
end
# If safe mode is off, load in any Ruby files under the plugins # If safe mode is off, load in any Ruby files under the plugins
# directory. # directory.
@ -83,6 +83,17 @@ module Jekyll
self.generators = instantiate_subclasses(Jekyll::Generator) self.generators = instantiate_subclasses(Jekyll::Generator)
end end
# Check that the destination dir isn't the source dir or a directory
# parent to the source dir.
def ensure_not_in_dest
dest = Pathname.new(self.dest)
Pathname.new(self.source).ascend do |path|
if path == dest
raise FatalException.new "Destination directory cannot be or contain the Source directory."
end
end
end
# Internal: Setup the plugin search path # Internal: Setup the plugin search path
# #
# Returns an Array of plugin search paths # Returns an Array of plugin search paths
@ -100,6 +111,7 @@ module Jekyll
def read def read
self.read_layouts self.read_layouts
self.read_directories self.read_directories
self.read_data(config['data_source'])
end end
# Read all the files in <source>/<layouts> and create a new Layout object # Read all the files in <source>/<layouts> and create a new Layout object
@ -110,7 +122,7 @@ module Jekyll
base = File.join(self.source, self.config['layouts']) base = File.join(self.source, self.config['layouts'])
return unless File.exists?(base) return unless File.exists?(base)
entries = [] entries = []
Dir.chdir(base) { entries = filter_entries(Dir['*.*']) } Dir.chdir(base) { entries = filter_entries(Dir['**/*.*']) }
entries.each do |f| entries.each do |f|
name = f.split(".")[0..-2].join(".") name = f.split(".")[0..-2].join(".")
@ -187,6 +199,25 @@ module Jekyll
end end
end end
# Read and parse all yaml files under <source>/<dir>
#
# Returns nothing
def read_data(dir)
base = File.join(self.source, dir)
return unless File.directory?(base) && (!self.safe || !File.symlink?(base))
entries = Dir.chdir(base) { Dir['*.{yaml,yml}'] }
entries.delete_if { |e| File.directory?(File.join(base, e)) }
entries.each do |entry|
path = File.join(self.source, dir, entry)
next if File.symlink?(path) && self.safe
key = sanitize_filename(File.basename(entry, '.*'))
self.data[key] = YAML.safe_load_file(path)
end
end
# Run each of the Generators. # Run each of the Generators.
# #
# Returns nothing. # Returns nothing.
@ -252,6 +283,14 @@ module Jekyll
hash hash
end end
# Prepare site data for site payload. The method maintains backward compatibility
# if the key 'data' is already used in _config.yml.
#
# Returns the Hash to be hooked to site.data.
def site_data
self.config['data'] || self.data
end
# The Hash payload containing site-wide data. # The Hash payload containing site-wide data.
# #
# Returns the Hash: { "site" => data } where data is a Hash with keys: # Returns the Hash: { "site" => data } where data is a Hash with keys:
@ -273,7 +312,8 @@ module Jekyll
"pages" => self.pages, "pages" => self.pages,
"html_pages" => self.pages.reject { |page| !page.html? }, "html_pages" => self.pages.reject { |page| !page.html? },
"categories" => post_attr_hash('categories'), "categories" => post_attr_hash('categories'),
"tags" => post_attr_hash('tags')})} "tags" => post_attr_hash('tags'),
"data" => site_data})}
end end
# Filter out any files/directories that are hidden or backup files (start # Filter out any files/directories that are hidden or backup files (start
@ -387,5 +427,11 @@ module Jekyll
def site_cleaner def site_cleaner
@site_cleaner ||= Cleaner.new(self) @site_cleaner ||= Cleaner.new(self)
end end
def sanitize_filename(name)
name = name.gsub(/[^\w\s_-]+/, '')
name = name.gsub(/(^|\b\s)\s+($|\s?\b)/, '\\1\\2')
name = name.gsub(/\s+/, '_')
end
end end
end end

View File

@ -12,7 +12,15 @@ module Jekyll
gist_id, filename = tag_contents[0], tag_contents[1] gist_id, filename = tag_contents[0], tag_contents[1]
gist_script_tag(gist_id, filename) gist_script_tag(gist_id, filename)
else else
"Error parsing gist id" raise ArgumentError.new <<-eos
Syntax error in tag 'gist' while parsing the following markup:
#{@markup}
Valid syntax:
for public gists: {% gist 1234567 %}
for private gists: {% gist user/1234567 %}
eos
end end
end end

View File

@ -14,7 +14,7 @@ module Jekyll
def initialize(tag_name, markup, tokens) def initialize(tag_name, markup, tokens)
super super
if markup.strip =~ SYNTAX if markup.strip =~ SYNTAX
@lang = $1 @lang = $1.downcase
@options = {} @options = {}
if defined?($2) && $2 != '' if defined?($2) && $2 != ''
$2.split.each do |opt| $2.split.each do |opt|

View File

@ -1,21 +1,33 @@
module Jekyll module Jekyll
module Tags module Tags
class IncludeTagError < StandardError
attr_accessor :path
def initialize(msg, path)
super(msg)
@path = path
end
end
class IncludeTag < Liquid::Tag class IncludeTag < Liquid::Tag
MATCHER = /([\w-]+)\s*=\s*(?:"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)'|([\w\.-]+))/ SYNTAX_EXAMPLE = "{% include file.ext param='value' param2='value' %}"
VALID_SYNTAX = /([\w-]+)\s*=\s*(?:"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)'|([\w\.-]+))/
INCLUDES_DIR = '_includes'
def initialize(tag_name, markup, tokens) def initialize(tag_name, markup, tokens)
super super
@file, @params = markup.strip.split(' ', 2); @file, @params = markup.strip.split(' ', 2);
validate_params if @params
end end
def parse_params(context) def parse_params(context)
validate_syntax
params = {} params = {}
markup = @params markup = @params
while match = MATCHER.match(markup) do while match = VALID_SYNTAX.match(markup) do
markup = markup[match.end(0)..-1] markup = markup[match.end(0)..-1]
value = if match[2] value = if match[2]
@ -31,55 +43,91 @@ module Jekyll
params params
end end
# ensure the entire markup string from start to end is valid syntax, and params are separated by spaces def validate_file_name
def validate_syntax if @file !~ /^[a-zA-Z0-9_\/\.-]+$/ || @file =~ /\.\// || @file =~ /\/\./
full_matcher = Regexp.compile('\A\s*(?:' + MATCHER.to_s + '(?=\s|\z)\s*)*\z') raise ArgumentError.new <<-eos
unless @params =~ full_matcher Invalid syntax for include tag. File contains invalid characters or sequences:
raise SyntaxError.new <<-eos
#{@file}
Valid syntax:
#{SYNTAX_EXAMPLE}
eos
end
end
def validate_params
full_valid_syntax = Regexp.compile('\A\s*(?:' + VALID_SYNTAX.to_s + '(?=\s|\z)\s*)*\z')
unless @params =~ full_valid_syntax
raise ArgumentError.new <<-eos
Invalid syntax for include tag: Invalid syntax for include tag:
#{@params} #{@params}
Valid syntax: Valid syntax:
{% include file.ext param='value' param2="value" %} #{SYNTAX_EXAMPLE}
eos eos
end end
end end
def render(context) # Grab file read opts in the context
includes_dir = File.join(context.registers[:site].source, '_includes') def file_read_opts(context)
context.registers[:site].file_read_opts
if error = validate_file(includes_dir)
return error
end end
source = File.read(File.join(includes_dir, @file)) def retrieve_variable(context)
partial = Liquid::Template.parse(source) if /\{\{([\w\-\.]+)\}\}/ =~ @file
raise ArgumentError.new("No variable #{$1} was found in include tag") if context[$1].nil?
@file = context[$1]
end
end
def render(context)
dir = File.join(context.registers[:site].source, INCLUDES_DIR)
validate_dir(dir, context.registers[:site].safe)
retrieve_variable(context)
validate_file_name
file = File.join(dir, @file)
validate_file(file, context.registers[:site].safe)
partial = Liquid::Template.parse(source(file, context))
context.stack do context.stack do
context['include'] = parse_params(context) if @params context['include'] = parse_params(context) if @params
partial.render(context) partial.render!(context)
end
rescue => e
raise IncludeTagError.new e.message, File.join(INCLUDES_DIR, @file)
end
def validate_dir(dir, safe)
if File.symlink?(dir) && safe
raise IOError.new "Includes directory '#{dir}' cannot be a symlink"
end end
end end
def validate_file(includes_dir) def validate_file(file, safe)
if File.symlink?(includes_dir)
return "Includes directory '#{includes_dir}' cannot be a symlink"
end
if @file !~ /^[a-zA-Z0-9_\/\.-]+$/ || @file =~ /\.\// || @file =~ /\/\./
return "Include file '#{@file}' contains invalid characters or sequences"
end
file = File.join(includes_dir, @file)
if !File.exists?(file) if !File.exists?(file)
return "Included file #{@file} not found in _includes directory" raise IOError.new "Included file '#{@file}' not found in '#{INCLUDES_DIR}' directory"
elsif File.symlink?(file) elsif File.symlink?(file) && safe
return "The included file '_includes/#{@file}' should not be a symlink" raise IOError.new "The included file '#{INCLUDES_DIR}/#{@file}' should not be a symlink"
end end
end end
def blank?
false
end
# This method allows to modify the file content by inheriting from the class.
def source(file, context)
File.read_with_options(file, file_read_opts(context))
end
end end
end end
end end

View File

@ -50,9 +50,11 @@ module Jekyll
end end
end end
puts "ERROR: post_url: \"#{@orig_post}\" could not be found" raise ArgumentError.new <<-eos
Could not find post "#{@orig_post}" in tag 'post_url'.
return "#" Make sure the post exists and the name is correct.
eos
end end
end end
end end

View File

@ -34,16 +34,16 @@ a:visited { color: #a0a; }
/* Home /* Home
/* /*
/*****************************************************************************/ /*****************************************************************************/
ul.posts { .posts {
list-style-type: none; list-style-type: none;
margin-bottom: 2em; margin-bottom: 2em;
} }
ul.posts li { .posts li {
line-height: 1.75em; line-height: 1.75em;
} }
ul.posts span { .posts span {
color: #aaa; color: #aaa;
font-family: Monaco, "Courier New", monospace; font-family: Monaco, "Courier New", monospace;
font-size: 80%; font-size: 80%;
@ -63,38 +63,38 @@ ul.posts span {
line-height: 1.5em; line-height: 1.5em;
} }
.site .header a { .header a {
font-weight: bold; font-weight: bold;
text-decoration: none; text-decoration: none;
} }
.site .header h1.title { .title {
display: inline-block; display: inline-block;
margin-bottom: 2em; margin-bottom: 2em;
} }
.site .header h1.title a { .title a {
color: #a00; color: #a00;
} }
.site .header h1.title a:hover { .title a:hover {
color: #000; color: #000;
} }
.site .header a.extra { .header a.extra {
color: #aaa; color: #aaa;
margin-left: 1em; margin-left: 1em;
} }
.site .header a.extra:hover { .header a.extra:hover {
color: #000; color: #000;
} }
.site .meta { .meta {
color: #aaa; color: #aaa;
} }
.site .footer { .footer {
font-size: 80%; font-size: 80%;
color: #666; color: #666;
border-top: 4px solid #eee; border-top: 4px solid #eee;
@ -102,22 +102,22 @@ ul.posts span {
overflow: hidden; overflow: hidden;
} }
.site .footer .contact { .footer .contact {
float: left; float: left;
margin-right: 3em; margin-right: 3em;
} }
.site .footer .contact a { .footer .contact a {
color: #8085C1; color: #8085C1;
} }
.site .footer .rss { .footer .rss {
margin-top: 1.1em; margin-top: 1.1em;
margin-right: -.2em; margin-right: -.2em;
float: right; float: right;
} }
.site .footer .rss img { .footer .rss img {
border: 0; border: 0;
} }

View File

@ -3,7 +3,7 @@
<h4>Getting Started</h4> <h4>Getting Started</h4>
{% include docs_ul.html items='home quickstart installation usage structure configuration' %} {% include docs_ul.html items='home quickstart installation usage structure configuration' %}
<h4>Your Content</h4> <h4>Your Content</h4>
{% include docs_ul.html items='frontmatter posts drafts pages variables migrations' %} {% include docs_ul.html items='frontmatter posts drafts pages variables datafiles migrations' %}
<h4>Customization</h4> <h4>Customization</h4>
{% include docs_ul.html items='templates permalinks pagination plugins extras' %} {% include docs_ul.html items='templates permalinks pagination plugins extras' %}
<h4>Deployment</h4> <h4>Deployment</h4>

View File

@ -5,7 +5,7 @@
{% include docs_option.html items='home quickstart installation usage structure configuration' %} {% include docs_option.html items='home quickstart installation usage structure configuration' %}
</optgroup> </optgroup>
<optgroup label="Your Content"> <optgroup label="Your Content">
{% include docs_option.html items='frontmatter posts drafts pages variables migrations' %} {% include docs_option.html items='frontmatter posts drafts pages variables datafiles migrations' %}
</optgroup> </optgroup>
<optgroup label="Customization"> <optgroup label="Customization">
{% include docs_option.html items='templates permalinks pagination plugins extras' %} {% include docs_option.html items='templates permalinks pagination plugins extras' %}

View File

@ -1,6 +1,6 @@
--- ---
layout: news_item layout: news_item
title: "Jekyll 1.2 Released" title: "Jekyll 1.2.0 Released"
date: "2013-09-06 22:02:41 -0400" date: "2013-09-06 22:02:41 -0400"
author: parkr author: parkr
version: 1.2.0 version: 1.2.0

View File

@ -0,0 +1,19 @@
---
layout: news_item
title: 'Jekyll 1.2.1 Released'
date: 2013-09-14 20:46:50 -0400
author: parkr
version: 1.2.1
categories: [release]
---
Quick turnover, anyone? A [recent incompatibility with Liquid
v2.5.2](https://github.com/mojombo/jekyll/pull/1525) produced a nasty bug in
which `include` tags were not rendered properly within `if` blocks.
This release also includes a better handling of detached servers (prints pid and
the command for killing the process). **Note**: the `--detach` flag and
`--watch` flags are presently incompatible in 1.2.x. Fix for that coming soon!
For a full list of the fixes in this release, check out [the change
log](/docs/history/)!

View File

@ -99,6 +99,22 @@ class="flag">flags</code> (specified on the command-line) that control them.
<p><code class="option">timezone: TIMEZONE</code></p> <p><code class="option">timezone: TIMEZONE</code></p>
</td> </td>
</tr> </tr>
<tr class='setting'>
<td>
<p class='name'><strong>Encoding</strong></p>
<p class="description">
Set the encoding of files by name. Only available for Ruby
1.9 or later).
The default value is nil, which use Ruby default,
<code>ASCII-8BIT</code>.
Available encoding for the ruby in use, can be shown by
command <code>ruby -e 'puts Encoding::list.join("\n")'</code>
</p>
</td>
<td class='align-center'>
<p><code class="option">encoding: ENCODING</code></p>
</td>
</tr>
<tr> <tr>
<td> <td>
<p class='name'><strong>Defaults</strong></p> <p class='name'><strong>Defaults</strong></p>
@ -309,6 +325,7 @@ include: ['.htaccess']
exclude: [] exclude: []
keep_files: ['.git','.svn'] keep_files: ['.git','.svn']
timezone: nil timezone: nil
encoding: nil
future: true future: true
show_drafts: nil show_drafts: nil

View File

@ -16,13 +16,19 @@ following in mind:
* If it's a brand new feature, make sure to create a new * If it's a brand new feature, make sure to create a new
[Cucumber](https://github.com/cucumber/cucumber/) feature and reuse steps [Cucumber](https://github.com/cucumber/cucumber/) feature and reuse steps
where appropriate. Also, whipping up some documentation in your fork's `site` where appropriate. Also, whipping up some documentation in your fork's `site`
directory would be appreciated, and once merged it will also appear in would be appreciated, and once merged it will be transferred over to the main
the next update of the main site. `site`, jekyllrb.com.
* If your contribution adds or changes any Jekyll behavior, make sure to update * If your contribution changes any Jekyll behavior, make sure to update the
the documentation. It lives in `site/docs`. If the docs are missing documentation. It lives in `site/docs`. If the docs are missing information,
information, please feel free to add it in. Great docs make a great project! please feel free to add it in. Great docs make a great project!
* Please follow the [GitHub Ruby Styleguide](https://github.com/styleguide/ruby) * Please follow the [GitHub Ruby Styleguide](https://github.com/styleguide/ruby)
when modifying Ruby code. when modifying Ruby code.
* Please do your best to submit **small pull requests**. The easier the proposed
change is to review, the more likely it will be merged.
* When submitting a pull request, please make judicious use of the pull request
body. A description of what changes were made, the motivations behind the
changes and [any tasks completed or left to complete](http://git.io/gfm-tasks)
will also speed up review time.
<div class="note warning"> <div class="note warning">
<h5>Contributions will not be accepted without tests</h5> <h5>Contributions will not be accepted without tests</h5>
@ -47,8 +53,8 @@ Before you start, run the tests and make sure that they pass (to confirm your
environment is configured properly): environment is configured properly):
{% highlight bash %} {% highlight bash %}
$ rake test $ bundle exec rake test
$ rake features $ bundle exec rake features
{% endhighlight %} {% endhighlight %}
Workflow Workflow
@ -79,8 +85,8 @@ git checkout -b my_awesome_feature
git push origin my_awesome_feature git push origin my_awesome_feature
{% endhighlight %} {% endhighlight %}
* Create a pull request against mojombo/jekyll and describe what your change * Create a pull request against mojombo/jekyll:master and describe what your
does and the why you think it should be merged. change does and the why you think it should be merged.
Updating Documentation Updating Documentation
---------------------- ----------------------

63
site/docs/datafiles.md Normal file
View File

@ -0,0 +1,63 @@
---
layout: docs
title: Data Files
prev_section: variables
next_section: migrations
permalink: /docs/datafiles/
---
In addition to the [built-in variables](../variables/) available from Jekyll,
you can specify your own custom data that can be accessed via the [Liquid
templating system](http://wiki.github.com/shopify/liquid/liquid-for-designers).
Jekyll supports loading data from [YAML](http://yaml.org/) files located in the
`_data` directory.
This powerful features allows you to avoid repetition in your templates and to
set site specific options without changing `_config.yml`.
Plugins/themes can also leverage Data Files to set configuration variables.
## The Data Folder
As explained on the [directory structure](../structure/) page, the `_data`
folder is where you can store additional data for Jekyll to use when generating
your site. These files must be YAML files (using either the `.yml` or `.yaml`
extension) and they will be accessible via `site.data`.
## Example: List of members
Here is a basic example of using Data Files to avoid copy-pasting large chunks of
code in your Jekyll templates:
In `_data/members.yml`:
{% highlight yaml %}
- name: Tom Preston-Werner
github: mojombo
- name: Parker Moore
github: parkr
- name: Liu Fengyun
github: liufengyun
{% endhighlight %}
This data can be accessed via `site.data.members` (notice that the filename
determines the variable name).
You can now render the list of members in a template:
{% highlight html %}
{% raw %}
<ul>
{% for member in site.data.members %}
<li>
<a href="https://github.com/{{ member.github }}">
{{ member.name }}
</a>
</li>
{% end %}
</ul>
{% endraw %}
{% endhighlight %}

View File

@ -5,6 +5,30 @@ permalink: /docs/history/
prev_section: contributing prev_section: contributing
--- ---
## 1.2.1 / 2013-09-14
### Minor Enhancements
- Print better messages for detached server. Mute output on detach. ([#1518]({{ site.repository }}/issues/1518))
- Disable reverse lookup when running `jekyll serve` ([#1363]({{ site.repository }}/issues/1363))
- Upgrade RedCarpet dependency to `~> 2.3.0` ([#1515]({{ site.repository }}/issues/1515))
- Upgrade to Liquid `>= 2.5.2, < 2.6` ([#1536]({{ site.repository }}/issues/1536))
### Bug Fixes
- Fix file discrepancy in gemspec ([#1522]({{ site.repository }}/issues/1522))
- Force rendering of Include tag ([#1525]({{ site.repository }}/issues/1525))
### Development Fixes
- Add a rake task to generate a new release post ([#1404]({{ site.repository }}/issues/1404))
- Mute LSI output in tests ([#1531]({{ site.repository }}/issues/1531))
- Update contributor documentation ([#1537]({{ site.repository }}/issues/1537))
### Site Enhancements
- Fix a couple of validation errors on the site ([#1511]({{ site.repository }}/issues/1511))
- Make navigation menus reusable ([#1507]({{ site.repository }}/issues/1507))
- Fix link to History page from Release v1.2.0 notes post.
- Fix markup in History file for command line options ([#1512]({{ site.repository }}/issues/1512))
- Expand 1.2 release post title to 1.2.0 ([#1516]({{ site.repository }}/issues/1516))
## 1.2.0 / 2013-09-06 ## 1.2.0 / 2013-09-06
### Major Enhancements ### Major Enhancements
@ -15,7 +39,7 @@ prev_section: contributing
- Catch and fix invalid `paginate` values ([#1390]({{ site.repository }}/issues/1390)) - Catch and fix invalid `paginate` values ([#1390]({{ site.repository }}/issues/1390))
- Remove superfluous `div.container` from the default html template for - Remove superfluous `div.container` from the default html template for
`jekyll new` ([#1315]({{ site.repository }}/issues/1315)) `jekyll new` ([#1315]({{ site.repository }}/issues/1315))
- Add -D short-form switch for the drafts option ([#1394]({{ site.repository }}/issues/1394)) - Add `-D` short-form switch for the drafts option ([#1394]({{ site.repository }}/issues/1394))
- Update the links in the site template for Twitter and GitHub ([#1400]({{ site.repository }}/issues/1400)) - Update the links in the site template for Twitter and GitHub ([#1400]({{ site.repository }}/issues/1400))
- Update dummy email address to example.com domain ([#1408]({{ site.repository }}/issues/1408)) - Update dummy email address to example.com domain ([#1408]({{ site.repository }}/issues/1408))
- Update normalize.css to v2.1.2 and minify; add rake task to update - Update normalize.css to v2.1.2 and minify; add rake task to update
@ -65,7 +89,7 @@ prev_section: contributing
- Fix markup for the Kramdown options ([#1445]({{ site.repository }}/issues/1445)) - Fix markup for the Kramdown options ([#1445]({{ site.repository }}/issues/1445))
- Fix typos in the History file ([#1454]({{ site.repository }}/issues/1454)) - Fix typos in the History file ([#1454]({{ site.repository }}/issues/1454))
- Add trailing slash to site's post URL ([#1462]({{ site.repository }}/issues/1462)) - Add trailing slash to site's post URL ([#1462]({{ site.repository }}/issues/1462))
- Clarify that --config will take multiple files ([#1474]({{ site.repository }}/issues/1474)) - Clarify that `--config` will take multiple files ([#1474]({{ site.repository }}/issues/1474))
- Fix docs/templates.md private gist example ([#1477]({{ site.repository }}/issues/1477)) - Fix docs/templates.md private gist example ([#1477]({{ site.repository }}/issues/1477))
- Use `site.repository` for Jekyll's GitHub URL ([#1463]({{ site.repository }}/issues/1463)) - Use `site.repository` for Jekyll's GitHub URL ([#1463]({{ site.repository }}/issues/1463))
- Add `jekyll-pageless-redirects` to list of third-party plugins ([#1486]({{ site.repository }}/issues/1486)) - Add `jekyll-pageless-redirects` to list of third-party plugins ([#1486]({{ site.repository }}/issues/1486))
@ -302,7 +326,7 @@ prev_section: contributing
- Allow symlinked files in unsafe mode ([#824]({{ site.repository }}/issues/824)) - Allow symlinked files in unsafe mode ([#824]({{ site.repository }}/issues/824))
- Add 'gist' Liquid tag to core ([#822]({{ site.repository }}/issues/822), [#861]({{ site.repository }}/issues/861)) - Add 'gist' Liquid tag to core ([#822]({{ site.repository }}/issues/822), [#861]({{ site.repository }}/issues/861))
- New format of Jekyll output ([#795]({{ site.repository }}/issues/795)) - New format of Jekyll output ([#795]({{ site.repository }}/issues/795))
- Reinstate --limit_posts and --future switches ([#788]({{ site.repository }}/issues/788)) - Reinstate `--limit_posts` and `--future` switches ([#788]({{ site.repository }}/issues/788))
- Remove ambiguity from command descriptions ([#815]({{ site.repository }}/issues/815)) - Remove ambiguity from command descriptions ([#815]({{ site.repository }}/issues/815))
- Fix SafeYAML Warnings ([#807]({{ site.repository }}/issues/807)) - Fix SafeYAML Warnings ([#807]({{ site.repository }}/issues/807))
- Relaxed Kramdown version to 0.14 ([#808]({{ site.repository }}/issues/808)) - Relaxed Kramdown version to 0.14 ([#808]({{ site.repository }}/issues/808))
@ -325,7 +349,7 @@ prev_section: contributing
- Catch all exceptions, not just StandardError descendents ([#1007]({{ site.repository }}/issues/1007)) - Catch all exceptions, not just StandardError descendents ([#1007]({{ site.repository }}/issues/1007))
- Bullet-proof limit_posts option ([#1004]({{ site.repository }}/issues/1004)) - Bullet-proof limit_posts option ([#1004]({{ site.repository }}/issues/1004))
- Read in YAML as UTF-8 to accept non-ASCII chars ([#836]({{ site.repository }}/issues/836)) - Read in YAML as UTF-8 to accept non-ASCII chars ([#836]({{ site.repository }}/issues/836))
- Fix the CLI option --plugins to actually accept dirs and files ([#993]({{ site.repository }}/issues/993)) - Fix the CLI option `--plugins` to actually accept dirs and files ([#993]({{ site.repository }}/issues/993))
- Allow 'excerpt' in YAML Front-Matter to override the extracted excerpt ([#946]({{ site.repository }}/issues/946)) - Allow 'excerpt' in YAML Front-Matter to override the extracted excerpt ([#946]({{ site.repository }}/issues/946))
- Fix cascade problem with site.baseurl, site.port and site.host. ([#935]({{ site.repository }}/issues/935)) - Fix cascade problem with site.baseurl, site.port and site.host. ([#935]({{ site.repository }}/issues/935))
- Filter out directories with valid post names ([#875]({{ site.repository }}/issues/875)) - Filter out directories with valid post names ([#875]({{ site.repository }}/issues/875))

View File

@ -46,6 +46,16 @@ installing Jekyll, check out the [troubleshooting](../troubleshooting/) page or
[report an issue]({{ site.repository }}/issues/new) so the Jekyll [report an issue]({{ site.repository }}/issues/new) so the Jekyll
community can improve the experience for everyone. community can improve the experience for everyone.
<div class="note info">
<h5>Installing Xcode Command-Line Tools</h5>
<p>
If you run into issues installing Jekyll's dependencies which make use of
native extensions and are using Mac OS X, you will need to install Xcode
and the Command-Line Tools it ships with. Download in
<code>Preferences &#8594; Downloads &#8594; Components</code>.
</p>
</div>
## Optional Extras ## Optional Extras
There are a number of (optional) extra features that Jekyll supports that you There are a number of (optional) extra features that Jekyll supports that you

View File

@ -1,7 +1,7 @@
--- ---
layout: docs layout: docs
title: Blog migrations title: Blog migrations
prev_section: variables prev_section: datafiles
next_section: templates next_section: templates
permalink: /docs/migrations/ permalink: /docs/migrations/
--- ---
@ -24,6 +24,15 @@ Jekyll's standard command line interface.
$ gem install jekyll-import --pre $ gem install jekyll-import --pre
{% endhighlight %} {% endhighlight %}
<div class="note warning">
<h5>Jekyll-import requires you to manually install some dependencies.</h5>
<p markdown="1">If you are importing your blog from Drupal 6,7, Joomla,
Mephisto, Movable Type, Textpattern, or Typo (with mysql db), you need to install
`mysql` and `sequel` gems. If you are importing from a WordPress database, you
need to install `mysql2` and `sequel` gems, and if you are importing from Enki
or Typo (with postgresql db) you need to install `pg` and `sequel` gems.</p>
</div>
You should now be all set to run the importers below. If you ever get stuck, you You should now be all set to run the importers below. If you ever get stuck, you
can see help for each importer: can see help for each importer:
@ -74,7 +83,7 @@ here's how:
{% highlight bash %} {% highlight bash %}
$ ruby -rubygems -e 'require "jekyll/jekyll-import/wordpress"; $ ruby -rubygems -e 'require "jekyll/jekyll-import/wordpress";
JekyllImport::WordPress.process("database", "user", "pass")' JekyllImport::WordPress.process({:dbname => "database", :user => "user", :pass => "pass"})'
{% endhighlight %} {% endhighlight %}
If you are using Webfaction and have to set up an [SSH If you are using Webfaction and have to set up an [SSH
@ -85,7 +94,7 @@ authentication system:
{% highlight bash %} {% highlight bash %}
$ ruby -rubygems -e 'require "jekyll/jekyll-import/wordpress"; $ ruby -rubygems -e 'require "jekyll/jekyll-import/wordpress";
JekyllImport::WordPress.process("database", "user", "pass", "127.0.0.1")' JekyllImport::WordPress.process({:host => "127.0.0.1", :dbname => "database", :user => "user", :pass => "pass"})'
{% endhighlight %} {% endhighlight %}
### Further WordPress migration alternatives ### Further WordPress migration alternatives

View File

@ -182,51 +182,30 @@ page with links to all but the current page.
{% highlight html %} {% highlight html %}
{% raw %} {% raw %}
<div id="post-pagination" class="pagination"> {% if paginator.total_pages > 1 %}
<div class="pagination">
{% if paginator.previous_page %} {% if paginator.previous_page %}
<p class="previous"> <a href="{{ paginator.previous_page_path | prepend: site.baseurl | replace: '//', '/' }}">&laquo; Prev</a>
{% if paginator.previous_page == 1 %}
<a href="/">Previous</a>
{% else %} {% else %}
<a href="{{ paginator.previous_page_path }}">Previous</a> <span>&laquo; Prev</span>
{% endif %}
</p>
{% else %}
<p class="previous disabled">
<span>Previous</span>
</p>
{% endif %} {% endif %}
<ul class="pages"> {% for page in (1..paginator.total_pages) %}
<li class="page"> {% if page == paginator.page %}
{% if paginator.page == 1 %} <em>{{ page }}</em>
<span class="current-page">1</span> {% elsif page == 1 %}
<a href="{{ '/index.html' | prepend: site.baseurl | replace: '//', '/' }}">{{ page }}</a>
{% else %} {% else %}
<a href="/">1</a> <a href="{{ site.paginate_path | prepend: site.baseurl | replace: '//', '/' | replace: ':num', page }}">{{ page }}</a>
{% endif %} {% endif %}
</li>
{% for count in (2..paginator.total_pages) %}
<li class="page">
{% if count == paginator.page %}
<span class="current-page">{{ count }}</span>
{% else %}
<a href="/page{{ count }}">{{ count }}</a>
{% endif %}
</li>
{% endfor %} {% endfor %}
</ul>
{% if paginator.next_page %} {% if paginator.next_page %}
<p class="next"> <a href="{{ paginator.next_page_path | prepend: site.baseurl | replace: '//', '/' }}">Next &raquo;</a>
<a href="{{ paginator.next_page_path }}">Next</a>
</p>
{% else %} {% else %}
<p class="next disabled"> <span>Next &raquo;</span>
<span>Next</span>
</p>
{% endif %} {% endif %}
</div> </div>
{% endif %}
{% endraw %} {% endraw %}
{% endhighlight %} {% endhighlight %}

View File

@ -38,7 +38,45 @@ In general, plugins you make will fall into one of three categories:
## Generators ## Generators
You can create a generator when you need Jekyll to create additional content You can create a generator when you need Jekyll to create additional content
based on your own rules. For example, a generator might look like this: based on your own rules.
A generator is a subclass of `Jekyll::Generator` that defines a `generate`
method, which receives an instance of
[`Jekyll::Site`]({{ site.repository }}/blob/master/lib/jekyll/site.rb).
Generation is triggered for its side-effects, the return value of `generate` is
ignored. Jekyll does not assume any particular side-effect to happen, it just
runs the method.
Generators run after Jekyll has made an inventory of the existing content, and
before the site is generated. Pages with YAML front-matters are stored as
instances of
[`Jekyll::Page`]({{ site.repository }}/blob/master/lib/jekyll/page.rb)
and are available via `site.pages`. Static files become instances of
[`Jekyll::StaticFile`]({{ site.repository }}/blob/master/lib/jekyll/static_file.rb)
and are available via `site.static_files`. See
[`Jekyll::Site`]({{ site.repository }}/blob/master/lib/jekyll/site.rb)
for more details.
For instance, a generator can inject values computed at build time for template
variables. In the following example the template `reading.html` has two
variables `ongoing` and `done` that we fill in the generator:
{% highlight ruby %}
module Reading
class Generator < Jekyll::Generator
def generate(site)
ongoing, done = Book.all.partition(&:ongoing?)
reading = site.pages.detect {|page| page.name == 'reading.html'}
reading.data['ongoing'] = ongoing
reading.data['done'] = done
end
end
end
{% endhighlight %}
This is a more complex generator that generates new pages:
{% highlight ruby %} {% highlight ruby %}
module Jekyll module Jekyll
@ -95,7 +133,7 @@ Generators are only required to implement one method:
<p><code>generate</code></p> <p><code>generate</code></p>
</td> </td>
<td> <td>
<p>String output of the content being generated.</p> <p>Generates content as a side-effect.</p>
</td> </td>
</tr> </tr>
</tbody> </tbody>
@ -430,6 +468,7 @@ You can find a few useful plugins at the following locations:
- [Jekyll Image Tag](https://github.com/robwierzbowski/jekyll-image-tag): Better images for Jekyll. Save image presets, generate resized images, and add classes, alt text, and other attributes. - [Jekyll Image Tag](https://github.com/robwierzbowski/jekyll-image-tag): Better images for Jekyll. Save image presets, generate resized images, and add classes, alt text, and other attributes.
- [Ditaa Tag](https://github.com/matze/jekyll-ditaa) by [matze](https://github.com/matze): Renders ASCII diagram art into PNG images and inserts a figure tag. - [Ditaa Tag](https://github.com/matze/jekyll-ditaa) by [matze](https://github.com/matze): Renders ASCII diagram art into PNG images and inserts a figure tag.
- [Good Include](https://github.com/penibelst/jekyll-good-include) by [Anatol Broder](http://penibelst.de/): Strips newlines and whitespaces from the end of include files before processing. - [Good Include](https://github.com/penibelst/jekyll-good-include) by [Anatol Broder](http://penibelst.de/): Strips newlines and whitespaces from the end of include files before processing.
- [Jekyll Suggested Tweet](https://github.com/davidensinger/jekyll-suggested-tweet) by [David Ensinger](https://github.com/davidensinger/): A Liquid tag for Jekyll that allows for the embedding of suggested tweets via Twitters Web Intents API.
#### Collections #### Collections

View File

@ -31,6 +31,8 @@ A basic Jekyll site usually looks something like this:
├── _posts ├── _posts
| ├── 2007-10-29-why-every-programmer-should-play-nethack.textile | ├── 2007-10-29-why-every-programmer-should-play-nethack.textile
| └── 2009-04-26-barcamp-boston-4-roundup.textile | └── 2009-04-26-barcamp-boston-4-roundup.textile
├── _data
| └── members.yml
├── _site ├── _site
└── index.html └── index.html
{% endhighlight %} {% endhighlight %}
@ -121,6 +123,21 @@ An overview of what each of these does:
</p> </p>
</td> </td>
</tr> </tr>
<tr>
<td>
<p><code>_data</code></p>
</td>
<td>
<p>
Well-formatted site data should be placed here. The jekyll engine will
autoload all yaml files (ends with <code>.yml</code> or <code>.yaml</code>)
in this directory. If there's a file <code>members.yml</code> under the directory,
then you can access contents of the file through <code>site.data.members</code>.
</p>
</td>
</tr>
<tr> <tr>
<td> <td>
<p><code>_site</code></p> <p><code>_site</code></p>

View File

@ -7,9 +7,9 @@ permalink: /docs/templates/
--- ---
Jekyll uses the [Liquid](http://wiki.shopify.com/Liquid) templating language to Jekyll uses the [Liquid](http://wiki.shopify.com/Liquid) templating language to
process templates. All of the [standard Liquid tags and process templates. All of the standard Liquid [tags](http://wiki.shopify.com/Logic) and
filters](http://wiki.github.com/shopify/liquid/liquid-for-designers) are [filters](http://wiki.shopify.com/Filters) are
supported, Jekyll even adds a few handy filters and tags of its own to make supported. Jekyll even adds a few handy filters and tags of its own to make
common tasks easier. common tasks easier.
## Filters ## Filters
@ -192,6 +192,19 @@ Jekyll expects all include files to be placed in an `_includes` directory at the
root of your source directory. This will embed the contents of root of your source directory. This will embed the contents of
`<source>/_includes/footer.html` into the calling file. `<source>/_includes/footer.html` into the calling file.
<div class="note">
<h5>ProTip™: Use variables as file name</h5>
<p>
The name of the file you wish to embed can be literal (as in the example above),
or you can use a variable, using liquid-like variable syntax as in
<code>{% raw %}{% include {{my_variable}} %}{% endraw %}</code>.
Note that unlike usual liquid variable syntax, you cannot have spaces inside the curly braces.
</p>
</div>
You can also pass parameters to an include: You can also pass parameters to an include:
{% highlight ruby %} {% highlight ruby %}

View File

@ -2,14 +2,14 @@
layout: docs layout: docs
title: Variables title: Variables
prev_section: pages prev_section: pages
next_section: migrations next_section: datafiles
permalink: /docs/variables/ permalink: /docs/variables/
--- ---
Jekyll traverses your site looking for files to process. Any files with [YAML Jekyll traverses your site looking for files to process. Any files with [YAML
Front Matter](../frontmatter/) are subject to processing. For each of these Front Matter](../frontmatter/) are subject to processing. For each of these
files, Jekyll makes a variety of data available via the [Liquid templating files, Jekyll makes a variety of data available via the [Liquid templating
system](http://wiki.github.com/shopify/liquid/liquid-for-designers). The system](http://wiki.shopify.com/Liquid). The
following is a reference of the available data. following is a reference of the available data.
## Global Variables ## Global Variables

View File

@ -1,7 +1,10 @@
if RUBY_VERSION > '1.9' && ENV["COVERAGE"] == "true" if RUBY_VERSION > '1.9'
require 'simplecov' require 'simplecov'
require 'simplecov-gem-adapter' require 'simplecov-gem-adapter'
SimpleCov.start('gem') SimpleCov.start('gem')
require 'coveralls'
Coveralls.wear_merged!
end end
require 'rubygems' require 'rubygems'

View File

@ -0,0 +1,2 @@
- java
- ruby

View File

@ -0,0 +1,7 @@
- name: Jack
age: 27
blog: http://example.com/jack
- name: John
age: 32
blog: http://example.com/john

View File

@ -0,0 +1 @@
../products.yml

View File

@ -0,0 +1 @@
<<< {{ content }} >>>

4
test/source/products.yml Normal file
View File

@ -0,0 +1,4 @@
- name: sugar
price: 5.3
- name: salt
price: 2.5

View File

@ -0,0 +1 @@
../_data

View File

@ -40,7 +40,7 @@ class TestConvertible < Test::Unit::TestCase
should "not parse if there is encoding error in file" do should "not parse if there is encoding error in file" do
name = 'broken_front_matter3.erb' name = 'broken_front_matter3.erb'
out = capture_stdout do out = capture_stdout do
ret = @convertible.read_yaml(@base, name) ret = @convertible.read_yaml(@base, name, :encoding => 'utf-8')
assert_equal({}, ret) assert_equal({}, ret)
end end
assert_match(/invalid byte sequence in UTF-8/, out) assert_match(/invalid byte sequence in UTF-8/, out)

View File

@ -29,6 +29,7 @@ class TestRelatedPosts < Test::Unit::TestCase
'destination' => dest_dir, 'destination' => dest_dir,
'lsi' => true}) 'lsi' => true})
end end
any_instance_of(Jekyll::RelatedPosts) { |i| stub(i).display }
@site = Site.new(Jekyll.configuration) @site = Site.new(Jekyll.configuration)
end end

View File

@ -156,7 +156,7 @@ class TestSite < Test::Unit::TestCase
should "read layouts" do should "read layouts" do
@site.read_layouts @site.read_layouts
assert_equal ["default", "simple"].sort, @site.layouts.keys.sort assert_equal ["default", "simple", "post/simple"].sort, @site.layouts.keys.sort
end end
should "read posts" do should "read posts" do
@ -335,5 +335,62 @@ class TestSite < Test::Unit::TestCase
end end
end end
context 'data directory' do
should 'auto load yaml files' do
site = Site.new(Jekyll.configuration)
site.process
file_content = YAML.safe_load_file(File.join(source_dir, '_data', 'members.yaml'))
assert_equal site.data['members'], file_content
assert_equal site.site_payload['site']['data']['members'], file_content
end
should 'auto load yml files' do
site = Site.new(Jekyll.configuration)
site.process
file_content = YAML.safe_load_file(File.join(source_dir, '_data', 'languages.yml'))
assert_equal site.data['languages'], file_content
assert_equal site.site_payload['site']['data']['languages'], file_content
end
should "load symlink files in unsafe mode" do
site = Site.new(Jekyll.configuration.merge({'safe' => false}))
site.process
file_content = YAML.safe_load_file(File.join(source_dir, '_data', 'products.yml'))
assert_equal site.data['products'], file_content
assert_equal site.site_payload['site']['data']['products'], file_content
end
should "not load symlink files in safe mode" do
site = Site.new(Jekyll.configuration.merge({'safe' => true}))
site.process
assert_nil site.data['products']
assert_nil site.site_payload['site']['data']['products']
end
should "load symlink directory in unsafe mode" do
site = Site.new(Jekyll.configuration.merge({'safe' => false, 'data_source' => File.join('symlink-test', '_data')}))
site.process
assert_not_nil site.data['products']
assert_not_nil site.data['languages']
assert_not_nil site.data['members']
end
should "not load symlink directory in safe mode" do
site = Site.new(Jekyll.configuration.merge({'safe' => true, 'data_source' => File.join('symlink-test', '_data')}))
site.process
assert_nil site.data['products']
assert_nil site.data['languages']
assert_nil site.data['members']
end
end
end end
end end

View File

@ -19,7 +19,7 @@ class TestTags < Test::Unit::TestCase
payload = { "pygments_prefix" => @converter.pygments_prefix, payload = { "pygments_prefix" => @converter.pygments_prefix,
"pygments_suffix" => @converter.pygments_suffix } "pygments_suffix" => @converter.pygments_suffix }
@result = Liquid::Template.parse(content).render(payload, info) @result = Liquid::Template.parse(content).render!(payload, info)
@result = @converter.convert(@result) @result = @converter.convert(@result)
end end
@ -69,6 +69,9 @@ CONTENT
tag = Jekyll::Tags::HighlightBlock.new('highlight', 'ruby linenos=table cssclass=hl', ["test", "{% endhighlight %}", "\n"]) tag = Jekyll::Tags::HighlightBlock.new('highlight', 'ruby linenos=table cssclass=hl', ["test", "{% endhighlight %}", "\n"])
assert_equal({ 'cssclass' => 'hl', 'linenos' => 'table' }, tag.instance_variable_get(:@options)) assert_equal({ 'cssclass' => 'hl', 'linenos' => 'table' }, tag.instance_variable_get(:@options))
tag = Jekyll::Tags::HighlightBlock.new('highlight', 'Ruby ', ["test", "{% endhighlight %}", "\n"])
assert_equal "ruby", tag.instance_variable_get(:@lang), "lexers should be case insensitive"
end end
end end
@ -273,8 +276,7 @@ CONTENT
end end
end end
context "when invalid" do should "raise ArgumentError when invalid" do
setup do
@gist = "mattr-24081a1d93d2898ecf0f" @gist = "mattr-24081a1d93d2898ecf0f"
@filename = "myfile.ext" @filename = "myfile.ext"
content = <<CONTENT content = <<CONTENT
@ -284,11 +286,9 @@ CONTENT
{% gist #{@gist} #{@filename} %} {% gist #{@gist} #{@filename} %}
CONTENT CONTENT
create_post(content, {'permalink' => 'pretty', 'source' => source_dir, 'destination' => dest_dir, 'read_posts' => true})
end
should "write script tag with specific file in gist" do assert_raise ArgumentError do
assert_match "Error parsing gist id", @result create_post(content, {'permalink' => 'pretty', 'source' => source_dir, 'destination' => dest_dir, 'read_posts' => true})
end end
end end
end end
@ -313,7 +313,7 @@ CONTENT
end end
context "with blank gist id" do context "with blank gist id" do
setup do should "raise ArgumentError" do
content = <<CONTENT content = <<CONTENT
--- ---
title: My Cool Gist title: My Cool Gist
@ -321,16 +321,15 @@ title: My Cool Gist
{% gist %} {% gist %}
CONTENT CONTENT
assert_raise ArgumentError do
create_post(content, {'permalink' => 'pretty', 'source' => source_dir, 'destination' => dest_dir, 'read_posts' => true}) create_post(content, {'permalink' => 'pretty', 'source' => source_dir, 'destination' => dest_dir, 'read_posts' => true})
end end
should "output error message" do
assert_match "Error parsing gist id", @result
end end
end end
context "with invalid gist id" do context "with invalid gist id" do
setup do should "raise ArgumentError" do
invalid_gist = 'invalid' invalid_gist = 'invalid'
content = <<CONTENT content = <<CONTENT
--- ---
@ -339,11 +338,10 @@ title: My Cool Gist
{% gist #{invalid_gist} %} {% gist #{invalid_gist} %}
CONTENT CONTENT
assert_raise ArgumentError do
create_post(content, {'permalink' => 'pretty', 'source' => source_dir, 'destination' => dest_dir, 'read_posts' => true}) create_post(content, {'permalink' => 'pretty', 'source' => source_dir, 'destination' => dest_dir, 'read_posts' => true})
end end
should "output error message" do
assert_match "Error parsing gist id", @result
end end
end end
end end
@ -373,7 +371,7 @@ CONTENT
end end
context "with invalid parameter syntax" do context "with invalid parameter syntax" do
should "throw a SyntaxError" do should "throw a ArgumentError" do
content = <<CONTENT content = <<CONTENT
--- ---
title: Invalid parameter syntax title: Invalid parameter syntax
@ -381,7 +379,7 @@ title: Invalid parameter syntax
{% include params.html param s="value" %} {% include params.html param s="value" %}
CONTENT CONTENT
assert_raise SyntaxError, 'Did not raise exception on invalid "include" syntax' do assert_raise ArgumentError, 'Did not raise exception on invalid "include" syntax' do
create_post(content, {'permalink' => 'pretty', 'source' => source_dir, 'destination' => dest_dir, 'read_posts' => true}) create_post(content, {'permalink' => 'pretty', 'source' => source_dir, 'destination' => dest_dir, 'read_posts' => true})
end end
@ -392,7 +390,7 @@ title: Invalid parameter syntax
{% include params.html params="value %} {% include params.html params="value %}
CONTENT CONTENT
assert_raise SyntaxError, 'Did not raise exception on invalid "include" syntax' do assert_raise ArgumentError, 'Did not raise exception on invalid "include" syntax' do
create_post(content, {'permalink' => 'pretty', 'source' => source_dir, 'destination' => dest_dir, 'read_posts' => true}) create_post(content, {'permalink' => 'pretty', 'source' => source_dir, 'destination' => dest_dir, 'read_posts' => true})
end end
end end
@ -436,5 +434,22 @@ CONTENT
assert_match "<span id='include-param' />", @result assert_match "<span id='include-param' />", @result
end end
end end
context "without parameters within if statement" do
setup do
content = <<CONTENT
---
title: without parameters within if statement
---
{% if true %}{% include params.html %}{% endif %}
CONTENT
create_post(content, {'permalink' => 'pretty', 'source' => source_dir, 'destination' => dest_dir, 'read_posts' => true})
end
should "include file with empty parameters within if statement" do
assert_match "<span id='include-param' />", @result
end
end
end end
end end