Merge pull request #2 from jekyll/master

Get latest master
This commit is contained in:
Eduardo Bouças 2015-03-12 21:58:39 +00:00
commit d3e23c2fae
216 changed files with 3052 additions and 1349 deletions

5
.gitignore vendored
View File

@ -12,5 +12,8 @@ gh-pages/
site/_site/ site/_site/
coverage coverage
.ruby-version .ruby-version
.ruby-gemset
.sass-cache .sass-cache
tmp/stackprof-* tmp/*
.jekyll-metadata
/vendor

View File

@ -2,9 +2,9 @@ language: ruby
cache: bundler cache: bundler
sudo: false sudo: false
rvm: rvm:
- 2.2
- 2.1 - 2.1
- 2.0 - 2.0
- 1.9.3
env: env:
matrix: matrix:
- TEST_SUITE=test - TEST_SUITE=test

View File

@ -4,6 +4,7 @@ Contribute
So you've got an awesome idea to throw into Jekyll. Great! Please keep the So you've got an awesome idea to throw into Jekyll. Great! Please keep the
following in mind: following in mind:
* **Use https://talk.jekyllrb.com for non-technical or indirect Jekyll questions that are not bugs.**
* **Contributions will not be accepted without tests or necessary documentation updates.** * **Contributions will not be accepted without tests or necessary documentation updates.**
* If you're creating a small fix or patch to an existing feature, just a simple * If you're creating a small fix or patch to an existing feature, just a simple
test will do. Please stay in the confines of the current test suite and use test will do. Please stay in the confines of the current test suite and use

33
Gemfile
View File

@ -1,7 +1,40 @@
source 'https://rubygems.org' source 'https://rubygems.org'
gemspec gemspec
gem 'pygments.rb', '~> 0.6.0'
gem 'redcarpet', '~> 3.1'
gem 'toml', '~> 0.1.0'
gem 'jekyll-paginate', '~> 1.0'
gem 'jekyll-gist', '~> 1.0'
gem 'jekyll-coffeescript', '~> 1.0'
gem 'classifier-reborn', '~> 2.0'
gem 'rake', '~> 10.1'
gem 'rdoc', '~> 3.11'
gem 'redgreen', '~> 1.2'
gem 'shoulda', '~> 3.5'
gem 'cucumber', '1.3.18'
gem 'maruku', '~> 0.7.0'
gem 'rdiscount', '~> 2.0'
gem 'launchy', '~> 2.3'
gem 'simplecov', '~> 0.9'
gem 'mime-types', '~> 1.5'
gem 'activesupport', '~> 3.2.13'
gem 'jekyll_test_plugin'
gem 'jekyll_test_plugin_malicious'
gem 'liquid-c', '~> 3.0'
gem 'minitest'
gem 'minitest-reporters'
gem 'minitest-profile'
gem 'test-unit' if RUBY_PLATFORM =~ /cygwin/ || RUBY_VERSION.start_with?("2.2")
gem 'rspec-mocks'
if ENV['BENCHMARK'] if ENV['BENCHMARK']
gem 'rbtrace' gem 'rbtrace'
gem 'stackprof' gem 'stackprof'
gem 'benchmark-ips'
end
if ENV['PROOF']
gem 'html-proofer', '~> 2.0'
end end

View File

@ -2,25 +2,172 @@
### Major Enhancements ### Major Enhancements
* Incremental regeneration (#3116)
* Drop support for Ruby 1.9.3. (#3235)
* Upgrade to Liquid 3.0.0 (#3002)
* Support Ruby v2.2 (#3234)
* Support RDiscount 2 (#2767)
* Remove most runtime deps (#3323)
* Move to Rouge as default highlighter (#3323)
* Mimic GitHub Pages `.html` extension stripping behavior in WEBrick (#3452)
* Always include file extension on output files (#3490)
* Improved permalinks for pages and collections (#3538)
### Minor Enhancements ### Minor Enhancements
* Sort static files just once, and call `site_payload` once for all collections (#3204)
* Separate `jekyll docs` and optimize external gem handling (#3241)
* Improve `Site#getConverterImpl` and call it `Site#find_converter_instance` (#3240)
* Use relative path for `path` Liquid variable in Documents for consistency (#2908)
* Generalize `Utils#slugify` for any scripts (#3047)
* Added basic microdata to post template in site template (#3189)
* Store log messages in an array of messages. (#3244)
* Allow collection documents to override `output` property in front matter (#3172)
* Keep file modification times between builds for static files (#3220)
* Only downcase mixed-case categories for the URL (#2571)
* Added per post `excerpt_separator` functionality (#3274)
* Allow collections YAML to end with three dots (#3134)
* Add mode parameter to `slugify` Liquid filter (#2918)
* Perf: `Markdown#matches` should avoid regexp (#3321)
* Perf: Use frozen regular expressions for `Utils#slugify` (#3321)
* Split off Textile support into jekyll-textile-converter (#3319)
* Improve the navigation menu alignment in the site template on small
screens (#3331)
* Show the regeneration time after the initial generation (#3378)
* Site template: Switch default font to Helvetica Neue (#3376)
* Make the `include` tag a teensy bit faster. (#3391)
* Add `pkill -f jekyll` to ways to kill. (#3397)
* Site template: collapsed, variable-driven font declaration (#3360)
* Site template: Don't always show the scrollbar in code blocks (#3419)
* Site template: Remove undefined `text` class from `p` element (#3440)
* Site template: Optimize text rendering for legibility (#3382)
* Add `draft?` method to identify if Post is a Draft & expose to Liquid (#3456)
* Write regeneration metadata even on full rebuild (#3464)
* Perf: Use `String#end_with?("/")` instead of regexp when checking paths (#3516)
* Docs: document 'ordinal' built-in permalink style (#3532)
* Upgrade liquid-c to 3.x (#3531)
* Use consistent syntax for deprecation warning (#3535)
* Added build --destination and --source flags (#3418)
* Site template: remove unused `page.meta` attribute (#3537)
* Improve the error message when sorting null objects (#3520)
### Bug Fixes
* Make permalink parsing consistent with pages (#3014)
* `time()`pre-filter method should accept a `Date` object (#3299)
* Remove unneeded end tag for `link` in site template (#3236)
* Kramdown: Use `enable_coderay` key instead of `use_coderay` (#3237)
* Unescape `Document` output path (#2924)
* Fix nav items alignment when on multiple rows (#3264)
* Highlight: Only Strip Newlines/Carriage Returns, not Spaces (#3278)
* Find variables in front matter defaults by searching with relative file path. (#2774)
* Allow variables (e.g `:categories`) in YAML front matter permalinks (#3320)
* Handle nil URL placeholders in permalinks (#3325)
* Template: Fix nav items alignment when in "burger" mode (#3329)
* Template: Remove `!important` from nav SCSS introduced in #3329 (#3375)
* The `:title` URL placeholder for collections should be the filename slug. (#3383)
* Trim the generate time diff to just 3 places past the decimal place (#3415)
* The highlight tag should only clip the newlines before and after the *entire* block, not in between (#3401)
* highlight: fix problem with linenos and rouge. (#3436)
* `Site#read_data_file`: read CSV's with proper file encoding (#3455)
* Ignore `.jekyll-metadata` in site template (#3496)
* Template: Point documentation link to the documentation pages (#3502)
* Removed the trailing slash from the example `/blog` baseurl comment (#3485)
### Development Fixes
* Improve the grammar in the documentation (#3233)
* Update the LICENSE text to match the MIT license exactly (#3253)
* Update rake task `site:publish` to fix minor bugs. (#3254)
* Switch to shields.io for the README badges. (#3255)
* Use `FileList` instead of `Dir.glob` in `site:publish` rake task (#3261)
* Fix test script to be platform-independent (#3279)
* Instead of symlinking `/tmp`, create and symlink a local `tmp` in the tests (#3258)
* Fix some spacing (#3312)
* Fix comment typo in `lib/jekyll/frontmatter_defaults.rb` (#3322)
* Move all `regenerate?` checking to `Regenerator` (#3326)
* Factor out a `read_data_file` call to keep things clean (#3380)
* Proof the site with CircleCI. (#3427)
* Update LICENSE to 2015. (#3477)
* Upgrade tests to use Minitest (#3492)
* Remove trailing whitespace (#3497)
* Use `fixture_site` for Document tests (#3511)
* Remove adapters deprecation warning (#3529)
* Minor fixes to `url.rb` to follow GitHub style guide (#3544)
* Minor changes to resolve deprecation warnings (#3547)
* Convert remaining textile test documents to markdown (#3528)
* Migrate the tests to use rspec-mocks (#3552)
### Site Enhancements
* Add blog post announcing Jekyll Help (#3523)
* Add Jekyll Talk to Help page on site (#3518)
* Fixing the default host on docs (#3229)
* Add `jekyll-thumbnail-filter` to list of third-party plugins (#2790)
* Add link to 'Adding Ajax pagination to Jekyll' to Resources page (#3186)
* Add a Resources link to tutorial on building dynamic navbars (#3185)
* Semantic structure improvements to the post and page layouts (#3251)
* Add new AsciiDoc plugin to list of third-party plugins. (#3277)
* Specify that all transformable collection documents must contain YAML front matter (#3271)
* Assorted accessibility fixes (#3256)
* Update configuration docs to mention `keep_files` for `destination` (#3288, #3296)
* Break when we successfully generate nav link to save CPU cycles. (#3291)
* Update usage docs to mention `keep_files` and a warning about `destination` cleaning (#3295)
* Add logic to automatically generate the `next_section` and `prev_section` navigation items (#3292)
* Some small fixes for the Plugins TOC. (#3306)
* Added versioning comment to configuration file (#3314)
* Add `jekyll-minifier` to list of third-party plugins (#3333)
* Add blog post about the Jekyll meet-up (#3332)
* Use `highlight` Liquid tag instead of the four-space tabs for code (#3336)
* 3.0.0.beta1 release post (#3346)
* Add `twa` to the list of third-party plugins (#3384)
* Remove extra spaces (#3388)
* Fix small grammar errors on a couple pages (#3396)
* Fix typo on Templates docs page (#3420)
* s/three/four for plugin type list (#3424)
* Release jekyllrb.com as a locally-compiled site. (#3426)
* Add a jekyllrb.com/help page which elucidates places from which to get help (#3428)
* Remove extraneous dash on Plugins doc page which caused a formatting error (#3431)
* Fix broken link to Jordan Thornquest's website. (#3438)
* Change the link to an extension (#3457)
* Fix Twitter link on the help page (#3466)
* Fix wording in code snippet highlighting section (#3475)
* Add a `/` to `paginate_path` in the Pagination documentation (#3479)
* Add a link on all the docs pages to "Improve this page". (#3510)
* Add jekyll-auto-image generator to the list of third-party plugins (#3489)
* Replace link to the proposed `picture` element spec (#3530)
* Add frontmatter date formatting information (#3469)
* Improve consistency and clarity of plugins options note (#3546)
* Add permalink warning to pagination docs (#3551)
* Fix grammar in Collections docs API stability warning (#3560)
## 2.5.3 / 2014-12-22
### Bug Fixes ### Bug Fixes
* When checking a Markdown extname, include position of the `.` (#3147) * When checking a Markdown extname, include position of the `.` (#3147)
* Fix `jsonify` Liquid filter handling of boolean values (#3154) * Fix `jsonify` Liquid filter handling of boolean values (#3154)
* Add comma to value of `viewport` meta tag (#3170) * Add comma to value of `viewport` meta tag (#3170)
* Set the link type for the RSS feed to `application/rss+xml` (#3176) * Set the link type for the RSS feed to `application/rss+xml` (#3176)
* Refactor `#as_liquid` (#3158)
### Development Fixes ### Development Fixes
* Exclude built-in bundles from being added to coverage report (#3180)
### Site Enhancements ### Site Enhancements
* Add `@alfredxing` to the `@jekyll/core` team. :tada: (#3218)
* Document the `-q` option for the `build` and `serve` commands (#3149) * Document the `-q` option for the `build` and `serve` commands (#3149)
* Fix some minor typos/flow fixes in documentation website content (#3165) * Fix some minor typos/flow fixes in documentation website content (#3165)
* Add `keep_files` to configuration documentation (#3162) * Add `keep_files` to configuration documentation (#3162)
* Repeat warning about cleaning of the `destination` directory (#3161) * Repeat warning about cleaning of the `destination` directory (#3161)
* Add jekyll-500px-embed to list of third-party plugins (#3163) * Add jekyll-500px-embed to list of third-party plugins (#3163)
* Simplified platform detection in Gemfile example for Windows (#3177) * Simplified platform detection in Gemfile example for Windows (#3177)
* Add the `jekyll-jalali` plugin added to the list of third-party plugins. (#3198)
* Add Table of Contents to Troubleshooting page (#3196)
* Add `inline_highlight` plugin to list of third-party plugins (#3212)
* Add `jekyll-mermaid` plugin to list of third-party plugins (#3222)
## 2.5.2 / 2014-11-17 ## 2.5.2 / 2014-11-17

View File

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

View File

@ -1,9 +1,9 @@
# [Jekyll](http://jekyllrb.com/) # [Jekyll](http://jekyllrb.com/)
[![Gem Version](https://badge.fury.io/rb/jekyll.svg)](https://rubygems.org/gems/jekyll) [![Gem Version](https://img.shields.io/gem/v/jekyll.svg)](https://rubygems.org/gems/jekyll)
[![Build Status](https://secure.travis-ci.org/jekyll/jekyll.svg?branch=master)](https://travis-ci.org/jekyll/jekyll) [![Build Status](https://img.shields.io/travis/jekyll/jekyll/master.svg)](https://travis-ci.org/jekyll/jekyll)
[![Code Climate](http://img.shields.io/codeclimate/github/jekyll/jekyll.svg)](https://codeclimate.com/github/jekyll/jekyll) [![Code Climate](https://img.shields.io/codeclimate/github/jekyll/jekyll.svg)](https://codeclimate.com/github/jekyll/jekyll)
[![Dependency Status](https://gemnasium.com/jekyll/jekyll.svg)](https://gemnasium.com/jekyll/jekyll) [![Dependency Status](https://img.shields.io/gemnasium/jekyll/jekyll.svg)](https://gemnasium.com/jekyll/jekyll)
[![Security](https://hakiri.io/github/jekyll/jekyll/master.svg)](https://hakiri.io/github/jekyll/jekyll/master) [![Security](https://hakiri.io/github/jekyll/jekyll/master.svg)](https://hakiri.io/github/jekyll/jekyll/master)
By Tom Preston-Werner, Nick Quaranto, Parker Moore, and many [awesome contributors](https://github.com/jekyll/jekyll/graphs/contributors)! By Tom Preston-Werner, Nick Quaranto, Parker Moore, and many [awesome contributors](https://github.com/jekyll/jekyll/graphs/contributors)!

View File

@ -26,7 +26,7 @@ def gemspec_file
end end
def gem_file def gem_file
"#{name}-#{version}.gem" "#{name}-#{Gem::Version.new(version).to_s}.gem"
end end
def normalize_bullets(markdown) def normalize_bullets(markdown)
@ -89,6 +89,7 @@ end
multitask :default => [:test, :features] multitask :default => [:test, :features]
task :spec => :test
require 'rake/testtask' require 'rake/testtask'
Rake::TestTask.new(:test) do |test| Rake::TestTask.new(:test) do |test|
test.libs << 'lib' << 'test' test.libs << 'lib' << 'test'
@ -179,33 +180,44 @@ namespace :site do
# Ensure the gh-pages dir exists so we can generate into it. # Ensure the gh-pages dir exists so we can generate into it.
puts "Checking for gh-pages dir..." puts "Checking for gh-pages dir..."
unless File.exist?("./gh-pages") unless File.exist?("./gh-pages")
puts "No gh-pages directory found. Run the following commands first:" puts "Creating gh-pages dir..."
puts " `git clone git@github.com:jekyll/jekyll gh-pages" sh "git clone git@github.com:jekyll/jekyll gh-pages"
puts " `cd gh-pages"
puts " `git checkout gh-pages`"
exit(1)
end end
# Ensure gh-pages branch is up to date. # Ensure latest gh-pages branch history.
Dir.chdir('gh-pages') do Dir.chdir('gh-pages') do
sh "git checkout gh-pages"
sh "git pull origin gh-pages" sh "git pull origin gh-pages"
end end
# Copy to gh-pages dir. # Proceed to purge all files in case we removed a file in this release.
puts "Copying site to gh-pages branch..." puts "Cleaning gh-pages directory..."
Dir.glob("site/*") do |path| purge_exclude = %w[
next if path.include? "_site" gh-pages/.
sh "cp -R #{path} gh-pages/" gh-pages/..
gh-pages/.git
gh-pages/.gitignore
]
FileList["gh-pages/{*,.*}"].exclude(*purge_exclude).each do |path|
sh "rm -rf #{path}"
end end
# Change any configuration settings for production. # Copy site to gh-pages dir.
config = YAML.load_file("gh-pages/_config.yml") puts "Building site into gh-pages branch..."
config.merge!({'sass' => {'style' => 'compressed'}}) ENV['JEKYLL_ENV'] = 'production'
File.write('gh-pages/_config.yml', YAML.dump(config)) require "jekyll"
Jekyll::Commands::Build.process({
"source" => File.expand_path("site"),
"destination" => File.expand_path("gh-pages"),
"sass" => { "style" => "compressed" },
"full_rebuild" => true
})
File.open('gh-pages/.nojekyll', 'wb') { |f| f.puts(":dog: food.") }
# Commit and push. # Commit and push.
puts "Committing and pushing to GitHub Pages..." puts "Committing and pushing to GitHub Pages..."
sha = `git log`.match(/[a-z0-9]{40}/)[0] sha = `git rev-parse HEAD`.strip
Dir.chdir('gh-pages') do Dir.chdir('gh-pages') do
sh "git add ." sh "git add ."
sh "git commit --allow-empty -m 'Updating to #{sha}.'" sh "git commit --allow-empty -m 'Updating to #{sha}.'"
@ -221,8 +233,7 @@ namespace :site do
front_matter = { front_matter = {
"layout" => "docs", "layout" => "docs",
"title" => "History", "title" => "History",
"permalink" => "/docs/history/", "permalink" => "/docs/history/"
"prev_section" => "contributing"
} }
Dir.chdir('site/_docs/') do Dir.chdir('site/_docs/') do
File.open("history.md", "w") do |file| File.open("history.md", "w") do |file|
@ -237,7 +248,7 @@ namespace :site do
desc "Write the site latest_version.txt file" desc "Write the site latest_version.txt file"
task :version_file do task :version_file do
File.open('site/latest_version.txt', 'wb') { |f| f.write(version) } File.open('site/latest_version.txt', 'wb') { |f| f.puts(version) } unless version =~ /(beta|rc|alpha)/i
end end
namespace :releases do namespace :releases do

View File

@ -0,0 +1,13 @@
require 'benchmark/ips'
Benchmark.ips do |x|
path_without_ending_slash = '/some/very/very/long/path/to/a/file/i/like'
x.report('no slash regexp') { path_without_ending_slash =~ /\/$/ }
x.report('no slash end_with?') { path_without_ending_slash.end_with?("/") }
end
Benchmark.ips do |x|
path_with_ending_slash = '/some/very/very/long/path/to/a/file/i/like/'
x.report('slash regexp') { path_with_ending_slash =~ /\/$/ }
x.report('slash end_with?') { path_with_ending_slash.end_with?("/") }
end

View File

@ -14,4 +14,3 @@ Benchmark.ips do |x|
x.report('.map.flatten with no nested arrays') { enum.map { |i| do_thing(i) }.flatten(1) } x.report('.map.flatten with no nested arrays') { enum.map { |i| do_thing(i) }.flatten(1) }
x.report('.flat_map with no nested arrays') { enum.flat_map { |i| do_thing(i) } } x.report('.flat_map with no nested arrays') { enum.flat_map { |i| do_thing(i) } }
end end

View File

@ -6,12 +6,9 @@ $:.unshift File.join(File.dirname(__FILE__), *%w{ .. lib })
require 'jekyll' require 'jekyll'
require 'mercenary' require 'mercenary'
%w[jekyll-import].each do |blessed_gem| Jekyll::External.require_if_present(
begin Jekyll::External.blessed_gems
require blessed_gem )
rescue LoadError
end
end
Jekyll::PluginManager.require_from_bundler Jekyll::PluginManager.require_from_bundler
@ -32,6 +29,7 @@ Mercenary.program(:jekyll) do |p|
p.action do |args, options| p.action do |args, options|
if args.empty? if args.empty?
Jekyll.logger.error "A subcommand is required."
puts p puts p
else else
unless p.has_command?(args.first) unless p.has_command?(args.first)

14
circle.yml Normal file
View File

@ -0,0 +1,14 @@
machine:
timezone: UTC
ruby:
version: 2.1.5
environment:
PROOF: true
test:
override:
- script/proof -f
general:
branches:
ignore:
- gh-pages # no proof script here
- master # don't need to duplicate work

View File

@ -9,7 +9,7 @@ Feature: Collections
And I have a configuration file with "collections" set to "['methods']" And I have a configuration file with "collections" set to "['methods']"
When I run jekyll build When I run jekyll build
Then the _site directory should exist Then the _site directory should exist
And I should see "Collections: <p>Use <code>Jekyll.configuration</code> to build a full configuration for use w/Jekyll.</p>\n\n<p>Whatever: foo.bar</p>\n<p><code>Jekyll.sanitized_path</code> is used to make sure your path is in your source.</p>\n<p>Run your generators! default</p>\n<p>Page without title.</p>\n<p>Run your generators! default</p>" in "_site/index.html" And I should see "Collections: <p>Use <code>Jekyll.configuration</code> to build a full configuration for use w/Jekyll.</p>\n\n<p>Whatever: foo.bar</p>\n<p>Signs are nice</p>\n<p><code>Jekyll.sanitized_path</code> is used to make sure your path is in your source.</p>\n<p>Run your generators! default</p>\n<p>Page without title.</p>\n<p>Run your generators! default</p>" in "_site/index.html"
And the "_site/methods/configuration.html" file should not exist And the "_site/methods/configuration.html" file should not exist
Scenario: Rendered collection Scenario: Rendered collection
@ -70,7 +70,7 @@ Feature: Collections
""" """
When I run jekyll build When I run jekyll build
Then the _site directory should exist Then the _site directory should exist
And I should see "Collections: _methods/configuration.md _methods/sanitized_path.md _methods/site/generate.md _methods/site/initialize.md _methods/um_hi.md" in "_site/index.html" And I should see "Collections: _methods/configuration.md _methods/escape-\+ #%20\[\].md _methods/sanitized_path.md _methods/site/generate.md _methods/site/initialize.md _methods/um_hi.md" in "_site/index.html"
Scenario: Collections specified as an hash Scenario: Collections specified as an hash
Given I have an "index.html" page that contains "Collections: {% for method in site.methods %}{{ method.relative_path }} {% endfor %}" Given I have an "index.html" page that contains "Collections: {% for method in site.methods %}{{ method.relative_path }} {% endfor %}"
@ -82,7 +82,7 @@ Feature: Collections
""" """
When I run jekyll build When I run jekyll build
Then the _site directory should exist Then the _site directory should exist
And I should see "Collections: _methods/configuration.md _methods/sanitized_path.md _methods/site/generate.md _methods/site/initialize.md _methods/um_hi.md" in "_site/index.html" And I should see "Collections: _methods/configuration.md _methods/escape-\+ #%20\[\].md _methods/sanitized_path.md _methods/site/generate.md _methods/site/initialize.md _methods/um_hi.md" in "_site/index.html"
Scenario: All the documents Scenario: All the documents
Given I have an "index.html" page that contains "All documents: {% for doc in site.documents %}{{ doc.relative_path }} {% endfor %}" Given I have an "index.html" page that contains "All documents: {% for doc in site.documents %}{{ doc.relative_path }} {% endfor %}"
@ -94,7 +94,7 @@ Feature: Collections
""" """
When I run jekyll build When I run jekyll build
Then the _site directory should exist Then the _site directory should exist
And I should see "All documents: _methods/configuration.md _methods/sanitized_path.md _methods/site/generate.md _methods/site/initialize.md _methods/um_hi.md" in "_site/index.html" And I should see "All documents: _methods/configuration.md _methods/escape-\+ #%20\[\].md _methods/sanitized_path.md _methods/site/generate.md _methods/site/initialize.md _methods/um_hi.md" in "_site/index.html"
Scenario: Documents have an output attribute, which is the converted HTML Scenario: Documents have an output attribute, which is the converted HTML
Given I have an "index.html" page that contains "First document's output: {{ site.documents.first.output }}" Given I have an "index.html" page that contains "First document's output: {{ site.documents.first.output }}"
@ -118,7 +118,7 @@ Feature: Collections
""" """
When I run jekyll build When I run jekyll build
Then the _site directory should exist Then the _site directory should exist
And I should see "Item count: 1" in "_site/index.html" And I should see "Item count: 2" in "_site/index.html"
Scenario: Sort by title Scenario: Sort by title
Given I have an "index.html" page that contains "{% assign items = site.methods | sort: 'title' %}1. of {{ items.size }}: {{ items.first.output }}" Given I have an "index.html" page that contains "{% assign items = site.methods | sort: 'title' %}1. of {{ items.size }}: {{ items.first.output }}"
@ -130,7 +130,7 @@ Feature: Collections
""" """
When I run jekyll build When I run jekyll build
Then the _site directory should exist Then the _site directory should exist
And I should see "1. of 5: <p>Page without title.</p>" in "_site/index.html" And I should see "1. of 7: <p>Page without title.</p>" in "_site/index.html"
Scenario: Sort by relative_path Scenario: Sort by relative_path
Given I have an "index.html" page that contains "Collections: {% assign methods = site.methods | sort: 'relative_path' %}{% for method in methods %}{{ method.title }}, {% endfor %}" Given I have an "index.html" page that contains "Collections: {% assign methods = site.methods | sort: 'relative_path' %}{% for method in methods %}{{ method.title }}, {% endfor %}"
@ -142,4 +142,4 @@ Feature: Collections
""" """
When I run jekyll build When I run jekyll build
Then the _site directory should exist Then the _site directory should exist
And I should see "Collections: Jekyll.configuration, Jekyll.sanitized_path, Site#generate, , Site#generate," in "_site/index.html" And I should see "Collections: Jekyll.configuration, Jekyll.escape, Jekyll.sanitized_path, Site#generate, , Site#generate," in "_site/index.html"

View File

@ -43,4 +43,4 @@ Feature: Draft Posts
| Recipe | 2009-03-27 | simple | Post path: {{ page.path }} | | Recipe | 2009-03-27 | simple | Post path: {{ page.path }} |
When I run jekyll build --drafts When I run jekyll build --drafts
Then the _site directory should exist Then the _site directory should exist
And I should see "Post path: _drafts/recipe.textile" in "_site/recipe.html" And I should see "Post path: _drafts/recipe.markdown" in "_site/recipe.html"

View File

@ -20,8 +20,6 @@ Feature: Embed filters
And I have the following post: And I have the following post:
| title | date | layout | content | | title | date | layout | content |
| Star & Wars | 2009-03-27 | default | These aren't the droids you're looking for. | | Star & Wars | 2009-03-27 | default | These aren't the droids you're looking for. |
And I have a default layout that contains "{{ page.title | xml_escape }}" And I have a default layout that contains "{{ page.title | xml_escape }}"
When I run jekyll build When I run jekyll build
Then the _site directory should exist Then the _site directory should exist
@ -33,7 +31,7 @@ Feature: Embed filters
And I have the following post: And I have the following post:
| title | date | layout | content | | title | date | layout | content |
| Star Wars | 2009-03-27 | default | These aren't the droids you're looking for. | | Star Wars | 2009-03-27 | default | These aren't the droids you're looking for. |
And I have a default layout that contains "{{ content | xml_escape }}" And I have a default layout that contains "{{ content | number_of_words }}"
When I run jekyll build When I run jekyll build
Then the _site directory should exist Then the _site directory should exist
And I should see "7" in "_site/2009/03/27/star-wars.html" And I should see "7" in "_site/2009/03/27/star-wars.html"
@ -49,13 +47,13 @@ Feature: Embed filters
Then the _site directory should exist Then the _site directory should exist
And I should see "scifi, movies, and force" in "_site/2009/03/27/star-wars.html" And I should see "scifi, movies, and force" in "_site/2009/03/27/star-wars.html"
Scenario: Textilize a given string Scenario: Markdownify a given string
Given I have a _posts directory Given I have a _posts directory
And I have a _layouts directory And I have a _layouts directory
And I have the following post: And I have the following post:
| title | date | layout | content | | title | date | layout | content |
| Star Wars | 2009-03-27 | default | These aren't the droids you're looking for. | | Star Wars | 2009-03-27 | default | These aren't the droids you're looking for. |
And I have a default layout that contains "By {{ '_Obi-wan_' | textilize }}" And I have a default layout that contains "By {{ '_Obi-wan_' | markdownify }}"
When I run jekyll build When I run jekyll build
Then the _site directory should exist Then the _site directory should exist
And I should see "By <p><em>Obi-wan</em></p>" in "_site/2009/03/27/star-wars.html" And I should see "By <p><em>Obi-wan</em></p>" in "_site/2009/03/27/star-wars.html"

View File

@ -25,7 +25,7 @@ Feature: frontmatter defaults
And I have a configuration file with "defaults" set to "[{scope: {path: ""}, values: {custom: "some special data", author: "Ben"}}]" And I have a configuration file with "defaults" set to "[{scope: {path: ""}, values: {custom: "some special data", author: "Ben"}}]"
When I run jekyll build When I run jekyll build
Then the _site directory should exist Then the _site directory should exist
And I should see "<p>some special data</p><div>Ben</div>" in "_site/2013/09/11/default-data.html" And I should see "<p>some special data</p>\n<div>Ben</div>" in "_site/2013/09/11/default-data.html"
And I should see "just some special data by Ben" in "_site/index.html" And I should see "just some special data by Ben" in "_site/index.html"
Scenario: Override frontmatter defaults by path Scenario: Override frontmatter defaults by path
@ -54,6 +54,28 @@ Feature: frontmatter defaults
And I should see "root: Overview for the webpage" in "_site/index.html" And I should see "root: Overview for the webpage" in "_site/index.html"
And I should see "subfolder: Overview for the special section" in "_site/special/index.html" And I should see "subfolder: Overview for the special section" in "_site/special/index.html"
Scenario: Use frontmatter variables by relative path
Given I have a _layouts directory
And I have a main layout that contains "main: {{ content }}"
And I have a _posts directory
And I have the following post:
| title | date | content |
| about | 2013-10-14 | content of site/2013/10/14/about.html |
And I have a special/_posts directory
And I have the following post in "special":
| title | date | path | content |
| about1 | 2013-10-14 | local | content of site/special/2013/10/14/about1.html |
| about2 | 2013-10-14 | local | content of site/special/2013/10/14/about2.html |
And I have a configuration file with "defaults" set to "[{scope: {path: "special"}, values: {layout: "main"}}, {scope: {path: "special/_posts"}, values: {layout: "main"}}, {scope: {path: "_posts"}, values: {layout: "main"}}]"
When I run jekyll build
Then the _site directory should exist
And I should see "main: <p>content of site/2013/10/14/about.html</p>" in "_site/2013/10/14/about.html"
And I should see "main: <p>content of site/special/2013/10/14/about1.html</p>" in "_site/special/2013/10/14/about1.html"
And I should see "main: <p>content of site/special/2013/10/14/about2.html</p>" in "_site/special/2013/10/14/about2.html"
Scenario: Override frontmatter defaults by type Scenario: Override frontmatter defaults by type
Given I have a _posts directory Given I have a _posts directory
And I have the following post: And I have the following post:
@ -78,6 +100,15 @@ Feature: frontmatter defaults
And I should see "nothing" in "_site/override.html" And I should see "nothing" in "_site/override.html"
But the "_site/perma.html" file should not exist But the "_site/perma.html" file should not exist
Scenario: Define permalink default for posts
Given I have a _posts directory
And I have the following post:
| title | date | category | content |
| testpost | 2013-10-14 | blog | blabla |
And I have a configuration file with "defaults" set to "[{scope: {path: "", type: "posts"}, values: {permalink: "/:categories/:title/"}}]"
When I run jekyll build
Then I should see "blabla" in "_site/blog/testpost/index.html"
Scenario: Use frontmatter defaults in collections Scenario: Use frontmatter defaults in collections
Given I have a _slides directory Given I have a _slides directory
And I have a "index.html" file that contains "nothing" And I have a "index.html" file that contains "nothing"

View File

@ -9,15 +9,15 @@ Feature: Include tags
And I have an "_includes/params.html" file that contains "Parameters:<ul>{% for param in include %}<li>{{param[0]}} = {{param[1]}}</li>{% endfor %}</ul>" And I have an "_includes/params.html" file that contains "Parameters:<ul>{% for param in include %}<li>{{param[0]}} = {{param[1]}}</li>{% endfor %}</ul>"
And I have an "_includes/ignore.html" file that contains "<footer>My blog footer</footer>" And I have an "_includes/ignore.html" file that contains "<footer>My blog footer</footer>"
And I have a _posts directory And I have a _posts directory
And I have the following post: And I have the following posts:
| title | date | layout | content | | title | date | type | content |
| Include Files | 2013-03-21 | default | {% include header.html param="myparam" %} | | Include Files | 2013-03-21 | html | {% include header.html param="myparam" %} |
| Ignore params if unused | 2013-03-21 | default | {% include ignore.html date="today" %} | | Ignore params if unused | 2013-03-21 | html | {% include ignore.html date="today" %} |
| List multiple parameters | 2013-03-21 | default | {% include params.html date="today" start="tomorrow" %} | | List multiple parameters | 2013-03-21 | html | {% include params.html date="today" start="tomorrow" %} |
| Dont keep parameters | 2013-03-21 | default | {% include ignore.html param="test" %}\n{% include header.html %} | | Dont keep parameters | 2013-03-21 | html | {% include ignore.html param="test" %}\n{% include header.html %} |
| Allow params with spaces and quotes | 2013-04-07 | default | {% include params.html cool="param with spaces" super="\"quoted\"" single='has "quotes"' escaped='\'single\' quotes' %} | | Allow params with spaces and quotes | 2013-04-07 | html | {% include params.html cool="param with spaces" super="\"quoted\"" single='has "quotes"' escaped='\'single\' quotes' %} |
| Parameter syntax | 2013-04-12 | default | {% include params.html param1_or_2="value" %} | | Parameter syntax | 2013-04-12 | html | {% include params.html param1_or_2="value" %} |
| Pass a variable | 2013-06-22 | default | {% assign var = 'some text' %}{% include params.html local=var layout=page.layout %} | | Pass a variable | 2013-06-22 | html | {% assign var = 'some text' %}{% include params.html local=var title=page.title %} |
When I run jekyll build When I run jekyll build
Then the _site directory should exist Then the _site directory should exist
And I should see "<header>My awesome blog header: myparam</header>" in "_site/2013/03/21/include-files.html" And I should see "<header>My awesome blog header: myparam</header>" in "_site/2013/03/21/include-files.html"
@ -27,12 +27,12 @@ Feature: Include tags
And I should not see "<header>My awesome blog header: myparam</header>" in "_site/2013/03/21/dont-keep-parameters.html" And I should not see "<header>My awesome blog header: myparam</header>" in "_site/2013/03/21/dont-keep-parameters.html"
But I should see "<header>My awesome blog header: </header>" in "_site/2013/03/21/dont-keep-parameters.html" But I should see "<header>My awesome blog header: </header>" in "_site/2013/03/21/dont-keep-parameters.html"
And I should see "<li>cool = param with spaces</li>" in "_site/2013/04/07/allow-params-with-spaces-and-quotes.html" And I should see "<li>cool = param with spaces</li>" in "_site/2013/04/07/allow-params-with-spaces-and-quotes.html"
And I should see "<li>super = &#8220;quoted&#8221;</li>" in "_site/2013/04/07/allow-params-with-spaces-and-quotes.html" And I should see "<li>super = \"quoted\"</li>" in "_site/2013/04/07/allow-params-with-spaces-and-quotes.html"
And I should see "<li>single = has &#8220;quotes&#8221;</li>" in "_site/2013/04/07/allow-params-with-spaces-and-quotes.html" And I should see "<li>single = has \"quotes\"</li>" in "_site/2013/04/07/allow-params-with-spaces-and-quotes.html"
And I should see "<li>escaped = &#8216;single&#8217; quotes</li>" in "_site/2013/04/07/allow-params-with-spaces-and-quotes.html" And I should see "<li>escaped = 'single' quotes</li>" in "_site/2013/04/07/allow-params-with-spaces-and-quotes.html"
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>title = Pass a variable</li>" in "_site/2013/06/22/pass-a-variable.html"
Scenario: Include a file from a variable Scenario: Include a file from a variable
Given I have an _includes directory Given I have an _includes directory

View File

@ -0,0 +1,60 @@
Feature: Incremental rebuild
As an impatient hacker who likes to blog
I want to be able to make a static site
Without waiting too long for it to build
Scenario: Produce correct output site
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 | default | The only winning move is not to play. |
And I have a default layout that contains "Post Layout: {{ content }}"
When I run jekyll build
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"
When I run jekyll build
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: Generate a metadata file
Given I have an "index.html" file that contains "Basic Site"
When I run jekyll build
Then the ".jekyll-metadata" file should exist
Scenario: Rebuild when content is changed
Given I have an "index.html" file that contains "Basic Site"
When I run jekyll build
Then the _site directory should exist
And I should see "Basic Site" in "_site/index.html"
When I wait 1 second
Then I have an "index.html" file that contains "Bacon Site"
When I run jekyll build
Then the _site directory should exist
And I should see "Bacon Site" in "_site/index.html"
Scenario: Rebuild when layout is changed
Given I have a _layouts directory
And I have an "index.html" page with layout "default" that contains "Basic Site with Layout"
And I have a default layout that contains "Page Layout: {{ content }}"
When I run jekyll build
Then the _site directory should exist
And I should see "Page Layout: Basic Site with Layout" in "_site/index.html"
When I wait 1 second
Then I have a default layout that contains "Page Layout Changed: {{ content }}"
When I run jekyll build --full-rebuild
Then the _site directory should exist
And I should see "Page Layout Changed: Basic Site with Layout" in "_site/index.html"
Scenario: Rebuild when an include is changed
Given I have a _includes directory
And I have an "index.html" page that contains "Basic Site with include tag: {% include about.textile %}"
And I have an "_includes/about.textile" file that contains "Generated by Jekyll"
When I run jekyll build
Then the _site directory should exist
And I should see "Basic Site with include tag: Generated by Jekyll" in "_site/index.html"
When I wait 1 second
Then I have an "_includes/about.textile" file that contains "Regenerated by Jekyll"
When I run jekyll build
Then the _site directory should exist
And I should see "Basic Site with include tag: Regenerated by Jekyll" in "_site/index.html"

View File

@ -17,7 +17,10 @@ Feature: Markdown
And I should see "<h1 id=\"my-title\">My Title</h1>" in "_site/index.html" And I should see "<h1 id=\"my-title\">My Title</h1>" in "_site/index.html"
Scenario: Markdown in pagination on index Scenario: Markdown in pagination on index
Given I have a configuration file with "paginate" set to "5" Given I have a configuration file with:
| key | value |
| paginate | 5 |
| gems | [jekyll-paginate] |
And I have an "index.html" page that contains "Index - {% for post in paginator.posts %} {{ post.content }} {% endfor %}" 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 a _posts directory
And I have the following post: And I have the following post:
@ -47,7 +50,7 @@ Feature: Markdown
And I should see "My awesome code" in "_site/index.html" And I should see "My awesome code" in "_site/index.html"
And I should see "<pre><code>My awesome code</code></pre>" in "_site/index.html" And I should see "<pre><code>My awesome code</code></pre>" in "_site/index.html"
Scenario: Maruku fenced codeblocks Scenario: Maruku fenced codeblocks with syntax highlighting
Given I have a configuration file with "markdown" set to "maruku" Given I have a configuration file with "markdown" set to "maruku"
And I have an "index.markdown" file with content: And I have an "index.markdown" file with content:
""" """

View File

@ -4,7 +4,10 @@ Feature: Site pagination
I want divide the posts in several pages I want divide the posts in several pages
Scenario Outline: Paginate with N posts per page Scenario Outline: Paginate with N posts per page
Given I have a configuration file with "paginate" set to "<num>" Given I have a configuration file with:
| key | value |
| paginate | <num> |
| gems | [jekyll-paginate] |
And I have a _layouts directory And I have a _layouts directory
And I have an "index.html" page that contains "{{ paginator.posts.size }}" And I have an "index.html" page that contains "{{ paginator.posts.size }}"
And I have a _posts directory And I have a _posts directory
@ -32,6 +35,7 @@ Feature: Site pagination
| paginate | 1 | | paginate | 1 |
| paginate_path | /blog/page-:num | | paginate_path | /blog/page-:num |
| permalink | /blog/:year/:month/:day/:title | | permalink | /blog/:year/:month/:day/:title |
| gems | [jekyll-paginate] |
And I have a blog directory And I have a blog directory
And I have an "blog/index.html" page that contains "{{ paginator.posts.size }}" And I have an "blog/index.html" page that contains "{{ paginator.posts.size }}"
And I have a _posts directory And I have a _posts directory
@ -59,6 +63,7 @@ Feature: Site pagination
| paginate | 1 | | paginate | 1 |
| paginate_path | /blog/page/:num | | paginate_path | /blog/page/:num |
| permalink | /blog/:year/:month/:day/:title | | permalink | /blog/:year/:month/:day/:title |
| gems | [jekyll-paginate] |
And I have a blog directory And I have a blog directory
And I have an "blog/index.html" page that contains "{{ paginator.posts.size }}" And I have an "blog/index.html" page that contains "{{ paginator.posts.size }}"
And I have an "index.html" page that contains "Don't pick me!" And I have an "index.html" page that contains "Don't pick me!"

View File

@ -39,7 +39,7 @@ Feature: Fancy permalinks
And I have the following post: And I have the following post:
| title | category | date | content | | title | category | date | content |
| Custom Permalink Schema | stuff | 2009-03-27 | Totally custom. | | Custom Permalink Schema | stuff | 2009-03-27 | Totally custom. |
And I have a configuration file with "permalink" set to "/blog/:year/:month/:day/:title" And I have a configuration file with "permalink" set to "/blog/:year/:month/:day/:title/"
When I run jekyll build When I run jekyll build
Then the _site directory should exist Then the _site directory should exist
And I should see "Totally custom." in "_site/blog/2009/03/27/custom-permalink-schema/index.html" And I should see "Totally custom." in "_site/blog/2009/03/27/custom-permalink-schema/index.html"
@ -68,7 +68,7 @@ Feature: Fancy permalinks
Given I have a _posts directory Given I have a _posts directory
And I have the following post: And I have the following post:
| title | date | permalink | content | | title | date | permalink | content |
| Some post | 2013-04-14 | /custom/posts/1 | bla bla | | Some post | 2013-04-14 | /custom/posts/1/ | bla bla |
When I run jekyll build When I run jekyll build
Then the _site directory should exist Then the _site directory should exist
And the _site/custom/posts/1 directory should exist And the _site/custom/posts/1 directory should exist
@ -83,13 +83,3 @@ Feature: Fancy permalinks
Then the _site directory should exist Then the _site directory should exist
And the _site/custom/posts directory should exist And the _site/custom/posts directory should exist
And I should see "bla bla" in "_site/custom/posts/some.html" And I should see "bla bla" in "_site/custom/posts/some.html"
Scenario: Use per-post ending in .htm
Given I have a _posts directory
And I have the following post:
| title | date | permalink | content |
| Some post | 2013-04-14 | /custom/posts/some.htm | bla bla |
When I run jekyll build
Then the _site directory should exist
And the _site/custom/posts directory should exist
And I should see "bla bla" in "_site/custom/posts/some.htm"

View File

@ -141,7 +141,7 @@ Feature: Post data
And I have a simple layout that contains "Post categories: {{ page.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 build When I run jekyll build
Then the _site directory should exist Then the _site directory should exist
And I should see "Post categories: scifi and movies" in "_site/scifi/movies/2009/03/27/star-wars.html" And I should see "Post categories: scifi and Movies" in "_site/scifi/movies/2009/03/27/star-wars.html"
Scenario: Use post.categories variable when category is in YAML Scenario: Use post.categories variable when category is in YAML
Given I have a _posts directory Given I have a _posts directory
@ -163,7 +163,7 @@ Feature: Post data
And I have a simple layout that contains "Post category: {{ page.categories }}" And I have a simple layout that contains "Post category: {{ page.categories }}"
When I run jekyll build When I run jekyll build
Then the _site directory should exist Then the _site directory should exist
And I should see "Post category: movies" in "_site/movies/2009/03/27/star-wars.html" And I should see "Post category: Movies" in "_site/movies/2009/03/27/star-wars.html"
Scenario: Use post.categories variable when categories are in YAML Scenario: Use post.categories variable when categories are in YAML
Given I have a _posts directory Given I have a _posts directory
@ -197,8 +197,8 @@ Feature: Post data
And I have a simple layout that contains "Post categories: {{ page.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 build When I run jekyll build
Then the _site directory should exist Then the _site directory should exist
And I should see "Post categories: scifi and movies" in "_site/scifi/movies/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"
And I should see "Post categories: scifi and movies" in "_site/scifi/movies/2013/03/17/star-trek.html" And I should see "Post categories: SciFi and movies" in "_site/scifi/movies/2013/03/17/star-trek.html"
Scenario Outline: Use page.path variable Scenario Outline: Use page.path variable
Given I have a <dir>/_posts directory Given I have a <dir>/_posts directory

View File

@ -46,5 +46,5 @@ Feature: Post excerpts
And the _site/2007/12 directory should exist And the _site/2007/12 directory should exist
And the _site/2007/12/31 directory should exist And the _site/2007/12/31 directory should exist
And the "_site/2007/12/31/entry1.html" file should exist And the "_site/2007/12/31/entry1.html" file should exist
And I should see exactly "<p>content for entry1.</p>" in "_site/index.html" And I should see "<p>content for entry1.</p>" in "_site/index.html"
And I should see exactly "<html><head></head><body><p>content for entry1.</p></body></html>" in "_site/2007/12/31/entry1.html" And I should see "<html><head></head><body><p>content for entry1.</p>\n\n</body></html>" in "_site/2007/12/31/entry1.html"

View File

@ -15,6 +15,7 @@ Feature: Rendering
Scenario: Don't place asset files in layout Scenario: Don't place asset files in layout
Given I have an "index.scss" page with layout "simple" that contains ".foo-bar { color:black; }" Given I have an "index.scss" page with layout "simple" that contains ".foo-bar { color:black; }"
And I have an "index.coffee" page with layout "simple" that contains "whatever()" And I have an "index.coffee" page with layout "simple" that contains "whatever()"
And I have a configuration file with "gems" set to "[jekyll-coffeescript]"
And I have a simple layout that contains "{{ content }}Ahoy, indeed!" And I have a simple layout that contains "{{ content }}Ahoy, indeed!"
When I run jekyll build When I run jekyll build
Then the _site directory should exist Then the _site directory should exist
@ -28,8 +29,15 @@ Feature: Rendering
Then the _site directory should exist Then the _site directory should exist
And I should see ".foo-bar {\n color: red; }" in "_site/index.css" And I should see ".foo-bar {\n color: red; }" in "_site/index.css"
Scenario: Render liquid in CoffeeScript Scenario: Not render liquid in CoffeeScript without explicitly including jekyll-coffeescript
Given I have an "index.coffee" page with animal "cicada" that contains "hey='for {{page.animal}}'" Given I have an "index.coffee" page with animal "cicada" that contains "hey='for {{page.animal}}'"
When I run jekyll build When I run jekyll build
Then the _site directory should exist Then the _site directory should exist
And the "_site/index.js" file should not exist
Scenario: Render liquid in CoffeeScript with jekyll-coffeescript enabled
Given I have an "index.coffee" page with animal "cicada" that contains "hey='for {{page.animal}}'"
And I have a configuration file with "gems" set to "[jekyll-coffeescript]"
When I run jekyll build
Then the _site directory should exist
And I should see "hey = 'for cicada';" in "_site/index.js" And I should see "hey = 'for cicada';" in "_site/index.js"

View File

@ -170,8 +170,8 @@ Feature: Site configuration
When I run jekyll build When I run jekyll build
Then the _site directory should exist Then the _site directory should exist
And I should see "Page Layout: 2" in "_site/index.html" And I should see "Page Layout: 2" in "_site/index.html"
And I should see "Post Layout: <p>content for entry1.</p> built at 2013-04-09T23:22:00-04:00" in "_site/2013/04/09/entry1.html" And I should see "Post Layout: <p>content for entry1.</p>\n built at 2013-04-09T23:22:00-04:00" in "_site/2013/04/09/entry1.html"
And I should see "Post Layout: <p>content for entry2.</p> built at 2013-04-10T03:14:00-04:00" in "_site/2013/04/10/entry2.html" And I should see "Post Layout: <p>content for entry2.</p>\n built at 2013-04-10T03:14:00-04:00" in "_site/2013/04/10/entry2.html"
Scenario: Generate proper dates with explicitly set timezone (different than posts' time) Scenario: Generate proper dates with explicitly set timezone (different than posts' time)
Given I have a _layouts directory Given I have a _layouts directory
@ -180,19 +180,19 @@ Feature: Site configuration
And I have an "index.html" page with layout "page" that contains "site index page" And I have an "index.html" page with layout "page" that contains "site index page"
And I have a configuration file with: And I have a configuration file with:
| key | value | | key | value |
| timezone | Australia/Melbourne | | timezone | Pacific/Honolulu |
And I have a _posts directory And I have a _posts directory
And I have the following posts: And I have the following posts:
| title | date | layout | content | | title | date | layout | content |
| entry1 | 2013-04-09 23:22 -0400 | post | content for entry1. | | entry1 | 2013-04-09 23:22 +0400 | post | content for entry1. |
| entry2 | 2013-04-10 03:14 -0400 | post | content for entry2. | | entry2 | 2013-04-10 03:14 +0400 | post | content for entry2. |
When I run jekyll build When I run jekyll build
Then the _site directory should exist Then the _site directory should exist
And I should see "Page Layout: 2" in "_site/index.html" And I should see "Page Layout: 2" in "_site/index.html"
And the "_site/2013/04/10/entry1.html" file should exist And the "_site/2013/04/09/entry1.html" file should exist
And the "_site/2013/04/10/entry2.html" file should exist And the "_site/2013/04/09/entry2.html" file should exist
And I should see escaped "Post Layout: <p>content for entry1.</p> built at 2013-04-10T13:22:00+10:00" in "_site/2013/04/10/entry1.html" And I should see "Post Layout: <p>content for entry1.</p>\n built at 2013-04-09T09:22:00-10:00" in "_site/2013/04/09/entry1.html"
And I should see escaped "Post Layout: <p>content for entry2.</p> built at 2013-04-10T17:14:00+10:00" in "_site/2013/04/10/entry2.html" And I should see "Post Layout: <p>content for entry2.</p>\n built at 2013-04-09T13:14:00-10:00" in "_site/2013/04/09/entry2.html"
Scenario: Limit the number of posts generated by most recent date Scenario: Limit the number of posts generated by most recent date
Given I have a _posts directory Given I have a _posts directory

View File

@ -8,7 +8,7 @@ def file_content_from_hash(input_hash)
input_hash['content'] input_hash['content']
end end
<<EOF <<-EOF
--- ---
#{matter} #{matter}
--- ---
@ -24,9 +24,10 @@ end
After do After do
FileUtils.rm_rf(TEST_DIR) if File.exist?(TEST_DIR) FileUtils.rm_rf(TEST_DIR) if File.exist?(TEST_DIR)
FileUtils.rm(JEKYLL_COMMAND_OUTPUT_FILE) if File.exist?(JEKYLL_COMMAND_OUTPUT_FILE) FileUtils.rm(JEKYLL_COMMAND_OUTPUT_FILE) if File.exist?(JEKYLL_COMMAND_OUTPUT_FILE)
Dir.chdir(File.dirname(TEST_DIR))
end end
World(Test::Unit::Assertions) World(Minitest::Assertions)
Given /^I have a blank site in "(.*)"$/ do |path| Given /^I have a blank site in "(.*)"$/ do |path|
FileUtils.mkdir_p(path) unless File.exist?(path) FileUtils.mkdir_p(path) unless File.exist?(path)
@ -39,7 +40,7 @@ end
# Like "I have a foo file" but gives a yaml front matter so jekyll actually processes it # Like "I have a foo file" but gives a yaml front matter so jekyll actually processes it
Given /^I have an? "(.*)" page(?: with (.*) "(.*)")? that contains "(.*)"$/ do |file, key, value, text| Given /^I have an? "(.*)" page(?: with (.*) "(.*)")? that contains "(.*)"$/ do |file, key, value, text|
File.open(file, 'w') do |f| File.open(file, 'w') do |f|
f.write <<EOF f.write <<-EOF
--- ---
#{key || 'layout'}: #{value || 'nil'} #{key || 'layout'}: #{value || 'nil'}
--- ---
@ -83,7 +84,7 @@ end
Given /^I have the following (draft|page|post)s?(?: (in|under) "([^"]+)")?:$/ do |status, direction, folder, table| Given /^I have the following (draft|page|post)s?(?: (in|under) "([^"]+)")?:$/ do |status, direction, folder, table|
table.hashes.each do |input_hash| table.hashes.each do |input_hash|
title = slug(input_hash['title']) title = slug(input_hash['title'])
ext = input_hash['type'] || 'textile' ext = input_hash['type'] || 'markdown'
before, after = location(folder, direction) before, after = location(folder, direction)
case status case status
@ -133,6 +134,10 @@ Given /^I have fixture collections$/ do
FileUtils.cp_r File.join(JEKYLL_SOURCE_DIR, "test", "source", "_methods"), source_dir FileUtils.cp_r File.join(JEKYLL_SOURCE_DIR, "test", "source", "_methods"), source_dir
end end
Given /^I wait (\d+) second(s?)$/ do |time, plural|
sleep(time.to_f)
end
################## ##################
# #
# Changing stuff # Changing stuff
@ -163,6 +168,12 @@ When /^I delete the file "(.*)"$/ do |file|
File.delete(file) File.delete(file)
end end
##################
#
# Checking stuff
#
##################
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
@ -180,7 +191,7 @@ Then /^I should see exactly "(.*)" in "(.*)"$/ do |text, file|
end end
Then /^I should not see "(.*)" in "(.*)"$/ do |text, file| Then /^I should not see "(.*)" in "(.*)"$/ do |text, file|
assert_no_match Regexp.new(text, Regexp::MULTILINE), file_contents(file) refute_match Regexp.new(text, Regexp::MULTILINE), file_contents(file)
end end
Then /^I should see escaped "(.*)" in "(.*)"$/ do |text, file| Then /^I should see escaped "(.*)" in "(.*)"$/ do |text, file|
@ -188,7 +199,15 @@ Then /^I should see escaped "(.*)" in "(.*)"$/ do |text, file|
end end
Then /^the "(.*)" file should +exist$/ do |file| Then /^the "(.*)" file should +exist$/ do |file|
assert File.file?(file), "The file \"#{file}\" does not exist" file_does_exist = File.file?(file)
unless file_does_exist
all_steps_to_path(file).each do |dir|
STDERR.puts ""
STDERR.puts "Dir #{dir}:"
STDERR.puts Dir["#{dir}/**/*"]
end
end
assert file_does_exist, "The file \"#{file}\" does not exist.\n"
end end
Then /^the "(.*)" file should not exist$/ do |file| Then /^the "(.*)" file should not exist$/ do |file|

View File

@ -1,7 +1,6 @@
require 'fileutils' require 'fileutils'
require 'posix-spawn' require 'posix-spawn'
require 'rr' require 'minitest/assertions'
require 'test/unit'
require 'time' require 'time'
JEKYLL_SOURCE_DIR = File.dirname(File.dirname(File.dirname(__FILE__))) JEKYLL_SOURCE_DIR = File.dirname(File.dirname(File.dirname(__FILE__)))
@ -13,6 +12,17 @@ def source_dir(*files)
File.join(TEST_DIR, *files) File.join(TEST_DIR, *files)
end end
def all_steps_to_path(path)
source = Pathname.new(source_dir('_site')).expand_path
dest = Pathname.new(path).expand_path
paths = []
dest.ascend do |f|
break if f.eql? source
paths.unshift f.to_s
end
paths
end
def jekyll_output_file def jekyll_output_file
JEKYLL_COMMAND_OUTPUT_FILE JEKYLL_COMMAND_OUTPUT_FILE
end end

View File

@ -5,64 +5,35 @@ require 'jekyll/version'
Gem::Specification.new do |s| Gem::Specification.new do |s|
s.specification_version = 2 if s.respond_to? :specification_version= 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.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version=
s.rubygems_version = '2.2.2' s.rubygems_version = '2.2.2'
s.required_ruby_version = '>= 1.9.3' s.required_ruby_version = '>= 2.0.0'
s.name = 'jekyll' s.name = 'jekyll'
s.version = Jekyll::VERSION s.version = Jekyll::VERSION
s.license = 'MIT' s.license = 'MIT'
s.summary = "A simple, blog aware, static site generator." s.summary = 'A simple, blog aware, static site generator.'
s.description = "Jekyll is a simple, blog aware, static site generator." s.description = 'Jekyll is a simple, blog aware, static site generator.'
s.authors = ["Tom Preston-Werner"] s.authors = ['Tom Preston-Werner']
s.email = 'tom@mojombo.com' s.email = 'tom@mojombo.com'
s.homepage = 'https://github.com/jekyll/jekyll' s.homepage = 'https://github.com/jekyll/jekyll'
all_files = `git ls-files -z`.split("\x0") all_files = `git ls-files -z`.split("\x0")
s.files = all_files.grep(%r{^(bin|lib)/}) s.files = all_files.grep(%r{^(bin|lib)/})
s.executables = all_files.grep(%r{^bin/}) { |f| File.basename(f) } s.executables = all_files.grep(%r{^bin/}) { |f| File.basename(f) }
s.require_paths = ["lib"] s.require_paths = ['lib']
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.6.1") s.add_runtime_dependency('liquid', '~> 3.0')
s.add_runtime_dependency('kramdown', "~> 1.3") s.add_runtime_dependency('kramdown', '~> 1.3')
s.add_runtime_dependency('mercenary', "~> 0.3.3") s.add_runtime_dependency('mercenary', '~> 0.3.3')
s.add_runtime_dependency('safe_yaml', "~> 1.0") s.add_runtime_dependency('safe_yaml', '~> 1.0')
s.add_runtime_dependency('colorator', "~> 0.1") s.add_runtime_dependency('colorator', '~> 0.1')
s.add_runtime_dependency('rouge', '~> 1.7')
# Before 3.0 drops, phase the following gems out as dev dependencies
# and gracefully handle their absence.
s.add_runtime_dependency('pygments.rb', "~> 0.6.0")
s.add_runtime_dependency('redcarpet', "~> 3.1")
s.add_runtime_dependency('toml', '~> 0.1.0')
s.add_runtime_dependency('jekyll-paginate', '~> 1.0')
s.add_runtime_dependency('jekyll-gist', '~> 1.0')
s.add_runtime_dependency('jekyll-coffeescript', '~> 1.0')
s.add_runtime_dependency('jekyll-sass-converter', '~> 1.0') s.add_runtime_dependency('jekyll-sass-converter', '~> 1.0')
s.add_runtime_dependency('jekyll-watch', '~> 1.1') s.add_runtime_dependency('jekyll-watch', '~> 1.1')
s.add_runtime_dependency('classifier-reborn', "~> 2.0")
s.add_development_dependency('rake', "~> 10.1")
s.add_development_dependency('rdoc', "~> 3.11")
s.add_development_dependency('redgreen', "~> 1.2")
s.add_development_dependency('shoulda', "~> 3.5")
s.add_development_dependency('rr', "~> 1.1")
s.add_development_dependency('cucumber', "1.3.11")
s.add_development_dependency('RedCloth', "~> 4.2")
s.add_development_dependency('maruku', "~> 0.7.0")
s.add_development_dependency('rdiscount', "~> 1.6")
s.add_development_dependency('launchy', "~> 2.3")
s.add_development_dependency('simplecov', "~> 0.9")
s.add_development_dependency('simplecov-gem-adapter', "~> 1.0.1")
s.add_development_dependency('mime-types', "~> 1.5")
s.add_development_dependency('activesupport', '~> 3.2.13')
s.add_development_dependency('jekyll_test_plugin')
s.add_development_dependency('jekyll_test_plugin_malicious')
s.add_development_dependency('rouge', '~> 1.7')
s.add_development_dependency('minitest') if RUBY_PLATFORM =~ /cygwin/
s.add_development_dependency('test-unit') if RUBY_PLATFORM =~ /cygwin/
end end

View File

@ -21,6 +21,7 @@ require 'time'
require 'English' require 'English'
require 'pathname' require 'pathname'
require 'logger' require 'logger'
require 'set'
# 3rd party # 3rd party
require 'safe_yaml/load' require 'safe_yaml/load'
@ -29,6 +30,7 @@ require 'kramdown'
require 'colorator' require 'colorator'
SafeYAML::OPTIONS[:suppress_warnings] = true SafeYAML::OPTIONS[:suppress_warnings] = true
Liquid::Template.error_mode = :strict
module Jekyll module Jekyll
@ -43,6 +45,7 @@ module Jekyll
autoload :EntryFilter, 'jekyll/entry_filter' autoload :EntryFilter, 'jekyll/entry_filter'
autoload :Errors, 'jekyll/errors' autoload :Errors, 'jekyll/errors'
autoload :Excerpt, 'jekyll/excerpt' autoload :Excerpt, 'jekyll/excerpt'
autoload :External, 'jekyll/external'
autoload :Filters, 'jekyll/filters' autoload :Filters, 'jekyll/filters'
autoload :FrontmatterDefaults, 'jekyll/frontmatter_defaults' autoload :FrontmatterDefaults, 'jekyll/frontmatter_defaults'
autoload :Layout, 'jekyll/layout' autoload :Layout, 'jekyll/layout'
@ -52,6 +55,7 @@ module Jekyll
autoload :PluginManager, 'jekyll/plugin_manager' autoload :PluginManager, 'jekyll/plugin_manager'
autoload :Post, 'jekyll/post' autoload :Post, 'jekyll/post'
autoload :Publisher, 'jekyll/publisher' autoload :Publisher, 'jekyll/publisher'
autoload :Regenerator, 'jekyll/regenerator'
autoload :RelatedPosts, 'jekyll/related_posts' autoload :RelatedPosts, 'jekyll/related_posts'
autoload :Renderer, 'jekyll/renderer' autoload :Renderer, 'jekyll/renderer'
autoload :Site, 'jekyll/site' autoload :Site, 'jekyll/site'
@ -153,6 +157,9 @@ module Jekyll
end end
end end
# Conditional optimizations
Jekyll::External.require_if_present('liquid-c')
end end
end end
@ -162,11 +169,4 @@ require_all 'jekyll/converters/markdown'
require_all 'jekyll/generators' require_all 'jekyll/generators'
require_all 'jekyll/tags' require_all 'jekyll/tags'
# Eventually remove these for 3.0 as non-core require 'jekyll-sass-converter'
Jekyll::Deprecator.gracefully_require(%w[
toml
jekyll-paginate
jekyll-gist
jekyll-coffeescript
jekyll-sass-converter
])

View File

@ -1,7 +1,6 @@
require 'set' require 'set'
module Jekyll module Jekyll
class Site
# Handles the cleanup of a site's destination before it is built. # Handles the cleanup of a site's destination before it is built.
class Cleaner class Cleaner
attr_reader :site attr_reader :site
@ -13,6 +12,7 @@ module Jekyll
# Cleans up the site's destination directory # Cleans up the site's destination directory
def cleanup! def cleanup!
FileUtils.rm_rf(obsolete_files) FileUtils.rm_rf(obsolete_files)
FileUtils.rm_rf(metadata_file) if @site.full_rebuild?
end end
private private
@ -24,6 +24,13 @@ module Jekyll
(existing_files - new_files - new_dirs + replaced_files).to_a (existing_files - new_files - new_dirs + replaced_files).to_a
end end
# Private: The metadata file storing dependency tree and build history
#
# Returns an Array with the metdata file as the only item
def metadata_file
[site.regenerator.metadata_file]
end
# Private: The list of existing files, apart from 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
@ -92,4 +99,3 @@ module Jekyll
end end
end end
end end
end

View File

@ -40,7 +40,7 @@ module Jekyll
if Utils.has_yaml_header? full_path if Utils.has_yaml_header? full_path
doc = Jekyll::Document.new(full_path, { site: site, collection: self }) doc = Jekyll::Document.new(full_path, { site: site, collection: self })
doc.read doc.read
docs << doc docs << doc if site.publisher.publish?(doc)
else else
relative_dir = Jekyll.sanitized_path(relative_directory, File.dirname(file_path)).chomp("/.") relative_dir = Jekyll.sanitized_path(relative_directory, File.dirname(file_path)).chomp("/.")
files << StaticFile.new(site, site.source, relative_dir, File.basename(full_path), self) files << StaticFile.new(site, site.source, relative_dir, File.basename(full_path), self)
@ -170,7 +170,9 @@ module Jekyll
# #
# Returns the URL template to render collection's documents at. # Returns the URL template to render collection's documents at.
def url_template def url_template
metadata.fetch('permalink', "/:collection/:path:output_ext") metadata.fetch('permalink') do
Utils.add_permalink_suffix("/:collection/:path", site.permalink_style)
end
end end
# Extract options for this collection from the site configuration. # Extract options for this collection from the site configuration.
@ -183,6 +185,5 @@ module Jekyll
{} {}
end end
end end
end end
end end

View File

@ -49,6 +49,8 @@ module Jekyll
# Returns nothing # Returns nothing
def add_build_options(c) def add_build_options(c)
c.option 'config', '--config CONFIG_FILE[,CONFIG_FILE2,...]', Array, 'Custom configuration file' c.option 'config', '--config CONFIG_FILE[,CONFIG_FILE2,...]', Array, 'Custom configuration file'
c.option 'destination', '-d', '--destination DESTINATION', 'The current folder will be generated into DESTINATION'
c.option 'source', '-s', '--source SOURCE', 'Custom source directory'
c.option 'future', '--future', 'Publishes posts with a future date' c.option 'future', '--future', 'Publishes posts with a future date'
c.option 'limit_posts', '--limit_posts MAX_POSTS', Integer, 'Limits the number of posts to parse and publish' c.option 'limit_posts', '--limit_posts MAX_POSTS', Integer, 'Limits the number of posts to parse and publish'
c.option 'watch', '-w', '--[no-]watch', 'Watch for changes and rebuild' c.option 'watch', '-w', '--[no-]watch', 'Watch for changes and rebuild'
@ -58,6 +60,7 @@ module Jekyll
c.option 'unpublished', '--unpublished', 'Render posts that were marked as unpublished' c.option 'unpublished', '--unpublished', 'Render posts that were marked as unpublished'
c.option 'quiet', '-q', '--quiet', 'Silence output.' c.option 'quiet', '-q', '--quiet', 'Silence output.'
c.option 'verbose', '-V', '--verbose', 'Print verbose output.' c.option 'verbose', '-V', '--verbose', 'Print verbose output.'
c.option 'full_rebuild', '-f', '--full-rebuild', 'Disable incremental rebuild.'
end end
end end

View File

@ -48,13 +48,16 @@ module Jekyll
# #
# Returns nothing. # Returns nothing.
def build(site, options) def build(site, options)
t = Time.now
source = options['source'] source = options['source']
destination = options['destination'] destination = options['destination']
full_build = options['full_rebuild']
Jekyll.logger.info "Source:", source Jekyll.logger.info "Source:", source
Jekyll.logger.info "Destination:", destination Jekyll.logger.info "Destination:", destination
Jekyll.logger.info "Incremental build:", (full_build ? "disabled" : "enabled")
Jekyll.logger.info "Generating..." Jekyll.logger.info "Generating..."
process_site(site) process_site(site)
Jekyll.logger.info "", "done." Jekyll.logger.info "", "done in #{(Time.now - t).round(3)} seconds."
end end
# Private: Watch for file changes and rebuild the site. # Private: Watch for file changes and rebuild the site.
@ -64,7 +67,7 @@ module Jekyll
# #
# Returns nothing. # Returns nothing.
def watch(site, options) def watch(site, options)
Deprecator.gracefully_require 'jekyll-watch' External.require_with_graceful_fail 'jekyll-watch'
Jekyll::Watcher.watch(options) Jekyll::Watcher.watch(options)
end end

View File

@ -0,0 +1,42 @@
module Jekyll
module Commands
class Clean < Command
class << self
def init_with_program(prog)
prog.command(:clean) do |c|
c.syntax 'clean [subcommand]'
c.description 'Clean the site (removes site output and metadata file) without building.'
c.action do |args, _|
Jekyll::Commands::Clean.process({})
end
end
end
def process(options)
options = configuration_from_options(options)
destination = options['destination']
metadata_file = File.join(options['source'], '.jekyll-metadata')
if File.directory? destination
Jekyll.logger.info "Cleaning #{destination}..."
FileUtils.rm_rf(destination)
Jekyll.logger.info "", "done."
else
Jekyll.logger.info "Nothing to do for #{destination}."
end
if File.file? metadata_file
Jekyll.logger.info "Removing #{metadata_file}..."
FileUtils.rm_rf(metadata_file)
Jekyll.logger.info "", "done."
else
Jekyll.logger.info "Nothing to do for #{metadata_file}."
end
end
end
end
end
end

View File

@ -1,30 +0,0 @@
module Jekyll
module Commands
class Docs < Command
class << self
def init_with_program(prog)
prog.command(:docs) do |c|
c.syntax 'docs'
c.description "Launch local server with docs for Jekyll v#{Jekyll::VERSION}"
c.option 'port', '-P', '--port [PORT]', 'Port to listen on'
c.option 'host', '-H', '--host [HOST]', 'Host to bind to'
c.action do |args, options|
options.merge!({
'source' => File.expand_path("../../../site", File.dirname(__FILE__)),
'destination' => File.expand_path("../../../site/_site", File.dirname(__FILE__))
})
Jekyll::Commands::Build.process(options)
Jekyll::Commands::Serve.process(options)
end
end
end
end
end
end
end

View File

@ -39,7 +39,7 @@ module Jekyll
contains_deprecated_pages = false contains_deprecated_pages = false
site.pages.each do |page| site.pages.each do |page|
if page.uses_relative_permalinks if page.uses_relative_permalinks
Jekyll.logger.warn "Deprecation:", "'#{page.path}' uses relative" + Jekyll::Deprecator.deprecation_message "'#{page.path}' uses relative" +
" permalinks which will be deprecated in" + " permalinks which will be deprecated in" +
" Jekyll v2.0.0 and beyond." " Jekyll v2.0.0 and beyond."
contains_deprecated_pages = true contains_deprecated_pages = true

View File

@ -40,7 +40,7 @@ module Jekyll
s.mount( s.mount(
options['baseurl'], options['baseurl'],
WEBrick::HTTPServlet::FileHandler, custom_file_handler,
destination, destination,
file_handler_options file_handler_options
) )
@ -50,7 +50,7 @@ module Jekyll
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)
Jekyll.logger.info "Server detached with pid '#{pid}'.", "Run `kill -9 #{pid}' to stop the server." Jekyll.logger.info "Server detached with pid '#{pid}'.", "Run `pkill -f jekyll' or `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 }
@ -99,6 +99,21 @@ module Jekyll
opts opts
end end
# Custom WEBrick FileHandler servlet for serving "/file.html" at "/file"
# when no exact match is found. This mirrors the behavior of GitHub
# Pages and many static web server configs.
def custom_file_handler
Class.new WEBrick::HTTPServlet::FileHandler do
def search_file(req, res, basename)
if file = super
file
else
super(req, res, "#{basename}.html")
end
end
end
end
def start_callback(detached) def start_callback(detached)
unless detached unless detached
Proc.new { Jekyll.logger.info "Server running...", "press ctrl-c to stop." } Proc.new { Jekyll.logger.info "Server running...", "press ctrl-c to stop." }

View File

@ -21,7 +21,7 @@ module Jekyll
'keep_files' => ['.git','.svn'], 'keep_files' => ['.git','.svn'],
'encoding' => 'utf-8', 'encoding' => 'utf-8',
'markdown_ext' => 'markdown,mkdown,mkdn,mkd,md', 'markdown_ext' => 'markdown,mkdown,mkdn,mkd,md',
'textile_ext' => 'textile', 'full_rebuild' => false,
# Filtering Content # Filtering Content
'show_drafts' => nil, 'show_drafts' => nil,
@ -35,7 +35,7 @@ module Jekyll
# Conversion # Conversion
'markdown' => 'kramdown', 'markdown' => 'kramdown',
'highlighter' => 'pygments', 'highlighter' => 'rouge',
'lsi' => false, 'lsi' => false,
'excerpt_separator' => "\n\n", 'excerpt_separator' => "\n\n",
@ -79,7 +79,7 @@ module Jekyll
'entity_output' => 'as_char', 'entity_output' => 'as_char',
'toc_levels' => '1..6', 'toc_levels' => '1..6',
'smart_quotes' => 'lsquo,rsquo,ldquo,rdquo', 'smart_quotes' => 'lsquo,rsquo,ldquo,rdquo',
'use_coderay' => false, 'enable_coderay' => false,
'coderay' => { 'coderay' => {
'coderay_wrap' => 'div', 'coderay_wrap' => 'div',
@ -89,10 +89,6 @@ module Jekyll
'coderay_bold_every' => 10, 'coderay_bold_every' => 10,
'coderay_css' => 'style' 'coderay_css' => 'style'
} }
},
'redcloth' => {
'hard_breaks' => true
} }
} }
@ -119,6 +115,7 @@ module Jekyll
def safe_load_file(filename) def safe_load_file(filename)
case File.extname(filename) case File.extname(filename)
when /\.toml/i when /\.toml/i
Jekyll::External.require_with_graceful_fail('toml') unless defined?(TOML)
TOML.load_file(filename) TOML.load_file(filename)
when /\.ya?ml/i when /\.ya?ml/i
SafeYAML.load_file(filename) SafeYAML.load_file(filename)
@ -140,7 +137,7 @@ module Jekyll
config_files = override.delete('config') config_files = override.delete('config')
if config_files.to_s.empty? if config_files.to_s.empty?
default = %w[yml yaml].find(Proc.new { 'yml' }) do |ext| default = %w[yml yaml].find(Proc.new { 'yml' }) do |ext|
File.exists? Jekyll.sanitized_path(source(override), "_config.#{ext}") File.exist?(Jekyll.sanitized_path(source(override), "_config.#{ext}"))
end end
config_files = Jekyll.sanitized_path(source(override), "_config.#{default}") config_files = Jekyll.sanitized_path(source(override), "_config.#{default}")
@default_config_file = true @default_config_file = true
@ -209,7 +206,7 @@ module Jekyll
config = clone config = clone
# Provide backwards-compatibility # Provide backwards-compatibility
if config.key?('auto') || config.key?('watch') if config.key?('auto') || config.key?('watch')
Jekyll.logger.warn "Deprecation:", "Auto-regeneration can no longer" + Jekyll::Deprecator.deprecation_message "Auto-regeneration can no longer" +
" be set from your configuration file(s). Use the"+ " be set from your configuration file(s). Use the"+
" --[no-]watch/-w command-line option instead." " --[no-]watch/-w command-line option instead."
config.delete('auto') config.delete('auto')
@ -217,14 +214,14 @@ module Jekyll
end end
if config.key? 'server' if config.key? 'server'
Jekyll.logger.warn "Deprecation:", "The 'server' configuration option" + Jekyll::Deprecator.deprecation_message "The 'server' configuration option" +
" is no longer accepted. Use the 'jekyll serve'" + " is no longer accepted. Use the 'jekyll serve'" +
" subcommand to serve your site with WEBrick." " subcommand to serve your site with WEBrick."
config.delete('server') config.delete('server')
end end
if config.key? 'server_port' if config.key? 'server_port'
Jekyll.logger.warn "Deprecation:", "The 'server_port' configuration option" + Jekyll::Deprecator.deprecation_message "The 'server_port' configuration option" +
" has been renamed to 'port'. Please update your config" + " has been renamed to 'port'. Please update your config" +
" file accordingly." " file accordingly."
# copy but don't overwrite: # copy but don't overwrite:
@ -233,7 +230,7 @@ module Jekyll
end end
if config.key? 'pygments' if config.key? 'pygments'
Jekyll.logger.warn "Deprecation:", "The 'pygments' configuration option" + Jekyll::Deprecator.deprecation_message "The 'pygments' configuration option" +
" has been renamed to 'highlighter'. Please update your" + " has been renamed to 'highlighter'. Please update your" +
" config file accordingly. The allowed values are 'rouge', " + " config file accordingly. The allowed values are 'rouge', " +
"'pygments' or null." "'pygments' or null."
@ -244,7 +241,7 @@ module Jekyll
%w[include exclude].each do |option| %w[include exclude].each do |option|
if config.fetch(option, []).is_a?(String) if config.fetch(option, []).is_a?(String)
Jekyll.logger.warn "Deprecation:", "The '#{option}' configuration option" + Jekyll::Deprecator.deprecation_message "The '#{option}' configuration option" +
" must now be specified as an array, but you specified" + " must now be specified as an array, but you specified" +
" a string. For now, we've treated the string you provided" + " a string. For now, we've treated the string you provided" +
" as a list of comma-separated values." " as a list of comma-separated values."
@ -253,11 +250,23 @@ module Jekyll
config[option].map!(&:to_s) config[option].map!(&:to_s)
end end
if (config['kramdown'] || {}).key?('use_coderay')
Jekyll::Deprecator.deprecation_message "Please change 'use_coderay'" +
" to 'enable_coderay' in your configuration file."
config['kramdown']['use_coderay'] = config['kramdown'].delete('enable_coderay')
end
if config.fetch('markdown', 'kramdown').to_s.downcase.eql?("maruku") if config.fetch('markdown', 'kramdown').to_s.downcase.eql?("maruku")
Jekyll::Deprecator.deprecation_message "You're using the 'maruku' " + Jekyll::Deprecator.deprecation_message "You're using the 'maruku' " +
"Markdown processor. Maruku support has been deprecated and will " + "Markdown processor. Maruku support has been deprecated and will " +
"be removed in 3.0.0. We recommend you switch to Kramdown." "be removed in 3.0.0. We recommend you switch to Kramdown."
end end
if config.key?('paginate') && config['paginate'] && !(config['gems'] || []).include?('jekyll-paginate')
Jekyll::Deprecator.deprecation_message "You appear to have pagination " +
"turned on, but you haven't included the `jekyll-paginate` gem. " +
"Ensure you have `gems: [jekyll-paginate]` in your configuration file."
end
config config
end end

View File

@ -46,15 +46,12 @@ module Jekyll
].map(&:to_sym) ].map(&:to_sym)
end end
def extname_matches_regexp def extname_list
@extname_matches_regexp ||= Regexp.new( @extname_list ||= @config['markdown_ext'].split(',').map { |e| ".#{e.downcase}" }
'^\.(' + @config['markdown_ext'].gsub(',','|') +')$',
Regexp::IGNORECASE
)
end end
def matches(ext) def matches(ext)
ext =~ extname_matches_regexp extname_list.include? ext.downcase
end end
def output_ext(ext) def output_ext(ext)

View File

@ -13,14 +13,14 @@ module Jekyll
def convert(content) def convert(content)
# Check for use of coderay # Check for use of coderay
if @config['kramdown']['use_coderay'] if @config['kramdown']['enable_coderay']
%w[wrap line_numbers line_numbers_start tab_width bold_every css default_lang].each do |opt| %w[wrap line_numbers line_numbers_start tab_width bold_every css default_lang].each do |opt|
key = "coderay_#{opt}" key = "coderay_#{opt}"
@config['kramdown'][key] = @config['kramdown']['coderay'][key] unless @config['kramdown'].key?(key) @config['kramdown'][key] = @config['kramdown']['coderay'][key] unless @config['kramdown'].key?(key)
end end
end end
Kramdown::Document.new(content, Utils.symbolize_hash_keys(@config["kramdown"])).to_html Kramdown::Document.new(content, Utils.symbolize_hash_keys(@config['kramdown'])).to_html
end end
end end

View File

@ -3,7 +3,7 @@ module Jekyll
class Markdown class Markdown
class RDiscountParser class RDiscountParser
def initialize(config) def initialize(config)
Jekyll::Deprecator.gracefully_require "rdiscount" Jekyll::External.require_with_graceful_fail "rdiscount"
@config = config @config = config
@rdiscount_extensions = @config['rdiscount']['extensions'].map { |e| e.to_sym } @rdiscount_extensions = @config['rdiscount']['extensions'].map { |e| e.to_sym }
end end

View File

@ -14,7 +14,7 @@ module Jekyll
module WithPygments module WithPygments
include CommonMethods include CommonMethods
def block_code(code, lang) def block_code(code, lang)
Jekyll::Deprecator.gracefully_require("pygments") Jekyll::External.require_with_graceful_fail("pygments")
lang = lang && lang.split.first || "text" lang = lang && lang.split.first || "text"
add_code_tags( add_code_tags(
Pygments.highlight(code, :lexer => lang, :options => { :encoding => 'utf-8' }), Pygments.highlight(code, :lexer => lang, :options => { :encoding => 'utf-8' }),
@ -55,7 +55,7 @@ module Jekyll
def initialize(config) def initialize(config)
Deprecator.gracefully_require("redcarpet") External.require_with_graceful_fail("redcarpet")
@config = config @config = config
@redcarpet_extensions = {} @redcarpet_extensions = {}
@config['redcarpet']['extensions'].each { |e| @redcarpet_extensions[e.to_sym] = true } @config['redcarpet']['extensions'].each { |e| @redcarpet_extensions[e.to_sym] = true }
@ -71,7 +71,7 @@ module Jekyll
end end
when "rouge" when "rouge"
Class.new(Redcarpet::Render::HTML) do Class.new(Redcarpet::Render::HTML) do
Jekyll::Deprecator.gracefully_require(%w[ Jekyll::External.require_with_graceful_fail(%w[
rouge rouge
rouge/plugins/redcarpet rouge/plugins/redcarpet
]) ])

View File

@ -1,56 +0,0 @@
module Jekyll
module Converters
class Textile < Converter
safe true
highlighter_prefix '<notextile>'
highlighter_suffix '</notextile>'
def setup
return if @setup
require 'redcloth'
@setup = true
rescue LoadError
STDERR.puts 'You are missing a library required for Textile. Please run:'
STDERR.puts ' $ [sudo] gem install RedCloth'
raise Errors::FatalException.new("Missing dependency: RedCloth")
end
def extname_matches_regexp
@extname_matches_regexp ||= Regexp.new(
'(' + @config['textile_ext'].gsub(',','|') +')$',
Regexp::IGNORECASE
)
end
def matches(ext)
ext =~ extname_matches_regexp
end
def output_ext(ext)
".html"
end
def convert(content)
setup
# Shortcut if config doesn't contain RedCloth section
return RedCloth.new(content).to_html if @config['redcloth'].nil?
# List of attributes defined on RedCloth
# (from https://github.com/jgarber/redcloth/blob/master/lib/redcloth/textile_doc.rb)
attrs = ['filter_classes', 'filter_html', 'filter_ids', 'filter_styles',
'hard_breaks', 'lite_mode', 'no_span_caps', 'sanitize_html']
r = RedCloth.new(content)
# Set attributes in r if they are NOT nil in the config
attrs.each do |attr|
r.instance_variable_set("@#{attr}".to_sym, @config['redcloth'][attr]) unless @config['redcloth'][attr].nil?
end
r.to_html
end
end
end
end

View File

@ -207,6 +207,12 @@ module Jekyll
info, info,
File.join(site.config['layouts'], layout.name)) File.join(site.config['layouts'], layout.name))
# Add layout to dependency tree
site.regenerator.add_dependency(
site.in_source_dir(path),
site.in_source_dir(layout.path)
)
if layout = layouts[layout.data["layout"]] if layout = layouts[layout.data["layout"]]
if used.include?(layout) if used.include?(layout)
layout = nil # avoid recursive chain layout = nil # avoid recursive chain

View File

@ -21,7 +21,7 @@ module Jekyll
def no_subcommand(args) def no_subcommand(args)
if args.size > 0 && args.first =~ /^--/ && !%w[--help --version].include?(args.first) if args.size > 0 && args.first =~ /^--/ && !%w[--help --version].include?(args.first)
deprecation_message "Jekyll now uses subcommands instead of just \ deprecation_message "Jekyll now uses subcommands instead of just \
switches. Run `jekyll --help' to find out more." switches. Run `jekyll --help` to find out more."
end end
end end
@ -40,22 +40,5 @@ module Jekyll
Jekyll.logger.warn "Defaults:", "Please update your front-matter defaults to use 'type: #{current}'." Jekyll.logger.warn "Defaults:", "Please update your front-matter defaults to use 'type: #{current}'."
end end
def gracefully_require(gem_name)
Array(gem_name).each do |name|
begin
require name
rescue LoadError => e
Jekyll.logger.error "Dependency Error:", <<-MSG
Yikes! It looks like you don't have #{name} or one of its dependencies installed.
In order to use Jekyll as currently configured, you'll need to install this gem.
The full error message from Ruby is: '#{e.message}'
If you run into trouble, you can find helpful resources at http://jekyllrb.com/help/!
MSG
raise Errors::MissingDependencyException.new(name)
end
end
end
end end
end end

View File

@ -4,9 +4,11 @@ module Jekyll
class Document class Document
include Comparable include Comparable
attr_reader :path, :site, :extname attr_reader :path, :site, :extname, :output_ext
attr_accessor :content, :collection, :output attr_accessor :content, :collection, :output
YAML_FRONT_MATTER_REGEXP = /\A(---\s*\n.*?\n?)^((---|\.\.\.)\s*$\n?)/m
# Create a new Document. # Create a new Document.
# #
# site - the Jekyll::Site instance to which this Document belongs # site - the Jekyll::Site instance to which this Document belongs
@ -17,6 +19,7 @@ module Jekyll
@site = relations[:site] @site = relations[:site]
@path = path @path = path
@extname = File.extname(path) @extname = File.extname(path)
@output_ext = Jekyll::Renderer.new(site, self).output_ext
@collection = relations[:collection] @collection = relations[:collection]
@has_yaml_header = nil @has_yaml_header = nil
end end
@ -128,9 +131,9 @@ module Jekyll
{ {
collection: collection.label, collection: collection.label,
path: cleaned_relative_path, path: cleaned_relative_path,
output_ext: Jekyll::Renderer.new(site, self).output_ext, output_ext: output_ext,
name: Utils.slugify(basename_without_ext), name: Utils.slugify(basename_without_ext),
title: Utils.slugify(data['title']) || Utils.slugify(basename_without_ext) title: Utils.slugify(data['slug']) || Utils.slugify(basename_without_ext)
} }
end end
@ -160,8 +163,9 @@ module Jekyll
# Returns the full path to the output file of this document. # Returns the full path to the output file of this document.
def destination(base_directory) def destination(base_directory)
dest = site.in_dest_dir(base_directory) dest = site.in_dest_dir(base_directory)
path = site.in_dest_dir(dest, url) path = site.in_dest_dir(dest, URL.unescape_path(url))
path = File.join(path, "index.html") if url =~ /\/$/ path = File.join(path, "index.html") if url.end_with?("/")
path << output_ext unless path.end_with?(output_ext)
path path
end end
@ -210,7 +214,7 @@ module Jekyll
@data = defaults @data = defaults
end end
@content = File.read(path, merged_file_read_opts(opts)) @content = File.read(path, merged_file_read_opts(opts))
if content =~ /\A(---\s*\n.*?\n?)^(---\s*$\n?)/m if content =~ YAML_FRONT_MATTER_REGEXP
@content = $POSTMATCH @content = $POSTMATCH
data_file = SafeYAML.load($1) data_file = SafeYAML.load($1)
unless data_file.nil? unless data_file.nil?
@ -233,8 +237,8 @@ module Jekyll
Utils.deep_merge_hashes data, { Utils.deep_merge_hashes data, {
"output" => output, "output" => output,
"content" => content, "content" => content,
"path" => path,
"relative_path" => relative_path, "relative_path" => relative_path,
"path" => relative_path,
"url" => url, "url" => url,
"collection" => collection.label "collection" => collection.label
} }

View File

@ -105,8 +105,7 @@ module Jekyll
# #
# Returns excerpt String # Returns excerpt String
def extract_excerpt(post_content) def extract_excerpt(post_content)
separator = site.config['excerpt_separator'] head, _, tail = post_content.to_s.partition(post.excerpt_separator)
head, _, tail = post_content.to_s.partition(separator)
"" << head << "\n\n" << tail.scan(/^\[[^\]]+\]:.+$/).join("\n") "" << head << "\n\n" << tail.scan(/^\[[^\]]+\]:.+$/).join("\n")
end end

59
lib/jekyll/external.rb Normal file
View File

@ -0,0 +1,59 @@
module Jekyll
module External
class << self
#
# Gems that, if installed, should be loaded.
# Usually contain subcommands.
#
def blessed_gems
%w{
jekyll-docs
jekyll-import
}
end
#
# Require a gem or file if it's present, otherwise silently fail.
#
# names - a string gem name or array of gem names
#
def require_if_present(names)
Array(names).each do |name|
begin
require name
rescue LoadError
Jekyll.logger.debug "Couldn't load #{name}. Skipping."
false
end
end
end
#
# Require a gem or gems. If it's not present, show a very nice error
# message that explains everything and is much more helpful than the
# normal LoadError.
#
# names - a string gem name or array of gem names
#
def require_with_graceful_fail(names)
Array(names).each do |name|
begin
require name
rescue LoadError => e
Jekyll.logger.error "Dependency Error:", <<-MSG
Yikes! It looks like you don't have #{name} or one of its dependencies installed.
In order to use Jekyll as currently configured, you'll need to install this gem.
The full error message from Ruby is: '#{e.message}'
If you run into trouble, you can find helpful resources at http://jekyllrb.com/help/!
MSG
raise Jekyll::Errors::MissingDependencyException.new(name)
end
end
end
end
end
end

View File

@ -1,19 +1,9 @@
require 'uri' require 'uri'
require 'json' require 'json'
require 'date'
module Jekyll module Jekyll
module Filters module Filters
# Convert a Textile string into HTML output.
#
# input - The Textile String to convert.
#
# Returns the HTML formatted String.
def textilize(input)
site = @context.registers[:site]
converter = site.getConverterImpl(Jekyll::Converters::Textile)
converter.convert(input)
end
# Convert a Markdown string into HTML output. # Convert a Markdown string into HTML output.
# #
# input - The Markdown String to convert. # input - The Markdown String to convert.
@ -21,7 +11,7 @@ module Jekyll
# Returns the HTML formatted String. # Returns the HTML formatted String.
def markdownify(input) def markdownify(input)
site = @context.registers[:site] site = @context.registers[:site]
converter = site.getConverterImpl(Jekyll::Converters::Markdown) converter = site.find_converter_instance(Jekyll::Converters::Markdown)
converter.convert(input) converter.convert(input)
end end
@ -32,7 +22,7 @@ module Jekyll
# Returns the CSS formatted String. # Returns the CSS formatted String.
def sassify(input) def sassify(input)
site = @context.registers[:site] site = @context.registers[:site]
converter = site.getConverterImpl(Jekyll::Converters::Sass) converter = site.find_converter_instance(Jekyll::Converters::Sass)
converter.convert(input) converter.convert(input)
end end
@ -43,19 +33,19 @@ module Jekyll
# Returns the CSS formatted String. # Returns the CSS formatted String.
def scssify(input) def scssify(input)
site = @context.registers[:site] site = @context.registers[:site]
converter = site.getConverterImpl(Jekyll::Converters::Scss) converter = site.find_converter_instance(Jekyll::Converters::Scss)
converter.convert(input) converter.convert(input)
end end
# Slugify a filename or title. # Slugify a filename or title.
# #
# input - The filename or title to slugify. # input - The filename or title to slugify.
# mode - how string is slugified
# #
# Returns the given filename or title as a lowercase String, with every # Returns the given filename or title as a lowercase URL String.
# sequence of spaces and non-alphanumeric characters replaced with a # See Utils.slugify for more detail.
# hyphen. def slugify(input, mode=nil)
def slugify(input) Utils.slugify(input, mode)
Utils.slugify(input)
end end
# Format a date in short format e.g. "27 Jan 2011". # Format a date in short format e.g. "27 Jan 2011".
@ -232,6 +222,9 @@ module Jekyll
# #
# Returns the filtered array of objects # Returns the filtered array of objects
def sort(input, property = nil, nils = "first") def sort(input, property = nil, nils = "first")
if input.nil?
raise ArgumentError.new("Cannot sort a null object.")
end
if property.nil? if property.nil?
input.sort input.sort
else else
@ -302,6 +295,8 @@ module Jekyll
case input case input
when Time when Time
input input
when Date
input.to_time
when String when String
Time.parse(input) rescue Time.at(input.to_i) Time.parse(input) rescue Time.at(input.to_i)
when Numeric when Numeric
@ -309,7 +304,7 @@ module Jekyll
else else
Jekyll.logger.error "Invalid Date:", "'#{input}' is not a valid datetime." Jekyll.logger.error "Invalid Date:", "'#{input}' is not a valid datetime."
exit(1) exit(1)
end end.localtime
end end
def groupable?(element) def groupable?(element)
@ -328,14 +323,23 @@ module Jekyll
def as_liquid(item) def as_liquid(item)
case item case item
when String, Numeric, true, false, nil
item.to_liquid
when Hash when Hash
Hash[item.map { |k, v| [as_liquid(k), as_liquid(v)] }] pairs = item.map { |k, v| as_liquid([k, v]) }
Hash[pairs]
when Array when Array
item.map{ |i| as_liquid(i) } item.map{ |i| as_liquid(i) }
else else
item.respond_to?(:to_liquid) ? as_liquid(item.to_liquid) : item if item.respond_to?(:to_liquid)
liquidated = item.to_liquid
# prevent infinite recursion for simple types (which return `self`)
if liquidated == item
item
else
as_liquid(liquidated)
end
else
item
end
end end
end end
end end

View File

@ -168,7 +168,7 @@ module Jekyll
end.compact end.compact
end end
# Sanitizes the given path by removing a leading and addding a trailing slash # Sanitizes the given path by removing a leading and adding a trailing slash
def sanitize_path(path) def sanitize_path(path)
if path.nil? || path.empty? if path.nil? || path.empty?
"" ""

View File

@ -8,6 +8,9 @@ module Jekyll
# Gets the name of this layout. # Gets the name of this layout.
attr_reader :name attr_reader :name
# Gets the path to this layout.
attr_reader :path
# Gets/Sets the extension of this layout. # Gets/Sets the extension of this layout.
attr_accessor :ext attr_accessor :ext
@ -26,6 +29,7 @@ module Jekyll
@site = site @site = site
@base = base @base = base
@name = name @name = name
@path = site.in_source_dir(base, name)
self.data = {} self.data = {}

View File

@ -1,6 +1,6 @@
module Jekyll module Jekyll
class LogAdapter class LogAdapter
attr_reader :writer attr_reader :writer, :messages
LOG_LEVELS = { LOG_LEVELS = {
:debug => ::Logger::DEBUG, :debug => ::Logger::DEBUG,
@ -16,6 +16,7 @@ module Jekyll
# #
# Returns nothing # Returns nothing
def initialize(writer, level = :info) def initialize(writer, level = :info)
@messages = []
@writer = writer @writer = writer
self.log_level = level self.log_level = level
end end
@ -87,7 +88,9 @@ module Jekyll
# #
# Returns the formatted message # Returns the formatted message
def message(topic, message) def message(topic, message)
formatted_topic(topic) + message.to_s.gsub(/\s+/, ' ') msg = formatted_topic(topic) + message.to_s.gsub(/\s+/, ' ')
messages << msg
msg
end end
# Internal: Format the topic # Internal: Format the topic

View File

@ -63,16 +63,12 @@ module Jekyll
# #
# Returns the template String. # Returns the template String.
def template def template
if site.permalink_style == :pretty if !html?
if index? && html? "/:path/:basename:output_ext"
elsif index?
"/:path/" "/:path/"
elsif html?
"/:path/:basename/"
else else
"/:path/:basename:output_ext" Utils.add_permalink_suffix("/:path/:basename", site.permalink_style)
end
else
"/:path/:basename:output_ext"
end end
end end
@ -141,7 +137,8 @@ module Jekyll
# Returns the destination file path String. # Returns the destination file path String.
def destination(dest) def destination(dest)
path = site.in_dest_dir(dest, URL.unescape_path(url)) path = site.in_dest_dir(dest, URL.unescape_path(url))
path = File.join(path, "index.html") if url =~ /\/$/ path = File.join(path, "index.html") if url.end_with?("/")
path << output_ext unless path.end_with?(output_ext)
path path
end end

View File

@ -23,6 +23,8 @@ module Jekyll
ATTRIBUTES_FOR_LIQUID = EXCERPT_ATTRIBUTES_FOR_LIQUID + %w[ ATTRIBUTES_FOR_LIQUID = EXCERPT_ATTRIBUTES_FOR_LIQUID + %w[
content content
excerpt excerpt
excerpt_separator
draft?
] ]
# Post name validator. Post filenames must be like: # Post name validator. Post filenames must be like:
@ -52,12 +54,12 @@ module Jekyll
@base = containing_dir(dir) @base = containing_dir(dir)
@name = name @name = name
self.categories = dir.downcase.split('/').reject { |x| x.empty? } self.categories = dir.split('/').reject { |x| x.empty? }
process(name) process(name)
read_yaml(@base, name) read_yaml(@base, name)
data.default_proc = proc do |hash, key| data.default_proc = proc do |hash, key|
site.frontmatter_defaults.find(File.join(dir, name), type, key) site.frontmatter_defaults.find(relative_path, type, key)
end end
if data.key?('date') if data.key?('date')
@ -80,7 +82,7 @@ module Jekyll
categories_from_data = Utils.pluralized_array_from_hash(data, 'category', 'categories') categories_from_data = Utils.pluralized_array_from_hash(data, 'category', 'categories')
self.categories = ( self.categories = (
Array(categories) + categories_from_data Array(categories) + categories_from_data
).map {|c| c.to_s.downcase}.flatten.uniq ).map { |c| c.to_s }.flatten.uniq
end end
def populate_tags def populate_tags
@ -118,6 +120,14 @@ module Jekyll
data.fetch('title') { titleized_slug } data.fetch('title') { titleized_slug }
end end
# Public: the Post excerpt_separator, from the YAML Front-Matter or site default
# excerpt_separator value
#
# Returns the post excerpt_separator
def excerpt_separator
(data['excerpt_separator'] || site.config['excerpt_separator']).to_s
end
# Turns the post slug into a suitable title # Turns the post slug into a suitable title
def titleized_slug def titleized_slug
slug.split('-').select {|w| w.capitalize! || w }.join(' ') slug.split('-').select {|w| w.capitalize! || w }.join(' ')
@ -218,7 +228,7 @@ module Jekyll
:title => slug, :title => slug,
:i_day => date.strftime("%-d"), :i_day => date.strftime("%-d"),
:i_month => date.strftime("%-m"), :i_month => date.strftime("%-m"),
:categories => (categories || []).map { |c| c.to_s }.join('/'), :categories => (categories || []).map { |c| c.to_s.downcase }.uniq.join('/'),
:short_month => date.strftime("%b"), :short_month => date.strftime("%b"),
:short_year => date.strftime("%y"), :short_year => date.strftime("%y"),
:y_day => date.strftime("%j"), :y_day => date.strftime("%j"),
@ -269,7 +279,8 @@ module Jekyll
def destination(dest) def destination(dest)
# The url needs to be unescaped in order to preserve the correct filename # The url needs to be unescaped in order to preserve the correct filename
path = site.in_dest_dir(dest, URL.unescape_path(url)) path = site.in_dest_dir(dest, URL.unescape_path(url))
path = File.join(path, "index.html") if path[/\.html?$/].nil? path = File.join(path, "index.html") if self.url.end_with?("/")
path << output_ext unless path.end_with?(output_ext)
path path
end end
@ -296,6 +307,11 @@ module Jekyll
end end
end end
# Returns if this Post is a Draft
def draft?
is_a?(Jekyll::Draft)
end
protected protected
def extract_excerpt def extract_excerpt
@ -307,7 +323,7 @@ module Jekyll
end end
def generate_excerpt? def generate_excerpt?
!(site.config['excerpt_separator'].to_s.empty?) !excerpt_separator.empty?
end end
end end
end end

141
lib/jekyll/regenerator.rb Normal file
View File

@ -0,0 +1,141 @@
module Jekyll
class Regenerator
attr_reader :site, :metadata, :cache
def initialize(site)
@site = site
# Read metadata from file
read_metadata
# Initialize cache to an empty hash
@cache = {}
end
# Checks if a renderable object needs to be regenerated
#
# Returns a boolean.
def regenerate?(document)
case document
when Post, Page
document.asset_file? || document.data['regenerate'] ||
modified?(site.in_source_dir(document.relative_path))
when Document
!document.write? || document.data['regenerate'] || modified?(document.path)
else
if document.respond_to?(:path)
modified?(document.path)
else
true
end
end
end
# Add a path to the metadata
#
# Returns true, also on failure.
def add(path)
return true unless File.exist?(path)
metadata[path] = {
"mtime" => File.mtime(path),
"deps" => []
}
cache[path] = true
end
# Force a path to regenerate
#
# Returns true.
def force(path)
cache[path] = true
end
# Clear the metadata and cache
#
# Returns nothing
def clear
@metadata = {}
@cache = {}
end
# Checks if a path's (or one of its dependencies)
# mtime has changed
#
# Returns a boolean.
def modified?(path)
return true if disabled?
# Check for path in cache
if cache.has_key? path
return cache[path]
end
# Check path that exists in metadata
data = metadata[path]
if data
data["deps"].each do |dependency|
if modified?(dependency)
return cache[dependency] = cache[path] = true
end
end
if data["mtime"].eql? File.mtime(path)
return cache[path] = false
else
return add(path)
end
end
# Path does not exist in metadata, add it
return add(path)
end
# Add a dependency of a path
#
# Returns nothing.
def add_dependency(path, dependency)
return if (metadata[path].nil? || @disabled)
metadata[path]["deps"] << dependency unless metadata[path]["deps"].include? dependency
regenerate? dependency
end
# Write the metadata to disk
#
# Returns nothing.
def write_metadata
File.open(metadata_file, 'w') do |f|
f.write(metadata.to_yaml)
end
end
# Produce the absolute path of the metadata file
#
# Returns the String path of the file.
def metadata_file
site.in_source_dir('.jekyll-metadata')
end
# Check if metadata has been disabled
#
# Returns a Boolean (true for disabled, false for enabled).
def disabled?
@disabled = site.full_rebuild? if @disabled.nil?
@disabled
end
private
# Read metadata from the metadata file, if no file is found,
# initialize with an empty hash
#
# Returns the read metadata.
def read_metadata
@metadata = if !disabled? && File.file?(metadata_file)
SafeYAML.load(File.read(metadata_file))
else
{}
end
end
end
end

View File

@ -10,7 +10,7 @@ module Jekyll
def initialize(post) def initialize(post)
@post = post @post = post
@site = post.site @site = post.site
require 'classifier-reborn' if site.lsi Jekyll::External.require_with_graceful_fail('classifier-reborn') if site.lsi
end end
def build def build

View File

@ -3,11 +3,12 @@
module Jekyll module Jekyll
class Renderer class Renderer
attr_reader :document, :site attr_reader :document, :site, :site_payload
def initialize(site, document) def initialize(site, document, site_payload = nil)
@site = site @site = site
@document = document @document = document
@site_payload = site_payload
end end
# Determine which converters to use based on this document's # Determine which converters to use based on this document's
@ -32,7 +33,7 @@ module Jekyll
def run def run
payload = Utils.deep_merge_hashes({ payload = Utils.deep_merge_hashes({
"page" => document.to_liquid "page" => document.to_liquid
}, site.site_payload) }, site_payload || site.site_payload)
info = { info = {
filters: [Jekyll::Filters], filters: [Jekyll::Filters],
@ -138,6 +139,12 @@ module Jekyll
File.join(site.config['layouts'], layout.name) File.join(site.config['layouts'], layout.name)
) )
# Add layout to dependency tree
site.regenerator.add_dependency(
site.in_source_dir(document.path),
site.in_source_dir(layout.path)
) if document.write?
if layout = site.layouts[layout.data["layout"]] if layout = site.layouts[layout.data["layout"]]
if used.include?(layout) if used.include?(layout)
layout = nil # avoid recursive chain layout = nil # avoid recursive chain

View File

@ -11,6 +11,7 @@ module Jekyll
:gems, :plugin_manager :gems, :plugin_manager
attr_accessor :converters, :generators attr_accessor :converters, :generators
attr_reader :regenerator
# Public: Initialize a new Site. # Public: Initialize a new Site.
# #
@ -27,6 +28,9 @@ module Jekyll
@source = File.expand_path(config['source']).freeze @source = File.expand_path(config['source']).freeze
@dest = File.expand_path(config['destination']).freeze @dest = File.expand_path(config['destination']).freeze
# Initialize incremental regenerator
@regenerator = Regenerator.new(self)
self.plugin_manager = Jekyll::PluginManager.new(self) self.plugin_manager = Jekyll::PluginManager.new(self)
self.plugins = plugin_manager.plugins_path self.plugins = plugin_manager.plugins_path
@ -183,6 +187,7 @@ module Jekyll
end end
pages.sort_by!(&:name) pages.sort_by!(&:name)
static_files.sort_by!(&:relative_path)
end end
# Read all the files in <source>/<dir>/_posts and create a new Post # Read all the files in <source>/<dir>/_posts and create a new Post
@ -253,13 +258,23 @@ module Jekyll
if File.directory?(path) if File.directory?(path)
read_data_to(path, data[key] = {}) read_data_to(path, data[key] = {})
else else
data[key] = read_data_file(path)
end
end
end
# Determines how to read a data file.
#
# Returns the contents of the data file.
def read_data_file(path)
case File.extname(path).downcase case File.extname(path).downcase
when '.csv' when '.csv'
data[key] = CSV.read(path, :headers => true).map(&:to_hash) CSV.read(path, {
:headers => true,
:encoding => config['encoding']
}).map(&:to_hash)
else else
data[key] = SafeYAML.load_file(path) SafeYAML.load_file(path)
end
end
end end
end end
@ -287,17 +302,22 @@ module Jekyll
def render def render
relative_permalinks_deprecation_method relative_permalinks_deprecation_method
payload = site_payload
collections.each do |label, collection| collections.each do |label, collection|
collection.docs.each do |document| collection.docs.each do |document|
document.output = Jekyll::Renderer.new(self, document).run if regenerator.regenerate?(document)
document.output = Jekyll::Renderer.new(self, document, payload).run
end
end end
end end
payload = site_payload payload = site_payload
[posts, pages].flatten.each do |page_or_post| [posts, pages].flatten.each do |page_or_post|
if regenerator.regenerate?(page_or_post)
page_or_post.render(layouts, payload) page_or_post.render(layouts, payload)
end end
rescue Errno::ENOENT => e end
rescue Errno::ENOENT
# ignore missing layout dir # ignore missing layout dir
end end
@ -312,7 +332,10 @@ module Jekyll
# #
# Returns nothing. # Returns nothing.
def write def write
each_site_file { |item| item.write(dest) } each_site_file { |item|
item.write(dest) if regenerator.regenerate?(item)
}
regenerator.write_metadata
end end
# Construct a Hash of Posts indexed by the specified Post attribute. # Construct a Hash of Posts indexed by the specified Post attribute.
@ -377,7 +400,7 @@ module Jekyll
"time" => time, "time" => time,
"posts" => posts.sort { |a, b| b <=> a }, "posts" => posts.sort { |a, b| b <=> a },
"pages" => pages, "pages" => pages,
"static_files" => static_files.sort { |a, b| a.relative_path <=> b.relative_path }, "static_files" => static_files,
"html_pages" => pages.select { |page| page.html? || page.url.end_with?("/") }, "html_pages" => pages.select { |page| page.html? || page.url.end_with?("/") },
"categories" => post_attr_hash('categories'), "categories" => post_attr_hash('categories'),
"tags" => post_attr_hash('tags'), "tags" => post_attr_hash('tags'),
@ -405,13 +428,8 @@ module Jekyll
# klass - The Class of the Converter to fetch. # klass - The Class of the Converter to fetch.
# #
# Returns the Converter instance implementing the given Converter. # Returns the Converter instance implementing the given Converter.
def getConverterImpl(klass) def find_converter_instance(klass)
matches = converters.select { |c| c.class == klass } converters.find { |c| c.class == klass } || proc { raise "No converter for #{klass}" }.call
if impl = matches.first
impl
else
raise "Converter implementation not found for #{klass}"
end
end end
# Create array of instances of the subclasses of the class or module # Create array of instances of the subclasses of the class or module
@ -453,7 +471,7 @@ module Jekyll
def relative_permalinks_deprecation_method def relative_permalinks_deprecation_method
if config['relative_permalinks'] && has_relative_page? if config['relative_permalinks'] && has_relative_page?
Jekyll.logger.warn "Deprecation:", "Starting in 2.0, permalinks for pages" + Jekyll::Deprecator.deprecation_message "Since v2.0, permalinks for pages" +
" in subfolders must be relative to the" + " in subfolders must be relative to the" +
" site source directory, not the parent" + " site source directory, not the parent" +
" directory. Check http://jekyllrb.com/docs/upgrading/"+ " directory. Check http://jekyllrb.com/docs/upgrading/"+
@ -483,6 +501,17 @@ module Jekyll
@frontmatter_defaults ||= FrontmatterDefaults.new(self) @frontmatter_defaults ||= FrontmatterDefaults.new(self)
end end
# Whether to perform a full rebuild without incremental regeneration
#
# Returns a Boolean: true for a full rebuild, false for normal build
def full_rebuild?(override = {})
override['full_rebuild'] || config['full_rebuild']
end
def publisher
@publisher ||= Publisher.new(self)
end
private private
def has_relative_page? def has_relative_page?
@ -499,13 +528,9 @@ module Jekyll
end end
def sanitize_filename(name) def sanitize_filename(name)
name.gsub!(/[^\w\s_-]+/, '') name.gsub!(/[^\w\s-]+/, '')
name.gsub!(/(^|\b\s)\s+($|\s?\b)/, '\\1\\2') name.gsub!(/(^|\b\s)\s+($|\s?\b)/, '\\1\\2')
name.gsub(/\s+/, '_') name.gsub(/\s+/, '_')
end end
def publisher
@publisher ||= Publisher.new(self)
end
end end
end end

View File

@ -3,6 +3,8 @@ module Jekyll
# The cache of last modification times [path] -> mtime. # The cache of last modification times [path] -> mtime.
@@mtimes = Hash.new @@mtimes = Hash.new
attr_reader :relative_path
# Initialize a new StaticFile. # Initialize a new StaticFile.
# #
# site - The Site. # site - The Site.
@ -15,6 +17,7 @@ module Jekyll
@dir = dir @dir = dir
@name = name @name = name
@collection = collection @collection = collection
@relative_path = File.join(*[@dir, @name].compact)
end end
# Returns source file path. # Returns source file path.
@ -22,11 +25,6 @@ module Jekyll
File.join(*[@base, @dir, @name].compact) File.join(*[@base, @dir, @name].compact)
end end
# Returns the source file path relative to the site source
def relative_path
@relative_path ||= File.join(*[@dir, @name].compact)
end
def extname def extname
File.extname(path) File.extname(path)
end end
@ -81,6 +79,7 @@ module Jekyll
FileUtils.mkdir_p(File.dirname(dest_path)) FileUtils.mkdir_p(File.dirname(dest_path))
FileUtils.rm(dest_path) if File.exist?(dest_path) FileUtils.rm(dest_path) if File.exist?(dest_path)
FileUtils.cp(path, dest_path) FileUtils.cp(path, dest_path)
File.utime(@@mtimes[path], @@mtimes[path], dest_path)
true true
end end

View File

@ -42,7 +42,7 @@ eos
def render(context) def render(context)
prefix = context["highlighter_prefix"] || "" prefix = context["highlighter_prefix"] || ""
suffix = context["highlighter_suffix"] || "" suffix = context["highlighter_suffix"] || ""
code = super.to_s.strip code = super.to_s.gsub(/\A(\n|\r)+|(\n|\r)+\z/, '')
is_safe = !!context.registers[:site].safe is_safe = !!context.registers[:site].safe
@ -75,9 +75,7 @@ eos
end end
def render_pygments(code, is_safe) def render_pygments(code, is_safe)
require 'pygments' Jekyll::External.require_with_graceful_fail('pygments')
@options[:encoding] = 'utf-8'
highlighted_code = Pygments.highlight( highlighted_code = Pygments.highlight(
code, code,
@ -96,26 +94,26 @@ eos
raise ArgumentError.new("Pygments.rb returned an unacceptable value when attempting to highlight some code.") raise ArgumentError.new("Pygments.rb returned an unacceptable value when attempting to highlight some code.")
end end
highlighted_code highlighted_code.sub('<div class="highlight"><pre>', '').sub('</pre></div>', '')
end end
def render_rouge(code) def render_rouge(code)
require 'rouge' Jekyll::External.require_with_graceful_fail('rouge')
formatter = Rouge::Formatters::HTML.new(line_numbers: @options[:linenos], wrap: false) formatter = Rouge::Formatters::HTML.new(line_numbers: @options[:linenos], wrap: false)
lexer = Rouge::Lexer.find_fancy(@lang, code) || Rouge::Lexers::PlainText lexer = Rouge::Lexer.find_fancy(@lang, code) || Rouge::Lexers::PlainText
code = formatter.format(lexer.lex(code)) formatter.format(lexer.lex(code))
"<div class=\"highlight\"><pre>#{code}</pre></div>"
end end
def render_codehighlighter(code) def render_codehighlighter(code)
"<div class=\"highlight\"><pre>#{h(code).strip}</pre></div>" h(code).strip
end end
def add_code_tag(code) def add_code_tag(code)
# Add nested <code> tags to code blocks code_attributes = [
code = code.sub(/<pre>\n*/,'<pre><code class="language-' + @lang.to_s.gsub("+", "-") + '" data-lang="' + @lang.to_s + '">') "class=\"language-#{@lang.to_s.gsub('+', '-')}\"",
code = code.sub(/\n*<\/pre>/,"</code></pre>") "data-lang=\"#{@lang.to_s}\""
code.strip ].join(" ")
"<div class=\"highlight\"><pre><code #{code_attributes}>#{code.chomp}</code></pre></div>"
end end
end end

View File

@ -101,20 +101,29 @@ eos
end end
def tag_includes_dir def tag_includes_dir
'_includes' '_includes'.freeze
end end
def render(context) def render(context)
site = context.registers[:site]
dir = resolved_includes_dir(context) dir = resolved_includes_dir(context)
file = render_variable(context) || @file file = render_variable(context) || @file
validate_file_name(file) validate_file_name(file)
path = File.join(dir, file) path = File.join(dir, file)
validate_path(path, dir, context.registers[:site].safe) validate_path(path, dir, site.safe)
# Add include to dependency tree
if context.registers[:page] and context.registers[:page].has_key? "path"
site.regenerator.add_dependency(
site.in_source_dir(context.registers[:page]["path"]),
path
)
end
begin begin
partial = Liquid::Template.parse(source(path, context)) partial = Liquid::Template.parse(read_file(path, context))
context.stack do context.stack do
context['include'] = parse_params(context) if @params context['include'] = parse_params(context) if @params
@ -126,7 +135,7 @@ eos
end end
def resolved_includes_dir(context) def resolved_includes_dir(context)
File.join(File.realpath(context.registers[:site].source), @includes_dir) context.registers[:site].in_source_dir(@includes_dir)
end end
def validate_path(path, dir, safe) def validate_path(path, dir, safe)
@ -146,14 +155,14 @@ eos
end end
# This method allows to modify the file content by inheriting from the class. # This method allows to modify the file content by inheriting from the class.
def source(file, context) def read_file(file, context)
File.read(file, file_read_opts(context)) File.read(file, file_read_opts(context))
end end
end end
class IncludeRelativeTag < IncludeTag class IncludeRelativeTag < IncludeTag
def tag_includes_dir def tag_includes_dir
'.' '.'.freeze
end end
def page_path(context) def page_path(context)

View File

@ -44,12 +44,12 @@ module Jekyll
# #
# Returns the _unsanitized String URL # Returns the _unsanitized String URL
def generated_permalink def generated_permalink
(@generated_permlink ||= generate_url(@permalink)) if @permalink (@generated_permalink ||= generate_url(@permalink)) if @permalink
end end
# Generates a URL from the template # Generates a URL from the template
# #
# Returns the _unsanitized String URL # Returns the unsanitized String URL
def generated_url def generated_url
@generated_url ||= generate_url(@template) @generated_url ||= generate_url(@template)
end end
@ -57,13 +57,18 @@ module Jekyll
# Internal: Generate the URL by replacing all placeholders with their # Internal: Generate the URL by replacing all placeholders with their
# respective values in the given template # respective values in the given template
# #
# Returns the _unsanitizied_ String URL # Returns the unsanitized String URL
def generate_url(template) def generate_url(template)
@placeholders.inject(template) do |result, token| @placeholders.inject(template) do |result, token|
break result if result.index(':').nil? break result if result.index(':').nil?
if token.last.nil?
# Remove leading '/' to avoid generating urls with `//`
result.gsub(/\/:#{token.first}/, '')
else
result.gsub(/:#{token.first}/, self.class.escape_path(token.last)) result.gsub(/:#{token.first}/, self.class.escape_path(token.last))
end end
end end
end
# Returns a sanitized String URL # Returns a sanitized String URL
def sanitize_url(in_url) def sanitize_url(in_url)
@ -76,7 +81,7 @@ module Jekyll
.gsub(/\A([^\/])/, '/\1') .gsub(/\A([^\/])/, '/\1')
# Append a trailing slash to the URL if the unsanitized URL had one # Append a trailing slash to the URL if the unsanitized URL had one
url << "/" if in_url[-1].eql?('/') url << "/" if in_url.end_with?("/")
url url
end end
@ -102,7 +107,7 @@ module Jekyll
# pct-encoded = "%" HEXDIG HEXDIG # pct-encoded = "%" HEXDIG HEXDIG
# sub-delims = "!" / "$" / "&" / "'" / "(" / ")" # sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
# / "*" / "+" / "," / ";" / "=" # / "*" / "+" / "," / ";" / "="
URI.escape(path, /[^a-zA-Z\d\-._~!$&\'()*+,;=:@\/]/).encode('utf-8') URI.escape(path, /[^a-zA-Z\d\-._~!$&'()*+,;=:@\/]/).encode('utf-8')
end end
# Unescapes a URL path segment # Unescapes a URL path segment

View File

@ -2,6 +2,12 @@ module Jekyll
module Utils module Utils
extend self extend self
# Constants for use in #slugify
SLUGIFY_MODES = %w{raw default pretty}
SLUGIFY_RAW_REGEXP = Regexp.new('\\s+').freeze
SLUGIFY_DEFAULT_REGEXP = Regexp.new('[^[:alnum:]]+').freeze
SLUGIFY_PRETTY_REGEXP = Regexp.new("[^[:alnum:]._~!$&'()+,;=@]+").freeze
# Merges a master hash with another hash, recursively. # Merges a master hash with another hash, recursively.
# #
# master_hash - the "parent" hash whose values will be overridden # master_hash - the "parent" hash whose values will be overridden
@ -90,7 +96,7 @@ module Jekyll
# Returns the parsed date if successful, throws a FatalException # Returns the parsed date if successful, throws a FatalException
# if not # if not
def parse_date(input, msg = "Input could not be parsed.") def parse_date(input, msg = "Input could not be parsed.")
Time.parse(input) Time.parse(input).localtime
rescue ArgumentError rescue ArgumentError
raise Errors::FatalException.new("Invalid date '#{input}': " + msg) raise Errors::FatalException.new("Invalid date '#{input}': " + msg)
end end
@ -104,21 +110,92 @@ module Jekyll
# Slugify a filename or title. # Slugify a filename or title.
# #
# name - the filename or title to slugify # string - the filename or title to slugify
# mode - how string is slugified
# #
# Returns the given filename or title in lowercase, with every # When mode is "none", return the given string in lowercase.
# sequence of spaces and non-alphanumeric characters replaced with a #
# hyphen. # When mode is "raw", return the given string in lowercase,
def slugify(string) # with every sequence of spaces characters replaced with a hyphen.
unless string.nil? #
string \ # When mode is "default" or nil, non-alphabetic characters are
# Replace each non-alphanumeric character sequence with a hyphen # replaced with a hyphen too.
.gsub(/[^a-z0-9]+/i, '-') \ #
# Remove leading/trailing hyphen # When mode is "pretty", some non-alphabetic characters (._~!$&'()+,;=@)
.gsub(/^\-|\-$/i, '') \ # are not replaced with hyphen.
# Downcase it #
.downcase # Examples:
# slugify("The _config.yml file")
# # => "the-config-yml-file"
#
# slugify("The _config.yml file", "pretty")
# # => "the-_config.yml-file"
#
# Returns the slugified string.
def slugify(string, mode=nil)
mode ||= 'default'
return nil if string.nil?
return string.downcase unless SLUGIFY_MODES.include?(mode)
# Replace each character sequence with a hyphen
re = case mode
when 'raw'
SLUGIFY_RAW_REGEXP
when 'default'
SLUGIFY_DEFAULT_REGEXP
when 'pretty'
# "._~!$&'()+,;=@" is human readable (not URI-escaped) in URL
# and is allowed in both extN and NTFS.
SLUGIFY_PRETTY_REGEXP
end end
string.
# Strip according to the mode
gsub(re, '-').
# Remove leading/trailing hyphen
gsub(/^\-|\-$/i, '').
# Downcase
downcase
end
# Add an appropriate suffix to template so that it matches the specified
# permalink style.
#
# template - permalink template without trailing slash or file extension
# permalink_style - permalink style, either built-in or custom
#
# The returned permalink template will use the same ending style as
# specified in permalink_style. For example, if permalink_style contains a
# trailing slash (or is :pretty, which indirectly has a trailing slash),
# then so will the returned template. If permalink_style has a trailing
# ":output_ext" (or is :none, :date, or :ordinal) then so will the returned
# template. Otherwise, template will be returned without modification.
#
# Examples:
# add_permalink_suffix("/:basename", :pretty)
# # => "/:basename/"
#
# add_permalink_suffix("/:basename", :date)
# # => "/:basename:output_ext"
#
# add_permalink_suffix("/:basename", "/:year/:month/:title/")
# # => "/:basename/"
#
# add_permalink_suffix("/:basename", "/:year/:month/:title")
# # => "/:basename"
#
# Returns the updated permalink template
def add_permalink_suffix(template, permalink_style)
case permalink_style
when :pretty
template << "/"
when :date, :ordinal, :none
template << ":output_ext"
else
template << "/" if permalink_style.to_s.end_with?("/")
template << ":output_ext" if permalink_style.to_s.end_with?(":output_ext")
end
template
end end
end end

View File

@ -1,3 +1,3 @@
module Jekyll module Jekyll
VERSION = '2.5.2' VERSION = '3.0.0.beta2'
end end

View File

@ -1,2 +1,3 @@
_site _site
.sass-cache .sass-cache
.jekyll-metadata

View File

@ -5,7 +5,7 @@ description: > # this means to ignore newlines until "baseurl:"
Write an awesome description for your new site here. You can edit this Write an awesome description for your new site here. You can edit this
line in _config.yml. It will appear in your document head meta (for line in _config.yml. It will appear in your document head meta (for
Google search results) and in your feed.xml site description. Google search results) and in your feed.xml site description.
baseurl: "" # the subpath of your site, e.g. /blog/ baseurl: "" # the subpath of your site, e.g. /blog
url: "http://yourdomain.com" # the base hostname & protocol for your site url: "http://yourdomain.com" # the base hostname & protocol for your site
twitter_username: jekyllrb twitter_username: jekyllrb
github_username: jekyll github_username: jekyll

View File

@ -46,7 +46,7 @@
</div> </div>
<div class="footer-col footer-col-3"> <div class="footer-col footer-col-3">
<p class="text">{{ site.description }}</p> <p>{{ site.description }}</p>
</div> </div>
</div> </div>

View File

@ -8,5 +8,5 @@
<link rel="stylesheet" href="{{ "/css/main.css" | prepend: site.baseurl }}"> <link rel="stylesheet" href="{{ "/css/main.css" | prepend: site.baseurl }}">
<link rel="canonical" href="{{ page.url | replace:'index.html','' | prepend: site.baseurl | prepend: site.url }}"> <link rel="canonical" href="{{ page.url | replace:'index.html','' | prepend: site.baseurl | prepend: site.url }}">
<link rel="alternate" type="application/rss+xml" title="{{ site.title }}" href="{{ "/feed.xml" | prepend: site.baseurl | prepend: site.url }}" /> <link rel="alternate" type="application/rss+xml" title="{{ site.title }}" href="{{ "/feed.xml" | prepend: site.baseurl | prepend: site.url }}">
</head> </head>

View File

@ -1,14 +1,14 @@
--- ---
layout: default layout: default
--- ---
<div class="post"> <article class="post">
<header class="post-header"> <header class="post-header">
<h1 class="post-title">{{ page.title }}</h1> <h1 class="post-title">{{ page.title }}</h1>
</header> </header>
<article class="post-content"> <div class="post-content">
{{ content }} {{ content }}
</article>
</div> </div>
</article>

View File

@ -1,15 +1,15 @@
--- ---
layout: default layout: default
--- ---
<div class="post"> <article class="post" itemscope itemtype="http://schema.org/BlogPosting">
<header class="post-header"> <header class="post-header">
<h1 class="post-title">{{ page.title }}</h1> <h1 class="post-title" itemprop="name headline">{{ page.title }}</h1>
<p class="post-meta">{{ page.date | date: "%b %-d, %Y" }}{% if page.author %} • {{ page.author }}{% endif %}{% if page.meta %} • {{ page.meta }}{% endif %}</p> <p class="post-meta"><time datetime="{{ page.date | date_to_xmlschema }}" itemprop="datePublished">{{ page.date | date: "%b %-d, %Y" }}</time>{% if page.author %} • <span itemprop="author" itemscope itemtype="http://schema.org/Person"><span itemprop="name">{{ page.author }}</span></span>{% endif %}</p>
</header> </header>
<article class="post-content"> <div class="post-content" itemprop="articleBody">
{{ content }} {{ content }}
</article>
</div> </div>
</article>

View File

@ -18,8 +18,8 @@ print_hi('Tom')
#=> prints 'Hi, Tom' to STDOUT. #=> prints 'Hi, Tom' to STDOUT.
{% endhighlight %} {% endhighlight %}
Check out the [Jekyll docs][jekyll] for more info on how to get the most out of Jekyll. File all bugs/feature requests at [Jekylls GitHub repo][jekyll-gh]. If you have questions, you can ask them on [Jekylls dedicated Help repository][jekyll-help]. Check out the [Jekyll docs][jekyll-docs] for more info on how to get the most out of Jekyll. File all bugs/feature requests at [Jekylls GitHub repo][jekyll-gh]. If you have questions, you can ask them on [Jekylls dedicated Help repository][jekyll-help].
[jekyll]: http://jekyllrb.com [jekyll-docs]: http://jekyllrb.com/docs/home
[jekyll-gh]: https://github.com/jekyll/jekyll [jekyll-gh]: https://github.com/jekyll/jekyll
[jekyll-help]: https://github.com/jekyll/jekyll-help [jekyll-help]: https://github.com/jekyll/jekyll-help

View File

@ -14,13 +14,15 @@ dl, dd, ol, ul, figure {
* Basic styling * Basic styling
*/ */
body { body {
font-family: $base-font-family; font: $base-font-weight #{$base-font-size}/#{$base-line-height} $base-font-family;
font-size: $base-font-size;
line-height: $base-line-height;
font-weight: 300;
color: $text-color; color: $text-color;
background-color: $background-color; background-color: $background-color;
-webkit-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;
-webkit-font-feature-settings: "kern" 1;
-moz-font-feature-settings: "kern" 1;
-o-font-feature-settings: "kern" 1;
font-feature-settings: "kern" 1;
font-kerning: normal;
} }
@ -80,7 +82,7 @@ li {
* Headings * Headings
*/ */
h1, h2, h3, h4, h5, h6 { h1, h2, h3, h4, h5, h6 {
font-weight: 300; font-weight: $base-font-weight;
} }
@ -139,7 +141,7 @@ code {
pre { pre {
padding: 8px 12px; padding: 8px 12px;
overflow-x: scroll; overflow-x: auto;
> code { > code {
border: 0; border: 0;

View File

@ -35,16 +35,16 @@
color: $text-color; color: $text-color;
line-height: $base-line-height; line-height: $base-line-height;
// Gaps between nav items, but not on the first one // Gaps between nav items, but not on the last one
&:not(:first-child) { &:not(:last-child) {
margin-left: 20px; margin-right: 20px;
} }
} }
@include media-query($on-palm) { @include media-query($on-palm) {
position: absolute; position: absolute;
top: 9px; top: 9px;
right: 30px; right: $spacing-unit / 2;
background-color: $background-color; background-color: $background-color;
border: 1px solid $grey-color-light; border: 1px solid $grey-color-light;
border-radius: 5px; border-radius: 5px;
@ -82,6 +82,11 @@
.page-link { .page-link {
display: block; display: block;
padding: 5px 10px; padding: 5px 10px;
&:not(:last-child) {
margin-right: 0;
}
margin-left: 20px;
} }
} }
} }

View File

@ -6,8 +6,9 @@
// Our variables // Our variables
$base-font-family: Helvetica, Arial, sans-serif; $base-font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
$base-font-size: 16px; $base-font-size: 16px;
$base-font-weight: 300;
$small-font-size: $base-font-size * 0.875; $small-font-size: $base-font-size * 0.875;
$base-line-height: 1.5; $base-line-height: 1.5;

View File

@ -1,4 +1,4 @@
#!/bin/sh #!/bin/sh
script/branding script/branding
bundle install bundle install -j8

View File

@ -5,20 +5,29 @@
set -e set -e
if [[ "$1" != "-f" ]]; then function msg {
git diff --name-only ..master | grep '^site/' || { printf "\e[0;37m==> $1\e[0m\n"
echo "No site files changed. We'll skip proofing. Run with -f to force."
exit 0
}
fi
echo "Some site files have been changed! Proofing..."
command -v htmlproof || {
echo "Installing HTML::Proofer!"
gem install html-proofer -- --use-system-libraries
} }
bundle exec jekyll build -s site -d _site --trace INGORE_HREFS=$(ruby -e 'puts %w{
printf "\e[0;36mProofing begins now!\e[0m\n" Chrononaut
htmlproof ./_site twitter.com
nearlyfreespeech.net
}.map{|h| "/#{h}/"}.join(",")')
SOURCE="site"
DESTINATION="_site"
export PROOF=true
export NOKOGIRI_USE_SYSTEM_LIBRARIES=true
# 1.
msg "Installing..."
bundle install -j8 > /dev/null || bundle install > /dev/null
# 2.
msg "Building..."
bundle exec jekyll build -s $SOURCE -d $DESTINATION --full-rebuild --trace
# 3.
msg "Proofing..."
time bundle exec htmlproof ./$DESTINATION --href-ignore $INGORE_HREFS

View File

@ -5,12 +5,12 @@ set -e
export BENCHMARK=true export BENCHMARK=true
command -v stackprof > /dev/null || script/bootstrap command -v stackprof > /dev/null || script/bootstrap
TEST_SCRIPT="Jekyll::Commands::Build.process({'source' => 'site'})" TEST_SCRIPT="Jekyll::Commands::Build.process({'source' => 'site', 'full_rebuild' => true})"
PROF_OUTPUT_FILE=tmp/stackprof-$(date +%Y%m%d).dump PROF_OUTPUT_FILE=tmp/stackprof-$(date +%Y%m%d%H%M).dump
test -f "$PROF_OUTPUT_FILE" || { test -f "$PROF_OUTPUT_FILE" || {
bundle exec ruby -r./lib/jekyll -rstackprof \ bundle exec ruby -r./lib/jekyll -rstackprof \
-e "StackProf.run(mode: :cpu, out: '${PROF_OUTPUT_FILE}') { ${TEST_SCRIPT} }" -e "StackProf.run(mode: :cpu, interval: 100, out: '${PROF_OUTPUT_FILE}') { ${TEST_SCRIPT} }"
} }
bundle exec stackprof $PROF_OUTPUT_FILE $@ bundle exec stackprof $PROF_OUTPUT_FILE $@

View File

@ -4,17 +4,20 @@
# script/test # script/test
# script/test <test_file> # script/test <test_file>
if [ ! -d tmp ]; then
mkdir tmp
fi
if [ -d test/dest ]; then
rm -r test/dest
fi
if [ -z "$1" ]; then if [ -z "$1" ]; then
TEST_FILES="./test/test_*.rb" TEST_FILES=$(ruby -e "puts Dir.glob('test/test_*.rb')")
else else
TEST_FILES="$@" TEST_FILES="$@"
fi fi
RAKE_LIB_DIR=$(ruby -e "puts Gem::Specification.find_by_name('rake').gem_dir + '/lib'")
set -x set -x
time bundle exec ruby -I"lib:test" \ time bundle exec ruby -Ilib -Itest -rloader $TEST_FILES --profile
-I"${RAKE_LIB_DIR}" \
"${RAKE_LIB_DIR}/rake/rake_test_loader.rb" \
$TEST_FILES

View File

@ -1 +0,0 @@
Jekyll's awesome website.

15
site/README.md Normal file
View File

@ -0,0 +1,15 @@
# Jekyll docs site
This directory contains the code for the Jekyll docs site, [jekyllrb.com](http://jekyllrb.com/).
## Contributing
For information about contributing, see the [Contributing page](http://jekyllrb.com/docs/contributing/).
## Running locally
You can preview your contributions before opening a pull request by running from within the directory:
1. `bundle install`
2. `bundle exec rake site:preview`
It's just a jekyll site, afterall! :wink:

View File

@ -1,8 +1,6 @@
--- ---
layout: docs layout: docs
title: Assets title: Assets
prev_section: datafiles
next_section: migrations
permalink: /docs/assets/ permalink: /docs/assets/
--- ---

View File

@ -1,15 +1,13 @@
--- ---
layout: docs layout: docs
title: Collections title: Collections
prev_section: variables
next_section: datafiles
permalink: /docs/collections/ permalink: /docs/collections/
--- ---
<div class="note warning"> <div class="note warning">
<h5>Collections support is unstable and may change</h5> <h5>Collections support is unstable and may change</h5>
<p> <p>
This is an experimental feature and that the API may likely change until the feature stabilizes. This is an experimental feature and the API may change until the feature stabilizes.
</p> </p>
</div> </div>
@ -37,7 +35,7 @@ collections:
### Step 2: Add your content ### Step 2: Add your content
Create a corresponding folder (e.g. `<source>/_my_collection`) and add documents. Create a corresponding folder (e.g. `<source>/_my_collection`) and add documents.
YAML Front Matter is read in as data if it exists, if not, then everything is just stuck in the Document's `content` attribute. YAML Front Matter is read in as data if it exists, and everything after it is stuck in the Document's `content` attribute. If no YAML Front Matter is provided, Jekyll will not generate the file in your collection.
Note: the folder must be named identically to the collection you defined in your `_config.yml` file, with the addition of the preceding `_` character. Note: the folder must be named identically to the collection you defined in your `_config.yml` file, with the addition of the preceding `_` character.
@ -211,8 +209,7 @@ In addition to any YAML Front Matter provided in the document's corresponding fi
</td> </td>
<td> <td>
<p> <p>
The (unrendered) content of the document. If no YAML Front Matter is provided, The (unrendered) content of the document. If no YAML Front Matter is provided, Jekyll will not generate the file in your collection. If YAML Front Matter
this is the entirety of the file contents. If YAML Front Matter
is used, then this is all the contents of the file after the terminating is used, then this is all the contents of the file after the terminating
`---` of the front matter. `---` of the front matter.
</p> </p>

View File

@ -1,8 +1,6 @@
--- ---
layout: docs layout: docs
title: Configuration title: Configuration
prev_section: structure
next_section: frontmatter
permalink: /docs/configuration/ permalink: /docs/configuration/
--- ---
@ -155,9 +153,12 @@ class="flag">flags</code> (specified on the command-line) that control them.
<h5>Destination folders are cleaned on site builds</h5> <h5>Destination folders are cleaned on site builds</h5>
<p> <p>
The contents of <code>&lt;destination&gt;</code> are automatically The contents of <code>&lt;destination&gt;</code> are automatically
cleaned when the site is built. Files or folders that are not cleaned, by default, when the site is built. Files or folders that are not
created by your site will be removed. Do not use an important created by your site will be removed. Some files could be retained
location for <code>&lt;destination&gt;</code>; instead, use it as by specifying them within the <code>&lt;keep_files&gt;</code> configuration directive.
</p>
<p>
Do not use an important location for <code>&lt;destination&gt;</code>; instead, use it as
a staging area and copy files from there to your web server. a staging area and copy files from there to your web server.
</p> </p>
</div> </div>
@ -387,7 +388,7 @@ defaults:
- -
scope: scope:
path: "projects" path: "projects"
type: "pages" type: "pages" # previously `page` in Jekyll 2.2.
values: values:
layout: "project" # overrides previous default layout layout: "project" # overrides previous default layout
author: "Mr. Hyde" author: "Mr. Hyde"
@ -409,7 +410,7 @@ defaults:
layout: "default" layout: "default"
{% endhighlight %} {% endhighlight %}
In this example the `layout` is set to `default` inside the [collection](../collections) with the name `my_collection`. In this example the `layout` is set to `default` inside the [collection](../collections/) with the name `my_collection`.
### Precedence ### Precedence
@ -447,9 +448,9 @@ The `projects/foo_project.md` would have the `layout` set to `foobar` instead of
## Default Configuration ## Default Configuration
Jekyll runs with the following configuration options by default. Unless Jekyll runs with the following configuration options by default. Alternative
alternative settings for these options are explicitly specified in the settings for these options can be explicitly specified in the configuration
configuration file or on the command-line, Jekyll will run using these options. file or on the command-line.
<div class="note warning"> <div class="note warning">
<h5>There are two unsupported kramdown options</h5> <h5>There are two unsupported kramdown options</h5>
@ -476,7 +477,6 @@ exclude: []
keep_files: [".git", ".svn"] keep_files: [".git", ".svn"]
encoding: "utf-8" encoding: "utf-8"
markdown_ext: "markdown,mkdown,mkdn,mkd,md" markdown_ext: "markdown,mkdown,mkdn,mkd,md"
textile_ext: "textile"
# Filtering Content # Filtering Content
show_drafts: null show_drafts: null
@ -490,14 +490,14 @@ gems: []
# Conversion # Conversion
markdown: kramdown markdown: kramdown
highlighter: pygments highlighter: rouge
lsi: false lsi: false
excerpt_separator: "\n\n" excerpt_separator: "\n\n"
# Serving # Serving
detach: false detach: false
port: 4000 port: 4000
host: 0.0.0.0 host: 127.0.0.1
baseurl: "" # does not include hostname baseurl: "" # does not include hostname
# Backwards-compatibility # Backwards-compatibility
@ -532,7 +532,7 @@ kramdown:
entity_output: as_char entity_output: as_char
toc_levels: 1..6 toc_levels: 1..6
smart_quotes: lsquo,rsquo,ldquo,rdquo smart_quotes: lsquo,rsquo,ldquo,rdquo
use_coderay: false enable_coderay: false
coderay: coderay:
coderay_wrap: div coderay_wrap: div
@ -541,9 +541,6 @@ kramdown:
coderay_tab_width: 4 coderay_tab_width: 4
coderay_bold_every: 10 coderay_bold_every: 10
coderay_css: style coderay_css: style
redcloth:
hard_breaks: true
{% endhighlight %} {% endhighlight %}
## Markdown Options ## Markdown Options

View File

@ -1,8 +1,6 @@
--- ---
layout: docs layout: docs
title: Continuous Integration title: Continuous Integration
prev_section: deployment-methods
next_section: troubleshooting
permalink: /docs/continuous-integration/ permalink: /docs/continuous-integration/
--- ---
@ -62,7 +60,7 @@ HTML::Proofer.new("./_site").run
{% endhighlight %} {% endhighlight %}
Options are given as a second argument to `.new`, and are encoded in a Options are given as a second argument to `.new`, and are encoded in a
symbol-keyed Ruby Hash. More information about the configuration options, symbol-keyed Ruby Hash. For more information about the configuration options,
check out `html-proofer`'s README file. check out `html-proofer`'s README file.
[2]: https://github.com/gjtorikian/html-proofer [2]: https://github.com/gjtorikian/html-proofer
@ -71,7 +69,7 @@ check out `html-proofer`'s README file.
This file is used to configure your Travis builds. Because Jekyll is built This file is used to configure your Travis builds. Because Jekyll is built
with Ruby and requires RubyGems to install, we use the Ruby language build with Ruby and requires RubyGems to install, we use the Ruby language build
environment. Below is a sample `.travis.yml` file, and what follows that is environment. Below is a sample `.travis.yml` file, followed by
an explanation of each line. an explanation of each line.
{% highlight yaml %} {% highlight yaml %}

View File

@ -1,8 +1,6 @@
--- ---
layout: docs layout: docs
title: Contributing title: Contributing
prev_section: upgrading
next_section: history
permalink: /docs/contributing/ permalink: /docs/contributing/
--- ---

View File

@ -1,8 +1,6 @@
--- ---
layout: docs layout: docs
title: Data Files title: Data Files
prev_section: collections
next_section: assets
permalink: /docs/datafiles/ permalink: /docs/datafiles/
--- ---

View File

@ -1,8 +1,6 @@
--- ---
layout: docs layout: docs
title: Deployment methods title: Deployment methods
prev_section: github-pages
next_section: continuous-integration
permalink: /docs/deployment-methods/ permalink: /docs/deployment-methods/
--- ---
@ -93,7 +91,7 @@ Another way to deploy your Jekyll site is to use [Rake](https://github.com/jimwe
### rsync ### rsync
Once youve generated the `_site` directory, you can easily rsync it using a `tasks/deploy` shell script similar to [this deploy script here](https://github.com/henrik/henrik.nyh.se/blob/master/tasks/deploy). Youd obviously need to change the values to reflect your sites details. There is even [a matching TextMate command](http://gist.github.com/214959) that will help you run Once youve generated the `_site` directory, you can easily rsync it using a `tasks/deploy` shell script similar to [this deploy script here](https://github.com/henrik/henrik.nyh.se/blob/master/script/deploy). Youd obviously need to change the values to reflect your sites details. There is even [a matching TextMate command](http://gist.github.com/214959) that will help you run
this script from within Textmate. this script from within Textmate.
@ -109,9 +107,10 @@ If you want to maintain Jekyll inside your existing Rails app, [Jekyll-Admin](ht
## Amazon S3 ## Amazon S3
If you want to host your site in Amazon S3, you can do so with If you want to host your site in Amazon S3, you can do so by
[s3_website](https://github.com/laurilehmijoki/s3_website) application. It will using the [s3_website](https://github.com/laurilehmijoki/s3_website)
push your site to Amazon S3 where it can be served like any web server, application. It will push your site to Amazon S3 where it can be served like
any web server,
dynamically scaling to almost unlimited traffic. This approach has the dynamically scaling to almost unlimited traffic. This approach has the
benefit of being about the cheapest hosting option available for benefit of being about the cheapest hosting option available for
low-volume blogs as you only pay for what you use. low-volume blogs as you only pay for what you use.

View File

@ -1,8 +1,6 @@
--- ---
layout: docs layout: docs
title: Working with drafts title: Working with drafts
prev_section: posts
next_section: pages
permalink: /docs/drafts/ permalink: /docs/drafts/
--- ---

View File

@ -1,8 +1,6 @@
--- ---
layout: docs layout: docs
title: Extras title: Extras
prev_section: plugins
next_section: github-pages
permalink: /docs/extras/ permalink: /docs/extras/
--- ---

View File

@ -1,8 +1,6 @@
--- ---
layout: docs layout: docs
title: Front Matter title: Front Matter
prev_section: configuration
next_section: posts
permalink: /docs/frontmatter/ permalink: /docs/frontmatter/
--- ---
@ -172,7 +170,9 @@ These are available out-of-the-box to be used in the front matter for a post.
<td> <td>
<p> <p>
A date here overrides the date from the name of the post. This can be A date here overrides the date from the name of the post. This can be
used to ensure correct sorting of posts. used to ensure correct sorting of posts. A date is specified in the format
<code>YYYY-MM-DD HH:MM:SS +/-TTTT</code>; hours, minutes, seconds, and timezone offset
are optional.
</p> </p>
</td> </td>
</tr> </tr>

View File

@ -1,8 +1,6 @@
--- ---
layout: docs layout: docs
title: GitHub Pages title: GitHub Pages
prev_section: extras
next_section: deployment-methods
permalink: /docs/github-pages/ permalink: /docs/github-pages/
--- ---

View File

@ -2,9 +2,41 @@
layout: docs layout: docs
title: History title: History
permalink: "/docs/history/" permalink: "/docs/history/"
prev_section: contributing
--- ---
## 2.5.3 / 2014-12-22
{: #v2-5-3}
### Bug Fixes
{: #bug-fixes-v2-5-3}
- When checking a Markdown extname, include position of the `.` ([#3147]({{ site.repository }}/issues/3147))
- Fix `jsonify` Liquid filter handling of boolean values ([#3154]({{ site.repository }}/issues/3154))
- Add comma to value of `viewport` meta tag ([#3170]({{ site.repository }}/issues/3170))
- Set the link type for the RSS feed to `application/rss+xml` ([#3176]({{ site.repository }}/issues/3176))
- Refactor `#as_liquid` ([#3158]({{ site.repository }}/issues/3158))
### Development Fixes
{: #development-fixes-v2-5-3}
- Exclude built-in bundles from being added to coverage report ([#3180]({{ site.repository }}/issues/3180))
### Site Enhancements
{: #site-enhancements-v2-5-3}
- Add `[@alfredxing](https://github.com/alfredxing)` to the `[@jekyll](https://github.com/jekyll)/core` team. :tada: ([#3218]({{ site.repository }}/issues/3218))
- Document the `-q` option for the `build` and `serve` commands ([#3149]({{ site.repository }}/issues/3149))
- Fix some minor typos/flow fixes in documentation website content ([#3165]({{ site.repository }}/issues/3165))
- Add `keep_files` to configuration documentation ([#3162]({{ site.repository }}/issues/3162))
- Repeat warning about cleaning of the `destination` directory ([#3161]({{ site.repository }}/issues/3161))
- Add jekyll-500px-embed to list of third-party plugins ([#3163]({{ site.repository }}/issues/3163))
- Simplified platform detection in Gemfile example for Windows ([#3177]({{ site.repository }}/issues/3177))
- Add the `jekyll-jalali` plugin added to the list of third-party plugins. ([#3198]({{ site.repository }}/issues/3198))
- Add Table of Contents to Troubleshooting page ([#3196]({{ site.repository }}/issues/3196))
- Add `inline_highlight` plugin to list of third-party plugins ([#3212]({{ site.repository }}/issues/3212))
- Add `jekyll-mermaid` plugin to list of third-party plugins ([#3222]({{ site.repository }}/issues/3222))
## 2.5.2 / 2014-11-17 ## 2.5.2 / 2014-11-17
{: #v2-5-2} {: #v2-5-2}

View File

@ -1,7 +1,6 @@
--- ---
layout: docs layout: docs
title: Welcome title: Welcome
next_section: quickstart
permalink: /docs/home/ permalink: /docs/home/
--- ---
@ -15,10 +14,9 @@ development of Jekyll itself.
Jekyll is a simple, blog-aware, static site generator. It takes a template Jekyll is a simple, blog-aware, static site generator. It takes a template
directory containing raw text files in various formats, runs it through directory containing raw text files in various formats, runs it through
[Markdown](http://daringfireball.net/projects/markdown/) (or a converter (like [Markdown](http://daringfireball.net/projects/markdown/))
[Textile](http://redcloth.org/textile)) and and our [Liquid](https://github.com/Shopify/liquid/wiki) renderer, and
[Liquid](https://github.com/Shopify/liquid/wiki) spits out a complete, ready-to-publish static website suitable
converters, and spits out a complete, ready-to-publish static website suitable
for serving with your favorite web server. Jekyll also happens to be the engine for serving with your favorite web server. Jekyll also happens to be the engine
behind [GitHub Pages](http://pages.github.com), which means you can use Jekyll behind [GitHub Pages](http://pages.github.com), which means you can use Jekyll
to host your projects page, blog, or website from GitHubs servers **for to host your projects page, blog, or website from GitHubs servers **for

View File

@ -1,8 +1,6 @@
--- ---
layout: docs layout: docs
title: Installation title: Installation
prev_section: quickstart
next_section: usage
permalink: /docs/installation/ permalink: /docs/installation/
--- ---

View File

@ -1,8 +1,6 @@
--- ---
layout: docs layout: docs
title: Blog migrations title: Blog migrations
prev_section: assets
next_section: templates
permalink: /docs/migrations/ permalink: /docs/migrations/
--- ---

View File

@ -1,8 +1,6 @@
--- ---
layout: docs layout: docs
title: Creating pages title: Creating pages
prev_section: drafts
next_section: variables
permalink: /docs/pages/ permalink: /docs/pages/
--- ---
@ -60,7 +58,7 @@ and associated URLs might look like:
### Named folders containing index HTML files ### Named folders containing index HTML files
There is nothing wrong with the above method, however some people like to keep There is nothing wrong with the above method. However, some people like to keep
their URLs free from things like filename extensions. To achieve clean URLs for their URLs free from things like filename extensions. To achieve clean URLs for
pages using Jekyll, you simply need to create a folder for each top-level page pages using Jekyll, you simply need to create a folder for each top-level page
you want, and then place an `index.html` file in each pages folder. This way you want, and then place an `index.html` file in each pages folder. This way

View File

@ -1,8 +1,6 @@
--- ---
layout: docs layout: docs
title: Pagination title: Pagination
prev_section: permalinks
next_section: plugins
permalink: /docs/pagination/ permalink: /docs/pagination/
--- ---
@ -32,10 +30,10 @@ paginate: 5
The number should be the maximum number of Posts youd like to be displayed per- The number should be the maximum number of Posts youd like to be displayed per-
page in the generated site. page in the generated site.
You may also specify where the destination of the pagination pages: You may also specify the destination of the pagination pages:
{% highlight yaml %} {% highlight yaml %}
paginate_path: "blog/page:num/" paginate_path: "/blog/page:num/"
{% endhighlight %} {% endhighlight %}
This will read in `blog/index.html`, send it each pagination page in Liquid as `paginator` This will read in `blog/index.html`, send it each pagination page in Liquid as `paginator`
@ -44,6 +42,13 @@ starting with `2`. If a site has 12 posts and specifies `paginate: 5`, Jekyll wi
`blog/index.html` with the first 5 posts, `blog/page2/index.html` with the next 5 posts `blog/index.html` with the first 5 posts, `blog/page2/index.html` with the next 5 posts
and `blog/page3/index.html` with the last 2 posts into the destination directory. and `blog/page3/index.html` with the last 2 posts into the destination directory.
<div class="note warning">
<h5>Don't set a permalink</h5>
<p>
Setting a permalink in the front matter of your blog page will cause pagination to break. Just omit the permalink.
</p>
</div>
## Liquid Attributes Available ## Liquid Attributes Available
The pagination plugin exposes the `paginator` liquid object with the following The pagination plugin exposes the `paginator` liquid object with the following

View File

@ -1,8 +1,6 @@
--- ---
layout: docs layout: docs
title: Permalinks title: Permalinks
prev_section: templates
next_section: pagination
permalink: /docs/permalinks/ permalink: /docs/permalinks/
--- ---
@ -80,7 +78,10 @@ permalink is defined as `/:categories/:year/:month/:day/:title.html`.
<p><code>title</code></p> <p><code>title</code></p>
</td> </td>
<td> <td>
<p>Title from the Posts filename</p> <p>
Title from the documents filename. May be overridden via the
documents <code>slug</code> YAML front matter.
</p>
</td> </td>
</tr> </tr>
<tr> <tr>
@ -137,6 +138,14 @@ enough to fix it all!
<p><code>/:categories/:year/:month/:day/:title/</code></p> <p><code>/:categories/:year/:month/:day/:title/</code></p>
</td> </td>
</tr> </tr>
<tr>
<td>
<p><code>ordinal</code></p>
</td>
<td>
<p><code>/:categories/:year/:y_day/:title.html</code></p>
</td>
</tr>
<tr> <tr>
<td> <td>
<p><code>none</code></p> <p><code>none</code></p>
@ -151,7 +160,7 @@ enough to fix it all!
## Permalink style examples ## Permalink style examples
Given a post named: `/2009-04-29-slap-chop.textile` Given a post named: `/2009-04-29-slap-chop.md`
<div class="mobile-side-scroller"> <div class="mobile-side-scroller">
<table> <table>

View File

@ -1,8 +1,6 @@
--- ---
layout: docs layout: docs
title: Plugins title: Plugins
prev_section: pagination
next_section: extras
permalink: /docs/plugins/ permalink: /docs/plugins/
--- ---
@ -13,8 +11,8 @@ having to modify the Jekyll source itself.
<div class="note info"> <div class="note info">
<h5>Plugins on GitHub Pages</h5> <h5>Plugins on GitHub Pages</h5>
<p> <p>
<a href="http://pages.github.com/">GitHub Pages</a> is powered by Jekyll, <a href="http://pages.github.com/">GitHub Pages</a> is powered by Jekyll.
however all Pages sites are generated using the <code>--safe</code> option However, all Pages sites are generated using the <code>--safe</code> option
to disable custom plugins for security reasons. Unfortunately, this means to disable custom plugins for security reasons. Unfortunately, this means
your plugins wont work if youre deploying to GitHub Pages.<br><br> your plugins wont work if youre deploying to GitHub Pages.<br><br>
You can still use GitHub Pages to publish your site, but youll need to You can still use GitHub Pages to publish your site, but youll need to
@ -44,20 +42,21 @@ You have 3 options for installing plugins:
<div class="note info"> <div class="note info">
<h5> <h5>
<code>_plugins</code> and <code>gems</code> <code>_plugins</code>, <code>_config.yml</code> and <code>Gemfile</code>
can be used simultaneously can be used simultaneously
</h5> </h5>
<p> <p>
You may use both of the aforementioned plugin options simultaneously in the You may use any of the aforementioned plugin options simultaneously in the
same site if you so choose. Use of one does not restrict the use of the other same site if you so choose. Use of one does not restrict the use of the others.
</p> </p>
</div> </div>
In general, plugins you make will fall into one of three categories: In general, plugins you make will fall into one of four categories:
1. Generators 1. [Generators](#generators)
2. Converters 2. [Converters](#converters)
3. Tags 3. [Commands](#commands)
4. [Tags](#tags)
## Generators ## Generators
@ -66,11 +65,8 @@ based on your own rules.
A generator is a subclass of `Jekyll::Generator` that defines a `generate` A generator is a subclass of `Jekyll::Generator` that defines a `generate`
method, which receives an instance of method, which receives an instance of
[`Jekyll::Site`]({{ site.repository }}/blob/master/lib/jekyll/site.rb). [`Jekyll::Site`]({{ site.repository }}/blob/master/lib/jekyll/site.rb). The
return value of `generate` is ignored.
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 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 before the site is generated. Pages with YAML Front Matters are stored as
@ -168,8 +164,9 @@ Generators are only required to implement one method:
## Converters ## Converters
If you have a new markup language youd like to use with your site, you can If you have a new markup language youd like to use with your site, you can
include it by implementing your own converter. Both the Markdown and Textile include it by implementing your own converter. Both the Markdown and
markup languages are implemented using this method. [Textile](https://github.com/jekyll/jekyll-textile-converter) markup
languages are implemented using this method.
<div class="note info"> <div class="note info">
<h5>Remember your YAML Front Matter</h5> <h5>Remember your YAML Front Matter</h5>
@ -253,7 +250,7 @@ In our example, `UpcaseConverter#matches` checks if our filename extension is
simply uppercasing the entire content string. Finally, when it saves the page, simply uppercasing the entire content string. Finally, when it saves the page,
it will do so with a `.html` extension. it will do so with a `.html` extension.
## Command ## Commands
As of version 2.5.0, Jekyll can be extended with plugins which provide As of version 2.5.0, Jekyll can be extended with plugins which provide
subcommands for the `jekyll` executable. This is possible by including the subcommands for the `jekyll` executable. This is possible by including the
@ -276,7 +273,7 @@ class MyNewCommand < Jekyll::Command
c.syntax "new [options]" c.syntax "new [options]"
c.description 'Create a new Jekyll site.' c.description 'Create a new Jekyll site.'
c.option 'dest', '-d DEST, 'Where the site should go.' c.option 'dest', '-d DEST', 'Where the site should go.'
c.action do |args, options| c.action do |args, options|
Jekyll::Site.new_site_at(options['dest']) Jekyll::Site.new_site_at(options['dest'])
@ -496,9 +493,11 @@ You can find a few useful plugins at the following locations:
- [Jekyll::AutolinkEmail by Ivan Tse](https://github.com/ivantsepp/jekyll-autolink_email): Autolink your emails. - [Jekyll::AutolinkEmail by Ivan Tse](https://github.com/ivantsepp/jekyll-autolink_email): Autolink your emails.
- [Jekyll::GitMetadata by Ivan Tse](https://github.com/ivantsepp/jekyll-git_metadata): Expose Git metadata for your templates. - [Jekyll::GitMetadata by Ivan Tse](https://github.com/ivantsepp/jekyll-git_metadata): Expose Git metadata for your templates.
- [Jekyll Http Basic Auth Plugin](https://gist.github.com/snrbrnjna/422a4b7e017192c284b3): Plugin to manage http basic auth for jekyll generated pages and directories. - [Jekyll Http Basic Auth Plugin](https://gist.github.com/snrbrnjna/422a4b7e017192c284b3): Plugin to manage http basic auth for jekyll generated pages and directories.
- [Jekyll Auto Image by Merlos](https://github.com/merlos/jekyll-auto-image): Gets the first image of a post. Useful to list your posts with images or to add [twitter cards](https://dev.twitter.com/cards/overview) to your site.
#### Converters #### Converters
- [Textile converter](https://github.com/jekyll/jekyll-textile-converter): Convert `.textile` files into HTML. Also includes the `textilize` Liquid filter.
- [Slim plugin](https://github.com/slim-template/jekyll-slim): Slim converter and includes for Jekyll with support for Liquid tags. - [Slim plugin](https://github.com/slim-template/jekyll-slim): Slim converter and includes for Jekyll with support for Liquid tags.
- [Jade plugin by John Papandriopoulos](https://github.com/snappylabs/jade-jekyll-plugin): Jade converter for Jekyll. - [Jade plugin by John Papandriopoulos](https://github.com/snappylabs/jade-jekyll-plugin): Jade converter for Jekyll.
- [HAML plugin by Sam Z](https://gist.github.com/517556): HAML converter for Jekyll. - [HAML plugin by Sam Z](https://gist.github.com/517556): HAML converter for Jekyll.
@ -517,6 +516,7 @@ You can find a few useful plugins at the following locations:
- [Org-mode Converter](https://gist.github.com/abhiyerra/7377603): Org-mode converter for Jekyll. - [Org-mode Converter](https://gist.github.com/abhiyerra/7377603): Org-mode converter for Jekyll.
- [Customized Kramdown Converter](https://github.com/mvdbos/kramdown-with-pygments): Enable Pygments syntax highlighting for Kramdown-parsed fenced code blocks. - [Customized Kramdown Converter](https://github.com/mvdbos/kramdown-with-pygments): Enable Pygments syntax highlighting for Kramdown-parsed fenced code blocks.
- [Bigfootnotes Plugin](https://github.com/TheFox/jekyll-bigfootnotes): Enables big footnotes for Kramdown. - [Bigfootnotes Plugin](https://github.com/TheFox/jekyll-bigfootnotes): Enables big footnotes for Kramdown.
- [AsciiDoc Plugin](https://github.com/asciidoctor/jekyll-asciidoc): AsciiDoc convertor for Jekyll using [Asciidoctor](http://asciidoctor.org/).
#### Filters #### Filters
@ -533,6 +533,8 @@ You can find a few useful plugins at the following locations:
- [jekyll-humanize](https://github.com/23maverick23/jekyll-humanize): This is a port of the Django app humanize which adds a "human touch" to data. Each method represents a Fluid type filter that can be used in your Jekyll site templates. Given that Jekyll produces static sites, some of the original methods do not make logical sense to port (e.g. naturaltime). - [jekyll-humanize](https://github.com/23maverick23/jekyll-humanize): This is a port of the Django app humanize which adds a "human touch" to data. Each method represents a Fluid type filter that can be used in your Jekyll site templates. Given that Jekyll produces static sites, some of the original methods do not make logical sense to port (e.g. naturaltime).
- [Jekyll-Ordinal](https://github.com/PatrickC8t/Jekyll-Ordinal): Jekyll liquid filter to output a date ordinal such as "st", "nd", "rd", or "th". - [Jekyll-Ordinal](https://github.com/PatrickC8t/Jekyll-Ordinal): Jekyll liquid filter to output a date ordinal such as "st", "nd", "rd", or "th".
- [Deprecated articles keeper](https://github.com/kzykbys/JekyllPlugins) by [Kazuya Kobayashi](http://blog.kazuya.co/): A simple Jekyll filter which monitor how old an article is. - [Deprecated articles keeper](https://github.com/kzykbys/JekyllPlugins) by [Kazuya Kobayashi](http://blog.kazuya.co/): A simple Jekyll filter which monitor how old an article is.
- [Jekyll-jalali](https://github.com/mehdisadeghi/jekyll-jalali) by [Mehdi Sadeghi](http://mehdix.ir): A simple Gregorian to Jalali date converter filter.
- [Jekyll Thumbnail Filter](https://github.com/matallo/jekyll-thumbnail-filter): Related posts thumbnail filter.
#### Tags #### Tags
@ -559,12 +561,12 @@ You can find a few useful plugins at the following locations:
- [Jekyll-citation](https://github.com/archome/jekyll-citation): Render BibTeX-formatted bibliographies/citations included in posts and pages (pure Ruby). - [Jekyll-citation](https://github.com/archome/jekyll-citation): Render BibTeX-formatted bibliographies/citations included in posts and pages (pure Ruby).
- [Jekyll Dribbble Set Tag](https://github.com/ericdfields/Jekyll-Dribbble-Set-Tag): Builds Dribbble image galleries from any user. - [Jekyll Dribbble Set Tag](https://github.com/ericdfields/Jekyll-Dribbble-Set-Tag): Builds Dribbble image galleries from any user.
- [Debbugs](https://gist.github.com/2218470): Allows posting links to Debian BTS easily. - [Debbugs](https://gist.github.com/2218470): Allows posting links to Debian BTS easily.
- [Refheap_tag](https://github.com/aburdette/refheap_tag): Liquid tag that allows embedding pastes from [refheap](https://refheap.com). - [Refheap_tag](https://github.com/aburdette/refheap_tag): Liquid tag that allows embedding pastes from [refheap](https://www.refheap.com/).
- [Jekyll-devonly_tag](https://gist.github.com/2403522): A block tag for including markup only during development. - [Jekyll-devonly_tag](https://gist.github.com/2403522): A block tag for including markup only during development.
- [JekyllGalleryTag](https://github.com/redwallhp/JekyllGalleryTag) by [redwallhp](https://github.com/redwallhp): Generates thumbnails from a directory of images and displays them in a grid. - [JekyllGalleryTag](https://github.com/redwallhp/JekyllGalleryTag) by [redwallhp](https://github.com/redwallhp): Generates thumbnails from a directory of images and displays them in a grid.
- [Youku and Tudou Embed](https://gist.github.com/Yexiaoxing/5891929): Liquid plugin for embedding Youku and Tudou videos. - [Youku and Tudou Embed](https://gist.github.com/Yexiaoxing/5891929): Liquid plugin for embedding Youku and Tudou videos.
- [Jekyll-swfobject](https://github.com/sectore/jekyll-swfobject): Liquid plugin for embedding Adobe Flash files (.swf) using [SWFObject](http://code.google.com/p/swfobject/). - [Jekyll-swfobject](https://github.com/sectore/jekyll-swfobject): Liquid plugin for embedding Adobe Flash files (.swf) using [SWFObject](http://code.google.com/p/swfobject/).
- [Jekyll Picture Tag](https://github.com/robwierzbowski/jekyll-picture-tag): Easy responsive images for Jekyll. Based on the proposed [`<picture>`](http://picture.responsiveimages.org/) element, polyfilled with Scott Jehls [Picturefill](https://github.com/scottjehl/picturefill). - [Jekyll Picture Tag](https://github.com/robwierzbowski/jekyll-picture-tag): Easy responsive images for Jekyll. Based on the proposed [`<picture>`](https://html.spec.whatwg.org/multipage/embedded-content.html#the-picture-element) element, polyfilled with Scott Jehls [Picturefill](https://github.com/scottjehl/picturefill).
- [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.
- [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. - [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.
@ -578,19 +580,22 @@ You can find a few useful plugins at the following locations:
- [Jekyll Github Sample Tag](https://github.com/bwillis/jekyll-github-sample): A liquid tag to include a sample of a github repo file in your Jekyll site. - [Jekyll Github Sample Tag](https://github.com/bwillis/jekyll-github-sample): A liquid tag to include a sample of a github repo file in your Jekyll site.
- [Jekyll Project Version Tag](https://github.com/rob-murray/jekyll-version-plugin): A Liquid tag plugin that renders a version identifier for your Jekyll site sourced from the git repository containing your code. - [Jekyll Project Version Tag](https://github.com/rob-murray/jekyll-version-plugin): A Liquid tag plugin that renders a version identifier for your Jekyll site sourced from the git repository containing your code.
- [Piwigo Gallery](https://github.com/AlessandroLorenzi/piwigo_gallery) by [Alessandro Lorenzi](http://www.alorenzi.eu/): Jekyll plugin to generate thumbnails from a Piwigo gallery and display them with a Liquid tag - [Piwigo Gallery](https://github.com/AlessandroLorenzi/piwigo_gallery) by [Alessandro Lorenzi](http://www.alorenzi.eu/): Jekyll plugin to generate thumbnails from a Piwigo gallery and display them with a Liquid tag
- [mathml.rb](https://github.com/tmthrgd/jekyll-plugins) by [Tom Thorogood](http://tomthorogood.co.uk/): A plugin to convert TeX mathematics into MathML for display. - [mathml.rb](https://github.com/tmthrgd/jekyll-plugins) by Tom Thorogood: A plugin to convert TeX mathematics into MathML for display.
- [webmention_io.rb](https://github.com/aarongustafson/jekyll-webmention_io) by [Aaron Gustafson](http://aaron-gustafson.com/): A plugin to enable [webmention](http://indiewebcamp.com/webmention) integration using [Webmention.io](http://webmention.io). Includes an optional JavaScript for updating webmentions automatically between publishes and, if available, in realtime using WebSockets. - [webmention_io.rb](https://github.com/aarongustafson/jekyll-webmention_io) by [Aaron Gustafson](http://aaron-gustafson.com/): A plugin to enable [webmention](http://indiewebcamp.com/webmention) integration using [Webmention.io](http://webmention.io). Includes an optional JavaScript for updating webmentions automatically between publishes and, if available, in realtime using WebSockets.
- [Jekyll 500px Embed](https://github.com/lkorth/jekyll-500px-embed) by [Luke Korth](https://lukekorth.com/). A Liquid tag plugin that embeds [500px](https://500px.com/) photos. - [Jekyll 500px Embed](https://github.com/lkorth/jekyll-500px-embed) by Luke Korth. A Liquid tag plugin that embeds [500px](https://500px.com/) photos.
- [inline\_highlight](https://github.com/bdesham/inline_highlight): A tag for inline syntax highlighting.
- [jekyll-mermaid](https://github.com/jasonbellamy/jekyll-mermaid): Simplify the creation of mermaid diagrams and flowcharts in your posts and pages.
- [twa](https://github.com/Ezmyrelda/twa): Twemoji Awesome plugin for Jekyll. Liquid tag allowing you to use twitter emoji in your jekyll pages.
#### Collections #### Collections
- [Jekyll Plugins by Recursive Design](http://recursive-design.com/projects/jekyll-plugins/): Plugins to generate Project pages from GitHub readmes, a Category page, and a Sitemap generator. - [Jekyll Plugins by Recursive Design](https://github.com/recurser/jekyll-plugins): Plugins to generate Project pages from GitHub readmes, a Category page, and a Sitemap generator.
- [Company website and blog plugins](https://github.com/flatterline/jekyll-plugins) by Flatterline, a [Ruby on Rails development company](http://flatterline.com/): Portfolio/project page generator, team/individual page generator, an author bio liquid tag for use on posts, and a few other smaller plugins. - [Company website and blog plugins](https://github.com/flatterline/jekyll-plugins) by Flatterline, a [Ruby on Rails development company](http://flatterline.com/): Portfolio/project page generator, team/individual page generator, an author bio liquid tag for use on posts, and a few other smaller plugins.
- [Jekyll plugins by Aucor](https://github.com/aucor/jekyll-plugins): Plugins for trimming unwanted newlines/whitespace and sorting pages by weight attribute. - [Jekyll plugins by Aucor](https://github.com/aucor/jekyll-plugins): Plugins for trimming unwanted newlines/whitespace and sorting pages by weight attribute.
#### Other #### Other
- [ditaa-ditaa](https://github.com/tmthrgd/ditaa-ditaa) by [Tom Thorogood](http://tomthorogood.co.uk/): a drastic revision of jekyll-ditaa that renders diagrams drawn using ASCII art into PNG images. - [ditaa-ditaa](https://github.com/tmthrgd/ditaa-ditaa) by Tom Thorogood: a drastic revision of jekyll-ditaa that renders diagrams drawn using ASCII art into PNG images.
- [Pygments Cache Path by Raimonds Simanovskis](https://github.com/rsim/blog.rayapps.com/blob/master/_plugins/pygments_cache_patch.rb): Plugin to cache syntax-highlighted code from Pygments. - [Pygments Cache Path by Raimonds Simanovskis](https://github.com/rsim/blog.rayapps.com/blob/master/_plugins/pygments_cache_patch.rb): Plugin to cache syntax-highlighted code from Pygments.
- [Draft/Publish Plugin by Michael Ivey](https://gist.github.com/49630): Save posts as drafts. - [Draft/Publish Plugin by Michael Ivey](https://gist.github.com/49630): Save posts as drafts.
- [Growl Notification Generator by Tate Johnson](https://gist.github.com/490101): Send Jekyll notifications to Growl. - [Growl Notification Generator by Tate Johnson](https://gist.github.com/490101): Send Jekyll notifications to Growl.
@ -611,13 +616,14 @@ You can find a few useful plugins at the following locations:
- [generator-jekyllrb](https://github.com/robwierzbowski/generator-jekyllrb): A generator that wraps Jekyll in [Yeoman](http://yeoman.io/), a tool collection and workflow for builing modern web apps. - [generator-jekyllrb](https://github.com/robwierzbowski/generator-jekyllrb): A generator that wraps Jekyll in [Yeoman](http://yeoman.io/), a tool collection and workflow for builing modern web apps.
- [grunt-jekyll](https://github.com/dannygarcia/grunt-jekyll): A straightforward [Grunt](http://gruntjs.com/) plugin for Jekyll. - [grunt-jekyll](https://github.com/dannygarcia/grunt-jekyll): A straightforward [Grunt](http://gruntjs.com/) plugin for Jekyll.
- [jekyll-postfiles](https://github.com/indirect/jekyll-postfiles): Add `_postfiles` directory and {% raw %}`{{ postfile }}`{% endraw %} tag so the files a post refers to will always be right there inside your repo. - [jekyll-postfiles](https://github.com/indirect/jekyll-postfiles): Add `_postfiles` directory and {% raw %}`{{ postfile }}`{% endraw %} tag so the files a post refers to will always be right there inside your repo.
- [A layout that compresses HTML](https://github.com/penibelst/jekyll-compress-html) by [Anatol Broder](http://penibelst.de/): Github Pages compatible, configurable way to compress HTML files on site build. - [A layout that compresses HTML](http://jch.penibelst.de/): Github Pages compatible, configurable way to compress HTML files on site build.
- [Jekyll CO₂](https://github.com/wdenton/jekyll-co2): Generates HTML showing the monthly change in atmospheric CO₂ at the Mauna Loa observatory in Hawaii. - [Jekyll CO₂](https://github.com/wdenton/jekyll-co2): Generates HTML showing the monthly change in atmospheric CO₂ at the Mauna Loa observatory in Hawaii.
- [remote-include](http://www.northfieldx.co.uk/remote-include/): Includes files using remote URLs - [remote-include](http://www.northfieldx.co.uk/remote-include/): Includes files using remote URLs
- [jekyll-minifier](https://github.com/digitalsparky/jekyll-minifier): Minifies HTML, XML, CSS, and Javascript both inline and as separate files utilising yui-compressor and htmlcompressor.
#### Editors #### Editors
- [sublime-jekyll](https://github.com/23maverick23/sublime-jekyll): A Sublime Text package for Jekyll static sites. This package should help creating Jekyll sites and posts easier by providing access to key template tags and filters, as well as common completions and a current date/datetime command (for dating posts). You can install this package manually via GitHub, or via [Package Control](https://sublime.wbond.net/packages/Jekyll). - [sublime-jekyll](https://github.com/23maverick23/sublime-jekyll): A Sublime Text package for Jekyll static sites. This package should help creating Jekyll sites and posts easier by providing access to key template tags and filters, as well as common completions and a current date/datetime command (for dating posts). You can install this package manually via GitHub, or via [Package Control](https://packagecontrol.io/packages/Jekyll).
- [vim-jekyll](https://github.com/parkr/vim-jekyll): A vim plugin to generate - [vim-jekyll](https://github.com/parkr/vim-jekyll): A vim plugin to generate
new posts and run `jekyll build` all without leaving vim. new posts and run `jekyll build` all without leaving vim.
- [markdown-writer](https://atom.io/packages/markdown-writer): An Atom package for Jekyll. It can create new posts/drafts, manage tags/categories, insert link/images and add many useful key mappings. - [markdown-writer](https://atom.io/packages/markdown-writer): An Atom package for Jekyll. It can create new posts/drafts, manage tags/categories, insert link/images and add many useful key mappings.

View File

@ -1,8 +1,6 @@
--- ---
layout: docs layout: docs
title: Writing posts title: Writing posts
prev_section: frontmatter
next_section: drafts
permalink: /docs/posts/ permalink: /docs/posts/
--- ---
@ -16,11 +14,12 @@ and web-based CMS systems, this will be a welcome change!
## The Posts Folder ## The Posts Folder
As explained on the [directory structure](../structure/) page, the `_posts` As explained on the [directory structure](../structure/) page, the `_posts`
folder is where your blog posts will live. These files can be either folder is where your blog posts will live. These files are generally
[Markdown](http://daringfireball.net/projects/markdown/) or [Markdown](http://daringfireball.net/projects/markdown/) or HTML, but can
[Textile](http://redcloth.org/textile) formatted text files, and as long as be other formats with the proper converter installed.
they have [YAML Front Matter](../frontmatter/), they will be converted from their All posts must have [YAML Front Matter](../frontmatter/), and they will be
source format into an HTML page that is part of your static site. converted from their source format into an HTML page that is part of your
static site.
### Creating Post Files ### Creating Post Files
@ -44,7 +43,7 @@ file. For example, the following are examples of valid post filenames:
<div class="note"> <div class="note">
<h5>ProTip™: Link to other posts</h5> <h5>ProTip™: Link to other posts</h5>
<p> <p>
Use the <a href="../templates#post-url"><code>post_url</code></a> Use the <a href="../templates/#post-url"><code>post_url</code></a>
tag to link to other posts without having to worry about the URL's tag to link to other posts without having to worry about the URL's
breaking when the site permalink style changes. breaking when the site permalink style changes.
</p> </p>
@ -54,12 +53,12 @@ file. For example, the following are examples of valid post filenames:
All blog post files must begin with [YAML Front Matter](../frontmatter/). After All blog post files must begin with [YAML Front Matter](../frontmatter/). After
that, it's simply a matter of deciding which format you prefer. Jekyll supports that, it's simply a matter of deciding which format you prefer. Jekyll supports
two popular content markup formats: [Markdown](http://daringfireball.net/projects/markdown/) out of the box,
[Markdown](http://daringfireball.net/projects/markdown/) and and has [myriad extensions for other formats as well](/docs/plugins/#converters-1),
[Textile](http://redcloth.org/textile). These formats each have their own way including the popular [Textile](http://redcloth.org/textile) format. These
of marking up different types of content within a post, so you should formats each have their own way of marking up different types of content
familiarize yourself with these formats and decide which one best suits your within a post, so you should familiarize yourself with these formats and
needs. decide which one best suits your needs.
<div class="note info"> <div class="note info">
<h5>Be aware of character sets</h5> <h5>Be aware of character sets</h5>
@ -171,6 +170,18 @@ your `excerpt_separator` to `""`.
Also, as with any output generated by Liquid tags, you can pass the `| strip_html` flag to remove any html tags in the output. This is particularly helpful if you wish to output a post excerpt as a `meta="description"` tag within the post `head`, or anywhere else having html tags along with the content is not desirable. Also, as with any output generated by Liquid tags, you can pass the `| strip_html` flag to remove any html tags in the output. This is particularly helpful if you wish to output a post excerpt as a `meta="description"` tag within the post `head`, or anywhere else having html tags along with the content is not desirable.
Additionally you are able to specify per-post `excerpt_separator` value if it is required just only the the selected post. Just specify the `excerpt_separator` with the same way as `excerpt` in the post's YAML head:
{% highlight text %}
---
excerpt_separator: <!--more-->
---
Excerpt
<!--more-->
Out-of-excerpt
{% endhighlight %}
## Highlighting code snippets ## Highlighting code snippets
Jekyll also has built-in support for syntax highlighting of code snippets using Jekyll also has built-in support for syntax highlighting of code snippets using

Some files were not shown because too many files have changed in this diff Show More