diff --git a/.gitignore b/.gitignore index aa6c14f8..baf9f1df 100644 --- a/.gitignore +++ b/.gitignore @@ -12,5 +12,8 @@ gh-pages/ site/_site/ coverage .ruby-version +.ruby-gemset .sass-cache -tmp/stackprof-* +tmp/* +.jekyll-metadata +/vendor diff --git a/.travis.yml b/.travis.yml index 90e08adf..d7960ce7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,13 +2,13 @@ language: ruby cache: bundler sudo: false rvm: +- 2.2 - 2.1 - 2.0 -- 1.9.3 env: matrix: - - TEST_SUITE=test - - TEST_SUITE=cucumber + - TEST_SUITE=test + - TEST_SUITE=cucumber before_script: bundle update script: script/cibuild notifications: @@ -16,9 +16,9 @@ notifications: on_success: change on_failure: change channels: - - irc.freenode.org#jekyll + - irc.freenode.org#jekyll template: - - "%{repository}#%{build_number} (%{branch}) %{message} %{build_url}" + - "%{repository}#%{build_number} (%{branch}) %{message} %{build_url}" email: on_success: never on_failure: never diff --git a/CONTRIBUTING.markdown b/CONTRIBUTING.markdown index 94533415..2145db65 100644 --- a/CONTRIBUTING.markdown +++ b/CONTRIBUTING.markdown @@ -4,6 +4,7 @@ Contribute So you've got an awesome idea to throw into Jekyll. Great! Please keep the 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.** * 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 @@ -67,7 +68,7 @@ You can find the documentation for jekyllrb.com in the [site](https://github.com/jekyll/jekyll/tree/master/site) directory of Jekyll's repo on GitHub.com. -All documentation pull requests should be directed at `master`. Pull +All documentation pull requests should be directed at `master`. Pull requests directed at another branch will not be accepted. The [Jekyll wiki](https://github.com/jekyll/jekyll/wiki) on GitHub diff --git a/Gemfile b/Gemfile index 25b40ed2..4299c72e 100644 --- a/Gemfile +++ b/Gemfile @@ -1,7 +1,40 @@ source 'https://rubygems.org' 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'] gem 'rbtrace' gem 'stackprof' + gem 'benchmark-ips' +end + +if ENV['PROOF'] + gem 'html-proofer', '~> 2.0' end diff --git a/History.markdown b/History.markdown index 225e6000..7d69a616 100644 --- a/History.markdown +++ b/History.markdown @@ -2,25 +2,172 @@ ### 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 + * 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 * When checking a Markdown extname, include position of the `.` (#3147) * Fix `jsonify` Liquid filter handling of boolean values (#3154) * Add comma to value of `viewport` meta tag (#3170) * Set the link type for the RSS feed to `application/rss+xml` (#3176) + * Refactor `#as_liquid` (#3158) ### Development Fixes + * Exclude built-in bundles from being added to coverage report (#3180) + ### Site Enhancements + * Add `@alfredxing` to the `@jekyll/core` team. :tada: (#3218) * Document the `-q` option for the `build` and `serve` commands (#3149) * Fix some minor typos/flow fixes in documentation website content (#3165) * Add `keep_files` to configuration documentation (#3162) * Repeat warning about cleaning of the `destination` directory (#3161) * Add jekyll-500px-embed to list of third-party plugins (#3163) * 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 @@ -477,7 +624,7 @@ * Add `Jekyll::LiquidExtensions` with `.lookup_variable` method for easy looking up of variable values in a Liquid context. (#2253) * Remove literal lang name from class (#2292) - * Return `utf-8` encoding in header for webrick error page response (#2289) + * Return `utf-8` encoding in header for webrick error page response (#2289) * Make template site easier to customize (#2268) * Add two-digit year to permalink template option (#2301) * Add `site.documents` to Liquid payload (list of all docs) (#2295) diff --git a/LICENSE b/LICENSE index 0e5f8440..527166b6 100644 --- a/LICENSE +++ b/LICENSE @@ -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 -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 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 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 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, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER diff --git a/README.markdown b/README.markdown index b68166cb..95c49bd7 100644 --- a/README.markdown +++ b/README.markdown @@ -1,9 +1,9 @@ # [Jekyll](http://jekyllrb.com/) -[![Gem Version](https://badge.fury.io/rb/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) -[![Code Climate](http://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) +[![Gem Version](https://img.shields.io/gem/v/jekyll.svg)](https://rubygems.org/gems/jekyll) +[![Build Status](https://img.shields.io/travis/jekyll/jekyll/master.svg)](https://travis-ci.org/jekyll/jekyll) +[![Code Climate](https://img.shields.io/codeclimate/github/jekyll/jekyll.svg)](https://codeclimate.com/github/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) By Tom Preston-Werner, Nick Quaranto, Parker Moore, and many [awesome contributors](https://github.com/jekyll/jekyll/graphs/contributors)! diff --git a/Rakefile b/Rakefile index 991f63e0..98610a3c 100644 --- a/Rakefile +++ b/Rakefile @@ -26,7 +26,7 @@ def gemspec_file end def gem_file - "#{name}-#{version}.gem" + "#{name}-#{Gem::Version.new(version).to_s}.gem" end def normalize_bullets(markdown) @@ -89,6 +89,7 @@ end multitask :default => [:test, :features] +task :spec => :test require 'rake/testtask' Rake::TestTask.new(:test) do |test| test.libs << 'lib' << 'test' @@ -179,33 +180,44 @@ namespace :site do # Ensure the gh-pages dir exists so we can generate into it. puts "Checking for gh-pages dir..." unless File.exist?("./gh-pages") - puts "No gh-pages directory found. Run the following commands first:" - puts " `git clone git@github.com:jekyll/jekyll gh-pages" - puts " `cd gh-pages" - puts " `git checkout gh-pages`" - exit(1) + puts "Creating gh-pages dir..." + sh "git clone git@github.com:jekyll/jekyll gh-pages" end - # Ensure gh-pages branch is up to date. + # Ensure latest gh-pages branch history. Dir.chdir('gh-pages') do + sh "git checkout gh-pages" sh "git pull origin gh-pages" end - # Copy to gh-pages dir. - puts "Copying site to gh-pages branch..." - Dir.glob("site/*") do |path| - next if path.include? "_site" - sh "cp -R #{path} gh-pages/" + # Proceed to purge all files in case we removed a file in this release. + puts "Cleaning gh-pages directory..." + purge_exclude = %w[ + gh-pages/. + gh-pages/.. + gh-pages/.git + gh-pages/.gitignore + ] + FileList["gh-pages/{*,.*}"].exclude(*purge_exclude).each do |path| + sh "rm -rf #{path}" end - # Change any configuration settings for production. - config = YAML.load_file("gh-pages/_config.yml") - config.merge!({'sass' => {'style' => 'compressed'}}) - File.write('gh-pages/_config.yml', YAML.dump(config)) + # Copy site to gh-pages dir. + puts "Building site into gh-pages branch..." + ENV['JEKYLL_ENV'] = 'production' + 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. 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 sh "git add ." sh "git commit --allow-empty -m 'Updating to #{sha}.'" @@ -221,8 +233,7 @@ namespace :site do front_matter = { "layout" => "docs", "title" => "History", - "permalink" => "/docs/history/", - "prev_section" => "contributing" + "permalink" => "/docs/history/" } Dir.chdir('site/_docs/') do File.open("history.md", "w") do |file| @@ -237,7 +248,7 @@ namespace :site do desc "Write the site latest_version.txt file" 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 namespace :releases do diff --git a/benchmark/end-with-vs-regexp b/benchmark/end-with-vs-regexp new file mode 100644 index 00000000..cb849f42 --- /dev/null +++ b/benchmark/end-with-vs-regexp @@ -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 diff --git a/benchmark/flat-map b/benchmark/flat-map index b10c5c9a..547bcee1 100644 --- a/benchmark/flat-map +++ b/benchmark/flat-map @@ -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('.flat_map with no nested arrays') { enum.flat_map { |i| do_thing(i) } } end - diff --git a/benchmark/string-replacement b/benchmark/string-replacement index 13715376..36de613c 100644 --- a/benchmark/string-replacement +++ b/benchmark/string-replacement @@ -8,6 +8,6 @@ Benchmark.ips do |x| x.report('#tr') { str.tr('some', 'a') } x.report('#gsub') { str.gsub('some', 'a') } x.report('#gsub!') { str.gsub!('some', 'a') } - x.report('#sub') { str.sub('some', 'a') } - x.report('#sub!') { str.sub!('some', 'a') } + x.report('#sub') { str.sub('some', 'a') } + x.report('#sub!') { str.sub!('some', 'a') } end diff --git a/bin/jekyll b/bin/jekyll index 060c9125..6c968cec 100755 --- a/bin/jekyll +++ b/bin/jekyll @@ -6,12 +6,9 @@ $:.unshift File.join(File.dirname(__FILE__), *%w{ .. lib }) require 'jekyll' require 'mercenary' -%w[jekyll-import].each do |blessed_gem| - begin - require blessed_gem - rescue LoadError - end -end +Jekyll::External.require_if_present( + Jekyll::External.blessed_gems +) Jekyll::PluginManager.require_from_bundler @@ -32,6 +29,7 @@ Mercenary.program(:jekyll) do |p| p.action do |args, options| if args.empty? + Jekyll.logger.error "A subcommand is required." puts p else unless p.has_command?(args.first) diff --git a/circle.yml b/circle.yml new file mode 100644 index 00000000..02259027 --- /dev/null +++ b/circle.yml @@ -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 diff --git a/features/collections.feature b/features/collections.feature index 4f69e8b9..91a271fc 100644 --- a/features/collections.feature +++ b/features/collections.feature @@ -9,7 +9,7 @@ Feature: Collections And I have a configuration file with "collections" set to "['methods']" When I run jekyll build Then the _site directory should exist - And I should see "Collections:

Use Jekyll.configuration to build a full configuration for use w/Jekyll.

\n\n

Whatever: foo.bar

\n

Jekyll.sanitized_path is used to make sure your path is in your source.

\n

Run your generators! default

\n

Page without title.

\n

Run your generators! default

" in "_site/index.html" + And I should see "Collections:

Use Jekyll.configuration to build a full configuration for use w/Jekyll.

\n\n

Whatever: foo.bar

\n

Signs are nice

\n

Jekyll.sanitized_path is used to make sure your path is in your source.

\n

Run your generators! default

\n

Page without title.

\n

Run your generators! default

" in "_site/index.html" And the "_site/methods/configuration.html" file should not exist Scenario: Rendered collection @@ -70,7 +70,7 @@ Feature: Collections """ When I run jekyll build 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 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 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 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 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 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 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 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 Then the _site directory should exist - And I should see "1. of 5:

Page without title.

" in "_site/index.html" + And I should see "1. of 7:

Page without title.

" in "_site/index.html" 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 %}" @@ -142,4 +142,4 @@ Feature: Collections """ When I run jekyll build 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" diff --git a/features/drafts.feature b/features/drafts.feature index c55edbb9..5d7982ec 100644 --- a/features/drafts.feature +++ b/features/drafts.feature @@ -43,4 +43,4 @@ Feature: Draft Posts | Recipe | 2009-03-27 | simple | Post path: {{ page.path }} | When I run jekyll build --drafts 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" diff --git a/features/embed_filters.feature b/features/embed_filters.feature index 889a1fc7..d6f99fc7 100644 --- a/features/embed_filters.feature +++ b/features/embed_filters.feature @@ -20,8 +20,6 @@ Feature: Embed filters And I have the following post: | title | date | layout | content | | 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 }}" When I run jekyll build Then the _site directory should exist @@ -33,7 +31,7 @@ Feature: Embed filters And I have the following post: | title | date | layout | content | | 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 Then the _site directory should exist 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 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 And I have a _layouts directory And I have the following post: | title | date | layout | content | | 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 Then the _site directory should exist And I should see "By

Obi-wan

" in "_site/2009/03/27/star-wars.html" diff --git a/features/frontmatter_defaults.feature b/features/frontmatter_defaults.feature index 7ac2d0a8..a9a64ae2 100644 --- a/features/frontmatter_defaults.feature +++ b/features/frontmatter_defaults.feature @@ -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"}}]" When I run jekyll build Then the _site directory should exist - And I should see "

some special data

Ben
" in "_site/2013/09/11/default-data.html" + And I should see "

some special data

\n
Ben
" in "_site/2013/09/11/default-data.html" And I should see "just some special data by Ben" in "_site/index.html" 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 "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:

content of site/2013/10/14/about.html

" in "_site/2013/10/14/about.html" + And I should see "main:

content of site/special/2013/10/14/about1.html

" in "_site/special/2013/10/14/about1.html" + And I should see "main:

content of site/special/2013/10/14/about2.html

" in "_site/special/2013/10/14/about2.html" + Scenario: Override frontmatter defaults by type Given I have a _posts directory And I have the following post: @@ -78,10 +100,19 @@ Feature: frontmatter defaults And I should see "nothing" in "_site/override.html" 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 Given I have a _slides directory And I have a "index.html" file that contains "nothing" - And I have a "_slides/slide1.html" file with content: + And I have a "_slides/slide1.html" file with content: """ --- --- @@ -107,7 +138,7 @@ Feature: frontmatter defaults Scenario: Override frontmatter defaults inside a collection Given I have a _slides directory And I have a "index.html" file that contains "nothing" - And I have a "_slides/slide2.html" file with content: + And I have a "_slides/slide2.html" file with content: """ --- myval: Override diff --git a/features/include_tag.feature b/features/include_tag.feature index 22a83480..c7e03ded 100644 --- a/features/include_tag.feature +++ b/features/include_tag.feature @@ -9,15 +9,15 @@ Feature: Include tags And I have an "_includes/params.html" file that contains "Parameters:" And I have an "_includes/ignore.html" file that contains "" And I have a _posts directory - And I have the following post: - | title | date | layout | content | - | Include Files | 2013-03-21 | default | {% include header.html param="myparam" %} | - | Ignore params if unused | 2013-03-21 | default | {% include ignore.html date="today" %} | - | List multiple parameters | 2013-03-21 | default | {% include params.html date="today" start="tomorrow" %} | - | Dont keep parameters | 2013-03-21 | default | {% 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' %} | - | Parameter syntax | 2013-04-12 | default | {% 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 %} | + And I have the following posts: + | title | date | type | content | + | Include Files | 2013-03-21 | html | {% include header.html param="myparam" %} | + | Ignore params if unused | 2013-03-21 | html | {% include ignore.html date="today" %} | + | List multiple parameters | 2013-03-21 | html | {% include params.html date="today" start="tomorrow" %} | + | 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 | html | {% include params.html cool="param with spaces" super="\"quoted\"" single='has "quotes"' escaped='\'single\' quotes' %} | + | Parameter syntax | 2013-04-12 | html | {% include params.html param1_or_2="value" %} | + | Pass a variable | 2013-06-22 | html | {% assign var = 'some text' %}{% include params.html local=var title=page.title %} | When I run jekyll build Then the _site directory should exist And I should see "
My awesome blog header: myparam
" in "_site/2013/03/21/include-files.html" @@ -27,12 +27,12 @@ Feature: Include tags And I should not see "
My awesome blog header: myparam
" in "_site/2013/03/21/dont-keep-parameters.html" But I should see "
My awesome blog header:
" in "_site/2013/03/21/dont-keep-parameters.html" And I should see "
  • cool = param with spaces
  • " in "_site/2013/04/07/allow-params-with-spaces-and-quotes.html" - And I should see "
  • super = “quoted”
  • " in "_site/2013/04/07/allow-params-with-spaces-and-quotes.html" - And I should see "
  • single = has “quotes”
  • " in "_site/2013/04/07/allow-params-with-spaces-and-quotes.html" - And I should see "
  • escaped = ‘single’ quotes
  • " in "_site/2013/04/07/allow-params-with-spaces-and-quotes.html" + And I should see "
  • super = \"quoted\"
  • " in "_site/2013/04/07/allow-params-with-spaces-and-quotes.html" + And I should see "
  • single = has \"quotes\"
  • " in "_site/2013/04/07/allow-params-with-spaces-and-quotes.html" + And I should see "
  • escaped = 'single' quotes
  • " in "_site/2013/04/07/allow-params-with-spaces-and-quotes.html" And I should see "
  • param1_or_2 = value
  • " in "_site/2013/04/12/parameter-syntax.html" And I should see "
  • local = some text
  • " in "_site/2013/06/22/pass-a-variable.html" - And I should see "
  • layout = default
  • " in "_site/2013/06/22/pass-a-variable.html" + And I should see "
  • title = Pass a variable
  • " in "_site/2013/06/22/pass-a-variable.html" Scenario: Include a file from a variable Given I have an _includes directory diff --git a/features/incremental_rebuild.feature b/features/incremental_rebuild.feature new file mode 100644 index 00000000..08739d3e --- /dev/null +++ b/features/incremental_rebuild.feature @@ -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:

    The only winning move is not to play.

    " in "_site/2009/03/27/wargames.html" + When I run jekyll build + Then the _site directory should exist + And I should see "Post Layout:

    The only winning move is not to play.

    " 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" diff --git a/features/markdown.feature b/features/markdown.feature index 659eed0f..2342951a 100644 --- a/features/markdown.feature +++ b/features/markdown.feature @@ -17,7 +17,10 @@ Feature: Markdown And I should see "

    My Title

    " in "_site/index.html" 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 a _posts directory 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" - Scenario: Maruku fenced codeblocks + Scenario: Maruku fenced codeblocks with syntax highlighting Given I have a configuration file with "markdown" set to "maruku" And I have an "index.markdown" file with content: """ diff --git a/features/pagination.feature b/features/pagination.feature index 21b96b08..b8b89ed0 100644 --- a/features/pagination.feature +++ b/features/pagination.feature @@ -4,7 +4,10 @@ Feature: Site pagination I want divide the posts in several pages Scenario Outline: Paginate with N posts per page - Given I have a configuration file with "paginate" set to "" + Given I have a configuration file with: + | key | value | + | paginate | | + | gems | [jekyll-paginate] | And I have a _layouts directory And I have an "index.html" page that contains "{{ paginator.posts.size }}" And I have a _posts directory @@ -32,6 +35,7 @@ Feature: Site pagination | paginate | 1 | | paginate_path | /blog/page-:num | | permalink | /blog/:year/:month/:day/:title | + | gems | [jekyll-paginate] | And I have a blog directory And I have an "blog/index.html" page that contains "{{ paginator.posts.size }}" And I have a _posts directory @@ -59,6 +63,7 @@ Feature: Site pagination | paginate | 1 | | paginate_path | /blog/page/:num | | permalink | /blog/:year/:month/:day/:title | + | gems | [jekyll-paginate] | And I have a blog directory 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!" diff --git a/features/permalinks.feature b/features/permalinks.feature index 67dfbb47..cb90d1f7 100644 --- a/features/permalinks.feature +++ b/features/permalinks.feature @@ -39,7 +39,7 @@ Feature: Fancy permalinks And I have the following post: | title | category | date | content | | 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 Then the _site directory should exist 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 And I have the following post: | 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 Then the _site 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 And the _site/custom/posts directory should exist 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" diff --git a/features/post_data.feature b/features/post_data.feature index 0ecaeef6..736fc936 100644 --- a/features/post_data.feature +++ b/features/post_data.feature @@ -141,7 +141,7 @@ Feature: Post data And I have a simple layout that contains "Post categories: {{ page.categories | array_to_sentence_string }}" When I run jekyll build 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 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 }}" When I run jekyll build 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 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 }}" When I run jekyll build 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/2013/03/17/star-trek.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" Scenario Outline: Use page.path variable Given I have a /_posts directory diff --git a/features/post_excerpts.feature b/features/post_excerpts.feature index 4ad6d128..e9d048bd 100644 --- a/features/post_excerpts.feature +++ b/features/post_excerpts.feature @@ -46,5 +46,5 @@ Feature: Post excerpts And the _site/2007/12 directory should exist And the _site/2007/12/31 directory should exist And the "_site/2007/12/31/entry1.html" file should exist - And I should see exactly "

    content for entry1.

    " in "_site/index.html" - And I should see exactly "

    content for entry1.

    " in "_site/2007/12/31/entry1.html" + And I should see "

    content for entry1.

    " in "_site/index.html" + And I should see "

    content for entry1.

    \n\n" in "_site/2007/12/31/entry1.html" diff --git a/features/rendering.feature b/features/rendering.feature index e0b9d8f0..55a9d3d2 100644 --- a/features/rendering.feature +++ b/features/rendering.feature @@ -15,6 +15,7 @@ Feature: Rendering Scenario: Don't place asset files in layout 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 a configuration file with "gems" set to "[jekyll-coffeescript]" And I have a simple layout that contains "{{ content }}Ahoy, indeed!" When I run jekyll build Then the _site directory should exist @@ -28,8 +29,15 @@ Feature: Rendering Then the _site directory should exist 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}}'" When I run jekyll build 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" diff --git a/features/site_configuration.feature b/features/site_configuration.feature index 1d067f0c..d3dadd2a 100644 --- a/features/site_configuration.feature +++ b/features/site_configuration.feature @@ -170,8 +170,8 @@ Feature: Site configuration When I run jekyll build Then the _site directory should exist And I should see "Page Layout: 2" in "_site/index.html" - And I should see "Post Layout:

    content for entry1.

    built at 2013-04-09T23:22:00-04:00" in "_site/2013/04/09/entry1.html" - And I should see "Post Layout:

    content for entry2.

    built at 2013-04-10T03:14:00-04:00" in "_site/2013/04/10/entry2.html" + And I should see "Post Layout:

    content for entry1.

    \n built at 2013-04-09T23:22:00-04:00" in "_site/2013/04/09/entry1.html" + And I should see "Post Layout:

    content for entry2.

    \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) 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 a configuration file with: | key | value | - | timezone | Australia/Melbourne | + | timezone | Pacific/Honolulu | And I have a _posts directory And I have the following posts: | title | date | layout | content | - | entry1 | 2013-04-09 23:22 -0400 | post | content for entry1. | - | entry2 | 2013-04-10 03:14 -0400 | post | content for entry2. | + | entry1 | 2013-04-09 23:22 +0400 | post | content for entry1. | + | entry2 | 2013-04-10 03:14 +0400 | post | content for entry2. | When I run jekyll build Then the _site directory should exist 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/10/entry2.html" file should exist - And I should see escaped "Post Layout:

    content for entry1.

    built at 2013-04-10T13:22:00+10:00" in "_site/2013/04/10/entry1.html" - And I should see escaped "Post Layout:

    content for entry2.

    built at 2013-04-10T17:14:00+10:00" in "_site/2013/04/10/entry2.html" + And the "_site/2013/04/09/entry1.html" file should exist + And the "_site/2013/04/09/entry2.html" file should exist + And I should see "Post Layout:

    content for entry1.

    \n built at 2013-04-09T09:22:00-10:00" in "_site/2013/04/09/entry1.html" + And I should see "Post Layout:

    content for entry2.

    \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 Given I have a _posts directory diff --git a/features/step_definitions/jekyll_steps.rb b/features/step_definitions/jekyll_steps.rb index b75379f5..5e0509e1 100644 --- a/features/step_definitions/jekyll_steps.rb +++ b/features/step_definitions/jekyll_steps.rb @@ -8,7 +8,7 @@ def file_content_from_hash(input_hash) input_hash['content'] end - <= 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.required_ruby_version = '>= 1.9.3' + s.required_ruby_version = '>= 2.0.0' - s.name = 'jekyll' - s.version = Jekyll::VERSION - s.license = 'MIT' + s.name = 'jekyll' + s.version = Jekyll::VERSION + s.license = 'MIT' - s.summary = "A simple, blog aware, static site generator." - s.description = "Jekyll is 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.authors = ["Tom Preston-Werner"] - s.email = 'tom@mojombo.com' - s.homepage = 'https://github.com/jekyll/jekyll' + s.authors = ['Tom Preston-Werner'] + s.email = 'tom@mojombo.com' + s.homepage = 'https://github.com/jekyll/jekyll' all_files = `git ls-files -z`.split("\x0") s.files = all_files.grep(%r{^(bin|lib)/}) 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.add_runtime_dependency('liquid', "~> 2.6.1") - s.add_runtime_dependency('kramdown', "~> 1.3") - s.add_runtime_dependency('mercenary', "~> 0.3.3") - s.add_runtime_dependency('safe_yaml', "~> 1.0") - s.add_runtime_dependency('colorator', "~> 0.1") - - # 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('liquid', '~> 3.0') + s.add_runtime_dependency('kramdown', '~> 1.3') + s.add_runtime_dependency('mercenary', '~> 0.3.3') + s.add_runtime_dependency('safe_yaml', '~> 1.0') + s.add_runtime_dependency('colorator', '~> 0.1') + s.add_runtime_dependency('rouge', '~> 1.7') s.add_runtime_dependency('jekyll-sass-converter', '~> 1.0') 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 diff --git a/lib/jekyll.rb b/lib/jekyll.rb index 03724100..02aa40b1 100644 --- a/lib/jekyll.rb +++ b/lib/jekyll.rb @@ -21,6 +21,7 @@ require 'time' require 'English' require 'pathname' require 'logger' +require 'set' # 3rd party require 'safe_yaml/load' @@ -29,6 +30,7 @@ require 'kramdown' require 'colorator' SafeYAML::OPTIONS[:suppress_warnings] = true +Liquid::Template.error_mode = :strict module Jekyll @@ -43,6 +45,7 @@ module Jekyll autoload :EntryFilter, 'jekyll/entry_filter' autoload :Errors, 'jekyll/errors' autoload :Excerpt, 'jekyll/excerpt' + autoload :External, 'jekyll/external' autoload :Filters, 'jekyll/filters' autoload :FrontmatterDefaults, 'jekyll/frontmatter_defaults' autoload :Layout, 'jekyll/layout' @@ -52,6 +55,7 @@ module Jekyll autoload :PluginManager, 'jekyll/plugin_manager' autoload :Post, 'jekyll/post' autoload :Publisher, 'jekyll/publisher' + autoload :Regenerator, 'jekyll/regenerator' autoload :RelatedPosts, 'jekyll/related_posts' autoload :Renderer, 'jekyll/renderer' autoload :Site, 'jekyll/site' @@ -153,6 +157,9 @@ module Jekyll end end + # Conditional optimizations + Jekyll::External.require_if_present('liquid-c') + end end @@ -162,11 +169,4 @@ require_all 'jekyll/converters/markdown' require_all 'jekyll/generators' require_all 'jekyll/tags' -# Eventually remove these for 3.0 as non-core -Jekyll::Deprecator.gracefully_require(%w[ - toml - jekyll-paginate - jekyll-gist - jekyll-coffeescript - jekyll-sass-converter -]) +require 'jekyll-sass-converter' diff --git a/lib/jekyll/cleaner.rb b/lib/jekyll/cleaner.rb index 6dd59ea0..a8b269f4 100644 --- a/lib/jekyll/cleaner.rb +++ b/lib/jekyll/cleaner.rb @@ -1,95 +1,101 @@ require 'set' module Jekyll - class Site - # Handles the cleanup of a site's destination before it is built. - class Cleaner - attr_reader :site + # Handles the cleanup of a site's destination before it is built. + class Cleaner + attr_reader :site - def initialize(site) - @site = site + def initialize(site) + @site = site + end + + # Cleans up the site's destination directory + def cleanup! + FileUtils.rm_rf(obsolete_files) + FileUtils.rm_rf(metadata_file) if @site.full_rebuild? + end + + private + + # Private: The list of files and directories to be deleted during cleanup process + # + # Returns an Array of the file and directory paths + def obsolete_files + (existing_files - new_files - new_dirs + replaced_files).to_a + 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. + # + # Returns a Set with the file paths + def existing_files + files = Set.new + Dir.glob(site.in_dest_dir("**", "*"), File::FNM_DOTMATCH) do |file| + files << file unless file =~ /\/\.{1,2}$/ || file =~ keep_file_regex || keep_dirs.include?(file) end + files + end - # Cleans up the site's destination directory - def cleanup! - FileUtils.rm_rf(obsolete_files) + # Private: The list of files to be created when site is built. + # + # Returns a Set with the file paths + def new_files + files = Set.new + site.each_site_file { |item| files << item.destination(site.dest) } + files + end + + # Private: The list of directories to be created when site is built. + # These are the parent directories of the files in #new_files. + # + # Returns a Set with the directory paths + def new_dirs + new_files.map { |file| parent_dirs(file) }.flatten.to_set + end + + # Private: The list of parent directories of a given file + # + # Returns an Array with the directory paths + def parent_dirs(file) + parent_dir = File.dirname(file) + if parent_dir == site.dest + [] + else + [parent_dir] + parent_dirs(parent_dir) end + end - private + # Private: The list of existing files that will be replaced by a directory during build + # + # Returns a Set with the file paths + def replaced_files + new_dirs.select { |dir| File.file?(dir) }.to_set + end - # Private: The list of files and directories to be deleted during cleanup process - # - # Returns an Array of the file and directory paths - def obsolete_files - (existing_files - new_files - new_dirs + replaced_files).to_a - end + # Private: The list of directories that need to be kept because they are parent directories + # of files specified in keep_files + # + # Returns a Set with the directory paths + def keep_dirs + site.keep_files.map { |file| parent_dirs(site.in_dest_dir(file)) }.flatten.to_set + end - # Private: The list of existing files, apart from those included in keep_files and hidden files. - # - # Returns a Set with the file paths - def existing_files - files = Set.new - Dir.glob(site.in_dest_dir("**", "*"), File::FNM_DOTMATCH) do |file| - files << file unless file =~ /\/\.{1,2}$/ || file =~ keep_file_regex || keep_dirs.include?(file) - end - files - end - - # Private: The list of files to be created when site is built. - # - # Returns a Set with the file paths - def new_files - files = Set.new - site.each_site_file { |item| files << item.destination(site.dest) } - files - end - - # Private: The list of directories to be created when site is built. - # These are the parent directories of the files in #new_files. - # - # Returns a Set with the directory paths - def new_dirs - new_files.map { |file| parent_dirs(file) }.flatten.to_set - end - - # Private: The list of parent directories of a given file - # - # Returns an Array with the directory paths - def parent_dirs(file) - parent_dir = File.dirname(file) - if parent_dir == site.dest - [] - else - [parent_dir] + parent_dirs(parent_dir) - end - end - - # Private: The list of existing files that will be replaced by a directory during build - # - # Returns a Set with the file paths - def replaced_files - new_dirs.select { |dir| File.file?(dir) }.to_set - end - - # Private: The list of directories that need to be kept because they are parent directories - # of files specified in keep_files - # - # Returns a Set with the directory paths - def keep_dirs - site.keep_files.map { |file| parent_dirs(site.in_dest_dir(file)) }.flatten.to_set - end - - # Private: Creates a regular expression from the config's keep_files array - # - # Examples - # ['.git','.svn'] creates the following regex: /\/(\.git|\/.svn)/ - # - # Returns the regular expression - def keep_file_regex - or_list = site.keep_files.join("|") - pattern = "\/(#{or_list.gsub(".", "\.")})" - Regexp.new pattern - end + # Private: Creates a regular expression from the config's keep_files array + # + # Examples + # ['.git','.svn'] creates the following regex: /\/(\.git|\/.svn)/ + # + # Returns the regular expression + def keep_file_regex + or_list = site.keep_files.join("|") + pattern = "\/(#{or_list.gsub(".", "\.")})" + Regexp.new pattern end end end diff --git a/lib/jekyll/collection.rb b/lib/jekyll/collection.rb index 73e480dd..e8740cf6 100644 --- a/lib/jekyll/collection.rb +++ b/lib/jekyll/collection.rb @@ -40,7 +40,7 @@ module Jekyll if Utils.has_yaml_header? full_path doc = Jekyll::Document.new(full_path, { site: site, collection: self }) doc.read - docs << doc + docs << doc if site.publisher.publish?(doc) else 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) @@ -170,7 +170,9 @@ module Jekyll # # Returns the URL template to render collection's documents at. 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 # Extract options for this collection from the site configuration. @@ -183,6 +185,5 @@ module Jekyll {} end end - end end diff --git a/lib/jekyll/command.rb b/lib/jekyll/command.rb index a1cc8c01..a72640fb 100644 --- a/lib/jekyll/command.rb +++ b/lib/jekyll/command.rb @@ -49,6 +49,8 @@ module Jekyll # Returns nothing def add_build_options(c) 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 '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' @@ -58,6 +60,7 @@ module Jekyll c.option 'unpublished', '--unpublished', 'Render posts that were marked as unpublished' c.option 'quiet', '-q', '--quiet', 'Silence output.' c.option 'verbose', '-V', '--verbose', 'Print verbose output.' + c.option 'full_rebuild', '-f', '--full-rebuild', 'Disable incremental rebuild.' end end diff --git a/lib/jekyll/commands/build.rb b/lib/jekyll/commands/build.rb index de234328..cc1e121f 100644 --- a/lib/jekyll/commands/build.rb +++ b/lib/jekyll/commands/build.rb @@ -48,13 +48,16 @@ module Jekyll # # Returns nothing. def build(site, options) + t = Time.now source = options['source'] destination = options['destination'] + full_build = options['full_rebuild'] Jekyll.logger.info "Source:", source Jekyll.logger.info "Destination:", destination + Jekyll.logger.info "Incremental build:", (full_build ? "disabled" : "enabled") Jekyll.logger.info "Generating..." process_site(site) - Jekyll.logger.info "", "done." + Jekyll.logger.info "", "done in #{(Time.now - t).round(3)} seconds." end # Private: Watch for file changes and rebuild the site. @@ -64,7 +67,7 @@ module Jekyll # # Returns nothing. def watch(site, options) - Deprecator.gracefully_require 'jekyll-watch' + External.require_with_graceful_fail 'jekyll-watch' Jekyll::Watcher.watch(options) end diff --git a/lib/jekyll/commands/clean.rb b/lib/jekyll/commands/clean.rb new file mode 100644 index 00000000..7d787d30 --- /dev/null +++ b/lib/jekyll/commands/clean.rb @@ -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 diff --git a/lib/jekyll/commands/docs.rb b/lib/jekyll/commands/docs.rb deleted file mode 100644 index 71c10160..00000000 --- a/lib/jekyll/commands/docs.rb +++ /dev/null @@ -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 diff --git a/lib/jekyll/commands/doctor.rb b/lib/jekyll/commands/doctor.rb index 0fab8b3a..e0ae36a1 100644 --- a/lib/jekyll/commands/doctor.rb +++ b/lib/jekyll/commands/doctor.rb @@ -39,7 +39,7 @@ module Jekyll contains_deprecated_pages = false site.pages.each do |page| 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" + " Jekyll v2.0.0 and beyond." contains_deprecated_pages = true diff --git a/lib/jekyll/commands/new.rb b/lib/jekyll/commands/new.rb index 724a1d8d..433d33b7 100644 --- a/lib/jekyll/commands/new.rb +++ b/lib/jekyll/commands/new.rb @@ -3,7 +3,7 @@ require 'erb' module Jekyll module Commands class New < Command - class << self + class << self def init_with_program(prog) prog.command(:new) do |c| c.syntax 'new PATH' @@ -11,7 +11,7 @@ module Jekyll c.option 'force', '--force', 'Force creation even if PATH already exists' c.option 'blank', '--blank', 'Creates scaffolding but with empty files' - + c.action do |args, options| Jekyll::Commands::New.process(args, options) end @@ -76,7 +76,7 @@ module Jekyll def scaffold_path "_posts/0000-00-00-welcome-to-jekyll.markdown.erb" end - end + end end end end diff --git a/lib/jekyll/commands/serve.rb b/lib/jekyll/commands/serve.rb index 2909f323..111d6709 100644 --- a/lib/jekyll/commands/serve.rb +++ b/lib/jekyll/commands/serve.rb @@ -40,7 +40,7 @@ module Jekyll s.mount( options['baseurl'], - WEBrick::HTTPServlet::FileHandler, + custom_file_handler, destination, file_handler_options ) @@ -50,7 +50,7 @@ module Jekyll if options['detach'] # detach the server pid = Process.fork { s.start } 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 t = Thread.new { s.start } trap("INT") { s.shutdown } @@ -99,6 +99,21 @@ module Jekyll opts 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) unless detached Proc.new { Jekyll.logger.info "Server running...", "press ctrl-c to stop." } diff --git a/lib/jekyll/configuration.rb b/lib/jekyll/configuration.rb index 7f1148a6..ca5d4839 100644 --- a/lib/jekyll/configuration.rb +++ b/lib/jekyll/configuration.rb @@ -21,7 +21,7 @@ module Jekyll 'keep_files' => ['.git','.svn'], 'encoding' => 'utf-8', 'markdown_ext' => 'markdown,mkdown,mkdn,mkd,md', - 'textile_ext' => 'textile', + 'full_rebuild' => false, # Filtering Content 'show_drafts' => nil, @@ -35,7 +35,7 @@ module Jekyll # Conversion 'markdown' => 'kramdown', - 'highlighter' => 'pygments', + 'highlighter' => 'rouge', 'lsi' => false, 'excerpt_separator' => "\n\n", @@ -74,12 +74,12 @@ module Jekyll }, 'kramdown' => { - 'auto_ids' => true, - 'footnote_nr' => 1, - 'entity_output' => 'as_char', - 'toc_levels' => '1..6', - 'smart_quotes' => 'lsquo,rsquo,ldquo,rdquo', - 'use_coderay' => false, + 'auto_ids' => true, + 'footnote_nr' => 1, + 'entity_output' => 'as_char', + 'toc_levels' => '1..6', + 'smart_quotes' => 'lsquo,rsquo,ldquo,rdquo', + 'enable_coderay' => false, 'coderay' => { 'coderay_wrap' => 'div', @@ -89,10 +89,6 @@ module Jekyll 'coderay_bold_every' => 10, 'coderay_css' => 'style' } - }, - - 'redcloth' => { - 'hard_breaks' => true } } @@ -119,6 +115,7 @@ module Jekyll def safe_load_file(filename) case File.extname(filename) when /\.toml/i + Jekyll::External.require_with_graceful_fail('toml') unless defined?(TOML) TOML.load_file(filename) when /\.ya?ml/i SafeYAML.load_file(filename) @@ -140,7 +137,7 @@ module Jekyll config_files = override.delete('config') if config_files.to_s.empty? 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 config_files = Jekyll.sanitized_path(source(override), "_config.#{default}") @default_config_file = true @@ -209,7 +206,7 @@ module Jekyll config = clone # Provide backwards-compatibility 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"+ " --[no-]watch/-w command-line option instead." config.delete('auto') @@ -217,14 +214,14 @@ module Jekyll end 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'" + " subcommand to serve your site with WEBrick." config.delete('server') end 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" + " file accordingly." # copy but don't overwrite: @@ -233,7 +230,7 @@ module Jekyll end 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" + " config file accordingly. The allowed values are 'rouge', " + "'pygments' or null." @@ -244,7 +241,7 @@ module Jekyll %w[include exclude].each do |option| 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" + " a string. For now, we've treated the string you provided" + " as a list of comma-separated values." @@ -253,11 +250,23 @@ module Jekyll config[option].map!(&:to_s) 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") Jekyll::Deprecator.deprecation_message "You're using the 'maruku' " + "Markdown processor. Maruku support has been deprecated and will " + "be removed in 3.0.0. We recommend you switch to Kramdown." 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 end diff --git a/lib/jekyll/converters/markdown.rb b/lib/jekyll/converters/markdown.rb index f0d1afb0..39389874 100644 --- a/lib/jekyll/converters/markdown.rb +++ b/lib/jekyll/converters/markdown.rb @@ -46,15 +46,12 @@ module Jekyll ].map(&:to_sym) end - def extname_matches_regexp - @extname_matches_regexp ||= Regexp.new( - '^\.(' + @config['markdown_ext'].gsub(',','|') +')$', - Regexp::IGNORECASE - ) + def extname_list + @extname_list ||= @config['markdown_ext'].split(',').map { |e| ".#{e.downcase}" } end def matches(ext) - ext =~ extname_matches_regexp + extname_list.include? ext.downcase end def output_ext(ext) diff --git a/lib/jekyll/converters/markdown/kramdown_parser.rb b/lib/jekyll/converters/markdown/kramdown_parser.rb index 097c9212..a9dbec96 100644 --- a/lib/jekyll/converters/markdown/kramdown_parser.rb +++ b/lib/jekyll/converters/markdown/kramdown_parser.rb @@ -13,14 +13,14 @@ module Jekyll def convert(content) # 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| key = "coderay_#{opt}" @config['kramdown'][key] = @config['kramdown']['coderay'][key] unless @config['kramdown'].key?(key) 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 diff --git a/lib/jekyll/converters/markdown/rdiscount_parser.rb b/lib/jekyll/converters/markdown/rdiscount_parser.rb index 0c8634e4..fb5172e7 100644 --- a/lib/jekyll/converters/markdown/rdiscount_parser.rb +++ b/lib/jekyll/converters/markdown/rdiscount_parser.rb @@ -3,7 +3,7 @@ module Jekyll class Markdown class RDiscountParser def initialize(config) - Jekyll::Deprecator.gracefully_require "rdiscount" + Jekyll::External.require_with_graceful_fail "rdiscount" @config = config @rdiscount_extensions = @config['rdiscount']['extensions'].map { |e| e.to_sym } end diff --git a/lib/jekyll/converters/markdown/redcarpet_parser.rb b/lib/jekyll/converters/markdown/redcarpet_parser.rb index 468069e9..3be60739 100644 --- a/lib/jekyll/converters/markdown/redcarpet_parser.rb +++ b/lib/jekyll/converters/markdown/redcarpet_parser.rb @@ -14,7 +14,7 @@ module Jekyll module WithPygments include CommonMethods def block_code(code, lang) - Jekyll::Deprecator.gracefully_require("pygments") + Jekyll::External.require_with_graceful_fail("pygments") lang = lang && lang.split.first || "text" add_code_tags( Pygments.highlight(code, :lexer => lang, :options => { :encoding => 'utf-8' }), @@ -55,7 +55,7 @@ module Jekyll def initialize(config) - Deprecator.gracefully_require("redcarpet") + External.require_with_graceful_fail("redcarpet") @config = config @redcarpet_extensions = {} @config['redcarpet']['extensions'].each { |e| @redcarpet_extensions[e.to_sym] = true } @@ -71,7 +71,7 @@ module Jekyll end when "rouge" Class.new(Redcarpet::Render::HTML) do - Jekyll::Deprecator.gracefully_require(%w[ + Jekyll::External.require_with_graceful_fail(%w[ rouge rouge/plugins/redcarpet ]) diff --git a/lib/jekyll/converters/textile.rb b/lib/jekyll/converters/textile.rb deleted file mode 100644 index c8137a3a..00000000 --- a/lib/jekyll/converters/textile.rb +++ /dev/null @@ -1,56 +0,0 @@ -module Jekyll - module Converters - class Textile < Converter - safe true - - highlighter_prefix '' - highlighter_suffix '' - - 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 diff --git a/lib/jekyll/convertible.rb b/lib/jekyll/convertible.rb index 4b21a66b..d587f8f3 100644 --- a/lib/jekyll/convertible.rb +++ b/lib/jekyll/convertible.rb @@ -207,6 +207,12 @@ module Jekyll info, 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 used.include?(layout) layout = nil # avoid recursive chain diff --git a/lib/jekyll/deprecator.rb b/lib/jekyll/deprecator.rb index 8e4daf9c..dfd3183c 100644 --- a/lib/jekyll/deprecator.rb +++ b/lib/jekyll/deprecator.rb @@ -21,7 +21,7 @@ module Jekyll def no_subcommand(args) if args.size > 0 && args.first =~ /^--/ && !%w[--help --version].include?(args.first) 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 @@ -40,22 +40,5 @@ module Jekyll Jekyll.logger.warn "Defaults:", "Please update your front-matter defaults to use 'type: #{current}'." 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 diff --git a/lib/jekyll/document.rb b/lib/jekyll/document.rb index 003c04eb..cd407dfa 100644 --- a/lib/jekyll/document.rb +++ b/lib/jekyll/document.rb @@ -4,9 +4,11 @@ module Jekyll class Document include Comparable - attr_reader :path, :site, :extname + attr_reader :path, :site, :extname, :output_ext attr_accessor :content, :collection, :output + YAML_FRONT_MATTER_REGEXP = /\A(---\s*\n.*?\n?)^((---|\.\.\.)\s*$\n?)/m + # Create a new Document. # # site - the Jekyll::Site instance to which this Document belongs @@ -17,6 +19,7 @@ module Jekyll @site = relations[:site] @path = path @extname = File.extname(path) + @output_ext = Jekyll::Renderer.new(site, self).output_ext @collection = relations[:collection] @has_yaml_header = nil end @@ -128,9 +131,9 @@ module Jekyll { collection: collection.label, path: cleaned_relative_path, - output_ext: Jekyll::Renderer.new(site, self).output_ext, + output_ext: output_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 @@ -160,8 +163,9 @@ module Jekyll # Returns the full path to the output file of this document. def destination(base_directory) dest = site.in_dest_dir(base_directory) - path = site.in_dest_dir(dest, url) - path = File.join(path, "index.html") if url =~ /\/$/ + path = site.in_dest_dir(dest, URL.unescape_path(url)) + path = File.join(path, "index.html") if url.end_with?("/") + path << output_ext unless path.end_with?(output_ext) path end @@ -210,7 +214,7 @@ module Jekyll @data = defaults end @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 data_file = SafeYAML.load($1) unless data_file.nil? @@ -233,8 +237,8 @@ module Jekyll Utils.deep_merge_hashes data, { "output" => output, "content" => content, - "path" => path, "relative_path" => relative_path, + "path" => relative_path, "url" => url, "collection" => collection.label } diff --git a/lib/jekyll/excerpt.rb b/lib/jekyll/excerpt.rb index 41d4976c..347be217 100644 --- a/lib/jekyll/excerpt.rb +++ b/lib/jekyll/excerpt.rb @@ -105,8 +105,7 @@ module Jekyll # # Returns excerpt String def extract_excerpt(post_content) - separator = site.config['excerpt_separator'] - head, _, tail = post_content.to_s.partition(separator) + head, _, tail = post_content.to_s.partition(post.excerpt_separator) "" << head << "\n\n" << tail.scan(/^\[[^\]]+\]:.+$/).join("\n") end diff --git a/lib/jekyll/external.rb b/lib/jekyll/external.rb new file mode 100644 index 00000000..e41bce27 --- /dev/null +++ b/lib/jekyll/external.rb @@ -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 diff --git a/lib/jekyll/filters.rb b/lib/jekyll/filters.rb index 2e4a1174..12d4eb5a 100644 --- a/lib/jekyll/filters.rb +++ b/lib/jekyll/filters.rb @@ -1,19 +1,9 @@ require 'uri' require 'json' +require 'date' module Jekyll 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. # # input - The Markdown String to convert. @@ -21,7 +11,7 @@ module Jekyll # Returns the HTML formatted String. def markdownify(input) site = @context.registers[:site] - converter = site.getConverterImpl(Jekyll::Converters::Markdown) + converter = site.find_converter_instance(Jekyll::Converters::Markdown) converter.convert(input) end @@ -32,7 +22,7 @@ module Jekyll # Returns the CSS formatted String. def sassify(input) site = @context.registers[:site] - converter = site.getConverterImpl(Jekyll::Converters::Sass) + converter = site.find_converter_instance(Jekyll::Converters::Sass) converter.convert(input) end @@ -43,19 +33,19 @@ module Jekyll # Returns the CSS formatted String. def scssify(input) site = @context.registers[:site] - converter = site.getConverterImpl(Jekyll::Converters::Scss) + converter = site.find_converter_instance(Jekyll::Converters::Scss) converter.convert(input) end # Slugify a filename or title. # # input - The filename or title to slugify. + # mode - how string is slugified # - # Returns the given filename or title as a lowercase String, with every - # sequence of spaces and non-alphanumeric characters replaced with a - # hyphen. - def slugify(input) - Utils.slugify(input) + # Returns the given filename or title as a lowercase URL String. + # See Utils.slugify for more detail. + def slugify(input, mode=nil) + Utils.slugify(input, mode) end # Format a date in short format e.g. "27 Jan 2011". @@ -232,6 +222,9 @@ module Jekyll # # Returns the filtered array of objects def sort(input, property = nil, nils = "first") + if input.nil? + raise ArgumentError.new("Cannot sort a null object.") + end if property.nil? input.sort else @@ -302,6 +295,8 @@ module Jekyll case input when Time input + when Date + input.to_time when String Time.parse(input) rescue Time.at(input.to_i) when Numeric @@ -309,7 +304,7 @@ module Jekyll else Jekyll.logger.error "Invalid Date:", "'#{input}' is not a valid datetime." exit(1) - end + end.localtime end def groupable?(element) @@ -328,14 +323,23 @@ module Jekyll def as_liquid(item) case item - when String, Numeric, true, false, nil - item.to_liquid 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 item.map{ |i| as_liquid(i) } 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 diff --git a/lib/jekyll/frontmatter_defaults.rb b/lib/jekyll/frontmatter_defaults.rb index 8355fa95..11eebf3f 100644 --- a/lib/jekyll/frontmatter_defaults.rb +++ b/lib/jekyll/frontmatter_defaults.rb @@ -168,7 +168,7 @@ module Jekyll end.compact 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) if path.nil? || path.empty? "" diff --git a/lib/jekyll/layout.rb b/lib/jekyll/layout.rb index 4dde59b6..c29f353f 100644 --- a/lib/jekyll/layout.rb +++ b/lib/jekyll/layout.rb @@ -8,6 +8,9 @@ module Jekyll # Gets the name of this layout. attr_reader :name + # Gets the path to this layout. + attr_reader :path + # Gets/Sets the extension of this layout. attr_accessor :ext @@ -26,6 +29,7 @@ module Jekyll @site = site @base = base @name = name + @path = site.in_source_dir(base, name) self.data = {} diff --git a/lib/jekyll/log_adapter.rb b/lib/jekyll/log_adapter.rb index 63e23fcd..46e0fe1f 100644 --- a/lib/jekyll/log_adapter.rb +++ b/lib/jekyll/log_adapter.rb @@ -1,6 +1,6 @@ module Jekyll class LogAdapter - attr_reader :writer + attr_reader :writer, :messages LOG_LEVELS = { :debug => ::Logger::DEBUG, @@ -16,6 +16,7 @@ module Jekyll # # Returns nothing def initialize(writer, level = :info) + @messages = [] @writer = writer self.log_level = level end @@ -87,7 +88,9 @@ module Jekyll # # Returns the formatted 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 # Internal: Format the topic diff --git a/lib/jekyll/page.rb b/lib/jekyll/page.rb index 98f730bf..a4ddb698 100644 --- a/lib/jekyll/page.rb +++ b/lib/jekyll/page.rb @@ -63,16 +63,12 @@ module Jekyll # # Returns the template String. def template - if site.permalink_style == :pretty - if index? && html? - "/:path/" - elsif html? - "/:path/:basename/" - else - "/:path/:basename:output_ext" - end - else + if !html? "/:path/:basename:output_ext" + elsif index? + "/:path/" + else + Utils.add_permalink_suffix("/:path/:basename", site.permalink_style) end end @@ -141,7 +137,8 @@ module Jekyll # Returns the destination file path String. def destination(dest) 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 end diff --git a/lib/jekyll/post.rb b/lib/jekyll/post.rb index c377e376..780f40f7 100644 --- a/lib/jekyll/post.rb +++ b/lib/jekyll/post.rb @@ -23,6 +23,8 @@ module Jekyll ATTRIBUTES_FOR_LIQUID = EXCERPT_ATTRIBUTES_FOR_LIQUID + %w[ content excerpt + excerpt_separator + draft? ] # Post name validator. Post filenames must be like: @@ -52,12 +54,12 @@ module Jekyll @base = containing_dir(dir) @name = name - self.categories = dir.downcase.split('/').reject { |x| x.empty? } + self.categories = dir.split('/').reject { |x| x.empty? } process(name) read_yaml(@base, name) 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 if data.key?('date') @@ -80,7 +82,7 @@ module Jekyll categories_from_data = Utils.pluralized_array_from_hash(data, 'category', 'categories') self.categories = ( Array(categories) + categories_from_data - ).map {|c| c.to_s.downcase}.flatten.uniq + ).map { |c| c.to_s }.flatten.uniq end def populate_tags @@ -118,6 +120,14 @@ module Jekyll data.fetch('title') { titleized_slug } 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 def titleized_slug slug.split('-').select {|w| w.capitalize! || w }.join(' ') @@ -218,7 +228,7 @@ module Jekyll :title => slug, :i_day => date.strftime("%-d"), :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_year => date.strftime("%y"), :y_day => date.strftime("%j"), @@ -269,7 +279,8 @@ module Jekyll def destination(dest) # The url needs to be unescaped in order to preserve the correct filename 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 end @@ -296,6 +307,11 @@ module Jekyll end end + # Returns if this Post is a Draft + def draft? + is_a?(Jekyll::Draft) + end + protected def extract_excerpt @@ -307,7 +323,7 @@ module Jekyll end def generate_excerpt? - !(site.config['excerpt_separator'].to_s.empty?) + !excerpt_separator.empty? end end end diff --git a/lib/jekyll/regenerator.rb b/lib/jekyll/regenerator.rb new file mode 100644 index 00000000..0616fdd9 --- /dev/null +++ b/lib/jekyll/regenerator.rb @@ -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 diff --git a/lib/jekyll/related_posts.rb b/lib/jekyll/related_posts.rb index 041ee551..b6899ec3 100644 --- a/lib/jekyll/related_posts.rb +++ b/lib/jekyll/related_posts.rb @@ -10,7 +10,7 @@ module Jekyll def initialize(post) @post = post @site = post.site - require 'classifier-reborn' if site.lsi + Jekyll::External.require_with_graceful_fail('classifier-reborn') if site.lsi end def build diff --git a/lib/jekyll/renderer.rb b/lib/jekyll/renderer.rb index f88a4187..f25ca343 100644 --- a/lib/jekyll/renderer.rb +++ b/lib/jekyll/renderer.rb @@ -3,11 +3,12 @@ module Jekyll class Renderer - attr_reader :document, :site + attr_reader :document, :site, :site_payload - def initialize(site, document) - @site = site - @document = document + def initialize(site, document, site_payload = nil) + @site = site + @document = document + @site_payload = site_payload end # Determine which converters to use based on this document's @@ -32,7 +33,7 @@ module Jekyll def run payload = Utils.deep_merge_hashes({ "page" => document.to_liquid - }, site.site_payload) + }, site_payload || site.site_payload) info = { filters: [Jekyll::Filters], @@ -138,6 +139,12 @@ module Jekyll 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 used.include?(layout) layout = nil # avoid recursive chain diff --git a/lib/jekyll/site.rb b/lib/jekyll/site.rb index 115b4133..96910255 100644 --- a/lib/jekyll/site.rb +++ b/lib/jekyll/site.rb @@ -11,6 +11,7 @@ module Jekyll :gems, :plugin_manager attr_accessor :converters, :generators + attr_reader :regenerator # Public: Initialize a new Site. # @@ -27,6 +28,9 @@ module Jekyll @source = File.expand_path(config['source']).freeze @dest = File.expand_path(config['destination']).freeze + # Initialize incremental regenerator + @regenerator = Regenerator.new(self) + self.plugin_manager = Jekyll::PluginManager.new(self) self.plugins = plugin_manager.plugins_path @@ -183,6 +187,7 @@ module Jekyll end pages.sort_by!(&:name) + static_files.sort_by!(&:relative_path) end # Read all the files in //_posts and create a new Post @@ -253,16 +258,26 @@ module Jekyll if File.directory?(path) read_data_to(path, data[key] = {}) else - case File.extname(path).downcase - when '.csv' - data[key] = CSV.read(path, :headers => true).map(&:to_hash) - else - data[key] = SafeYAML.load_file(path) - end + 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 + when '.csv' + CSV.read(path, { + :headers => true, + :encoding => config['encoding'] + }).map(&:to_hash) + else + SafeYAML.load_file(path) + end + end + # Read in all collections specified in the configuration # # Returns nothing. @@ -287,17 +302,22 @@ module Jekyll def render relative_permalinks_deprecation_method + payload = site_payload collections.each do |label, collection| 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 payload = site_payload [posts, pages].flatten.each do |page_or_post| - page_or_post.render(layouts, payload) + if regenerator.regenerate?(page_or_post) + page_or_post.render(layouts, payload) + end end - rescue Errno::ENOENT => e + rescue Errno::ENOENT # ignore missing layout dir end @@ -312,7 +332,10 @@ module Jekyll # # Returns nothing. def write - each_site_file { |item| item.write(dest) } + each_site_file { |item| + item.write(dest) if regenerator.regenerate?(item) + } + regenerator.write_metadata end # Construct a Hash of Posts indexed by the specified Post attribute. @@ -377,7 +400,7 @@ module Jekyll "time" => time, "posts" => posts.sort { |a, b| b <=> a }, "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?("/") }, "categories" => post_attr_hash('categories'), "tags" => post_attr_hash('tags'), @@ -405,13 +428,8 @@ module Jekyll # klass - The Class of the Converter to fetch. # # Returns the Converter instance implementing the given Converter. - def getConverterImpl(klass) - matches = converters.select { |c| c.class == klass } - if impl = matches.first - impl - else - raise "Converter implementation not found for #{klass}" - end + def find_converter_instance(klass) + converters.find { |c| c.class == klass } || proc { raise "No converter for #{klass}" }.call end # Create array of instances of the subclasses of the class or module @@ -453,7 +471,7 @@ module Jekyll def relative_permalinks_deprecation_method 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" + " site source directory, not the parent" + " directory. Check http://jekyllrb.com/docs/upgrading/"+ @@ -483,6 +501,17 @@ module Jekyll @frontmatter_defaults ||= FrontmatterDefaults.new(self) 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 def has_relative_page? @@ -499,13 +528,9 @@ module Jekyll end def sanitize_filename(name) - name.gsub!(/[^\w\s_-]+/, '') + name.gsub!(/[^\w\s-]+/, '') name.gsub!(/(^|\b\s)\s+($|\s?\b)/, '\\1\\2') name.gsub(/\s+/, '_') end - - def publisher - @publisher ||= Publisher.new(self) - end end end diff --git a/lib/jekyll/static_file.rb b/lib/jekyll/static_file.rb index eae85b54..b83f4fae 100644 --- a/lib/jekyll/static_file.rb +++ b/lib/jekyll/static_file.rb @@ -3,6 +3,8 @@ module Jekyll # The cache of last modification times [path] -> mtime. @@mtimes = Hash.new + attr_reader :relative_path + # Initialize a new StaticFile. # # site - The Site. @@ -15,6 +17,7 @@ module Jekyll @dir = dir @name = name @collection = collection + @relative_path = File.join(*[@dir, @name].compact) end # Returns source file path. @@ -22,11 +25,6 @@ module Jekyll File.join(*[@base, @dir, @name].compact) end - # Returns the source file path relative to the site source - def relative_path - @relative_path ||= File.join(*[@dir, @name].compact) - end - def extname File.extname(path) end @@ -81,6 +79,7 @@ module Jekyll FileUtils.mkdir_p(File.dirname(dest_path)) FileUtils.rm(dest_path) if File.exist?(dest_path) FileUtils.cp(path, dest_path) + File.utime(@@mtimes[path], @@mtimes[path], dest_path) true end diff --git a/lib/jekyll/tags/highlight.rb b/lib/jekyll/tags/highlight.rb index b51712b6..5589d38f 100644 --- a/lib/jekyll/tags/highlight.rb +++ b/lib/jekyll/tags/highlight.rb @@ -42,7 +42,7 @@ eos def render(context) prefix = context["highlighter_prefix"] || "" 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 @@ -75,9 +75,7 @@ eos end def render_pygments(code, is_safe) - require 'pygments' - - @options[:encoding] = 'utf-8' + Jekyll::External.require_with_graceful_fail('pygments') highlighted_code = Pygments.highlight( code, @@ -96,26 +94,26 @@ eos raise ArgumentError.new("Pygments.rb returned an unacceptable value when attempting to highlight some code.") end - highlighted_code + highlighted_code.sub('
    ', '').sub('
    ', '') end def render_rouge(code) - require 'rouge' + Jekyll::External.require_with_graceful_fail('rouge') formatter = Rouge::Formatters::HTML.new(line_numbers: @options[:linenos], wrap: false) lexer = Rouge::Lexer.find_fancy(@lang, code) || Rouge::Lexers::PlainText - code = formatter.format(lexer.lex(code)) - "
    #{code}
    " + formatter.format(lexer.lex(code)) end def render_codehighlighter(code) - "
    #{h(code).strip}
    " + h(code).strip end def add_code_tag(code) - # Add nested tags to code blocks - code = code.sub(/
    \n*/,'
    ')
    -        code = code.sub(/\n*<\/pre>/,"
    ") - code.strip + code_attributes = [ + "class=\"language-#{@lang.to_s.gsub('+', '-')}\"", + "data-lang=\"#{@lang.to_s}\"" + ].join(" ") + "
    #{code.chomp}
    " end end diff --git a/lib/jekyll/tags/include.rb b/lib/jekyll/tags/include.rb index 3eb4d7c0..b809ffe7 100644 --- a/lib/jekyll/tags/include.rb +++ b/lib/jekyll/tags/include.rb @@ -101,20 +101,29 @@ eos end def tag_includes_dir - '_includes' + '_includes'.freeze end def render(context) + site = context.registers[:site] dir = resolved_includes_dir(context) file = render_variable(context) || @file validate_file_name(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 - partial = Liquid::Template.parse(source(path, context)) + partial = Liquid::Template.parse(read_file(path, context)) context.stack do context['include'] = parse_params(context) if @params @@ -126,7 +135,7 @@ eos end def resolved_includes_dir(context) - File.join(File.realpath(context.registers[:site].source), @includes_dir) + context.registers[:site].in_source_dir(@includes_dir) end def validate_path(path, dir, safe) @@ -146,14 +155,14 @@ eos end # 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)) end end class IncludeRelativeTag < IncludeTag def tag_includes_dir - '.' + '.'.freeze end def page_path(context) diff --git a/lib/jekyll/url.rb b/lib/jekyll/url.rb index 6bed8d57..14b70631 100644 --- a/lib/jekyll/url.rb +++ b/lib/jekyll/url.rb @@ -44,12 +44,12 @@ module Jekyll # # Returns the _unsanitized String URL def generated_permalink - (@generated_permlink ||= generate_url(@permalink)) if @permalink + (@generated_permalink ||= generate_url(@permalink)) if @permalink end # Generates a URL from the template # - # Returns the _unsanitized String URL + # Returns the unsanitized String URL def generated_url @generated_url ||= generate_url(@template) end @@ -57,11 +57,16 @@ module Jekyll # Internal: Generate the URL by replacing all placeholders with their # respective values in the given template # - # Returns the _unsanitizied_ String URL + # Returns the unsanitized String URL def generate_url(template) @placeholders.inject(template) do |result, token| break result if result.index(':').nil? - result.gsub(/:#{token.first}/, self.class.escape_path(token.last)) + 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)) + end end end @@ -76,7 +81,7 @@ module Jekyll .gsub(/\A([^\/])/, '/\1') # 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 end @@ -102,7 +107,7 @@ module Jekyll # pct-encoded = "%" HEXDIG HEXDIG # sub-delims = "!" / "$" / "&" / "'" / "(" / ")" # / "*" / "+" / "," / ";" / "=" - URI.escape(path, /[^a-zA-Z\d\-._~!$&\'()*+,;=:@\/]/).encode('utf-8') + URI.escape(path, /[^a-zA-Z\d\-._~!$&'()*+,;=:@\/]/).encode('utf-8') end # Unescapes a URL path segment diff --git a/lib/jekyll/utils.rb b/lib/jekyll/utils.rb index 34861593..39302790 100644 --- a/lib/jekyll/utils.rb +++ b/lib/jekyll/utils.rb @@ -2,6 +2,12 @@ module Jekyll module Utils 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. # # 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 # if not def parse_date(input, msg = "Input could not be parsed.") - Time.parse(input) + Time.parse(input).localtime rescue ArgumentError raise Errors::FatalException.new("Invalid date '#{input}': " + msg) end @@ -104,21 +110,92 @@ module Jekyll # 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 - # sequence of spaces and non-alphanumeric characters replaced with a - # hyphen. - def slugify(string) - unless string.nil? - string \ - # Replace each non-alphanumeric character sequence with a hyphen - .gsub(/[^a-z0-9]+/i, '-') \ - # Remove leading/trailing hyphen - .gsub(/^\-|\-$/i, '') \ - # Downcase it - .downcase + # When mode is "none", return the given string in lowercase. + # + # When mode is "raw", return the given string in lowercase, + # with every sequence of spaces characters replaced with a hyphen. + # + # When mode is "default" or nil, non-alphabetic characters are + # replaced with a hyphen too. + # + # When mode is "pretty", some non-alphabetic characters (._~!$&'()+,;=@) + # are not replaced with hyphen. + # + # 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 + + 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 diff --git a/lib/jekyll/version.rb b/lib/jekyll/version.rb index 4df11160..64cdaba2 100644 --- a/lib/jekyll/version.rb +++ b/lib/jekyll/version.rb @@ -1,3 +1,3 @@ module Jekyll - VERSION = '2.5.2' + VERSION = '3.0.0.beta2' end diff --git a/lib/site_template/.gitignore b/lib/site_template/.gitignore index badbc02f..45c15053 100644 --- a/lib/site_template/.gitignore +++ b/lib/site_template/.gitignore @@ -1,2 +1,3 @@ _site .sass-cache +.jekyll-metadata diff --git a/lib/site_template/_config.yml b/lib/site_template/_config.yml index 2f03e74d..f4151011 100644 --- a/lib/site_template/_config.yml +++ b/lib/site_template/_config.yml @@ -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 line in _config.yml. It will appear in your document head meta (for 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 twitter_username: jekyllrb github_username: jekyll diff --git a/lib/site_template/_includes/footer.html b/lib/site_template/_includes/footer.html index be3976f7..8fa89ba9 100644 --- a/lib/site_template/_includes/footer.html +++ b/lib/site_template/_includes/footer.html @@ -5,19 +5,19 @@
    @@ -387,7 +388,7 @@ defaults: - scope: path: "projects" - type: "pages" + type: "pages" # previously `page` in Jekyll 2.2. values: layout: "project" # overrides previous default layout author: "Mr. Hyde" @@ -409,7 +410,7 @@ defaults: layout: "default" {% 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 @@ -447,9 +448,9 @@ The `projects/foo_project.md` would have the `layout` set to `foobar` instead of ## Default Configuration -Jekyll runs with the following configuration options by default. Unless -alternative settings for these options are explicitly specified in the -configuration file or on the command-line, Jekyll will run using these options. +Jekyll runs with the following configuration options by default. Alternative +settings for these options can be explicitly specified in the configuration +file or on the command-line.
    There are two unsupported kramdown options
    @@ -476,7 +477,6 @@ exclude: [] keep_files: [".git", ".svn"] encoding: "utf-8" markdown_ext: "markdown,mkdown,mkdn,mkd,md" -textile_ext: "textile" # Filtering Content show_drafts: null @@ -490,14 +490,14 @@ gems: [] # Conversion markdown: kramdown -highlighter: pygments +highlighter: rouge lsi: false excerpt_separator: "\n\n" # Serving detach: false port: 4000 -host: 0.0.0.0 +host: 127.0.0.1 baseurl: "" # does not include hostname # Backwards-compatibility @@ -527,12 +527,12 @@ redcarpet: extensions: [] kramdown: - auto_ids: true - footnote_nr: 1 - entity_output: as_char - toc_levels: 1..6 - smart_quotes: lsquo,rsquo,ldquo,rdquo - use_coderay: false + auto_ids: true + footnote_nr: 1 + entity_output: as_char + toc_levels: 1..6 + smart_quotes: lsquo,rsquo,ldquo,rdquo + enable_coderay: false coderay: coderay_wrap: div @@ -541,9 +541,6 @@ kramdown: coderay_tab_width: 4 coderay_bold_every: 10 coderay_css: style - -redcloth: - hard_breaks: true {% endhighlight %} ## Markdown Options diff --git a/site/_docs/continuous-integration.md b/site/_docs/continuous-integration.md index 0e2b3a5c..17823e1b 100644 --- a/site/_docs/continuous-integration.md +++ b/site/_docs/continuous-integration.md @@ -1,8 +1,6 @@ --- layout: docs title: Continuous Integration -prev_section: deployment-methods -next_section: troubleshooting permalink: /docs/continuous-integration/ --- @@ -62,7 +60,7 @@ HTML::Proofer.new("./_site").run {% endhighlight %} 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. [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 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. {% highlight yaml %} diff --git a/site/_docs/contributing.md b/site/_docs/contributing.md index e3dbe807..2ff5cd4f 100644 --- a/site/_docs/contributing.md +++ b/site/_docs/contributing.md @@ -1,8 +1,6 @@ --- layout: docs title: Contributing -prev_section: upgrading -next_section: history permalink: /docs/contributing/ --- @@ -99,7 +97,7 @@ You can find the documentation for jekyllrb.com in the [site]({{ site.repository }}/tree/master/site) directory of Jekyll's repo on GitHub.com. -All documentation pull requests should be directed at `master`. Pull +All documentation pull requests should be directed at `master`. Pull requests directed at another branch will not be accepted. The [Jekyll wiki]({{ site.repository }}/wiki) on GitHub diff --git a/site/_docs/datafiles.md b/site/_docs/datafiles.md index 7088fec4..7f54a279 100644 --- a/site/_docs/datafiles.md +++ b/site/_docs/datafiles.md @@ -1,8 +1,6 @@ --- layout: docs title: Data Files -prev_section: collections -next_section: assets permalink: /docs/datafiles/ --- diff --git a/site/_docs/deployment-methods.md b/site/_docs/deployment-methods.md index 2ab929b2..d9dd7ea2 100644 --- a/site/_docs/deployment-methods.md +++ b/site/_docs/deployment-methods.md @@ -1,8 +1,6 @@ --- layout: docs title: Deployment methods -prev_section: github-pages -next_section: continuous-integration permalink: /docs/deployment-methods/ --- @@ -93,7 +91,7 @@ Another way to deploy your Jekyll site is to use [Rake](https://github.com/jimwe ### rsync -Once you’ve 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). You’d obviously need to change the values to reflect your site’s details. There is even [a matching TextMate command](http://gist.github.com/214959) that will help you run +Once you’ve 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). You’d obviously need to change the values to reflect your site’s details. There is even [a matching TextMate command](http://gist.github.com/214959) that will help you run 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 -If you want to host your site in Amazon S3, you can do so with -[s3_website](https://github.com/laurilehmijoki/s3_website) application. It will -push your site to Amazon S3 where it can be served like any web server, +If you want to host your site in Amazon S3, you can do so by +using the [s3_website](https://github.com/laurilehmijoki/s3_website) +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 benefit of being about the cheapest hosting option available for low-volume blogs as you only pay for what you use. diff --git a/site/_docs/drafts.md b/site/_docs/drafts.md index 959964d0..9e7f1c6f 100644 --- a/site/_docs/drafts.md +++ b/site/_docs/drafts.md @@ -1,8 +1,6 @@ --- layout: docs title: Working with drafts -prev_section: posts -next_section: pages permalink: /docs/drafts/ --- @@ -17,5 +15,5 @@ first draft: {% endhighlight %} To preview your site with drafts, simply run `jekyll serve` or `jekyll build` with -the `--drafts` switch. Each will be assigned the value modification time of the draft file +the `--drafts` switch. Each will be assigned the value modification time of the draft file for its date, and thus you will see currently edited drafts as the latest posts. diff --git a/site/_docs/extras.md b/site/_docs/extras.md index 5bdf2c73..2af6a305 100644 --- a/site/_docs/extras.md +++ b/site/_docs/extras.md @@ -1,8 +1,6 @@ --- layout: docs title: Extras -prev_section: plugins -next_section: github-pages permalink: /docs/extras/ --- diff --git a/site/_docs/frontmatter.md b/site/_docs/frontmatter.md index 998be544..8c08f7df 100644 --- a/site/_docs/frontmatter.md +++ b/site/_docs/frontmatter.md @@ -1,8 +1,6 @@ --- layout: docs title: Front Matter -prev_section: configuration -next_section: posts permalink: /docs/frontmatter/ --- @@ -172,7 +170,9 @@ These are available out-of-the-box to be used in the front matter for a post.

    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 + YYYY-MM-DD HH:MM:SS +/-TTTT; hours, minutes, seconds, and timezone offset + are optional.

    diff --git a/site/_docs/github-pages.md b/site/_docs/github-pages.md index 83af0b3c..eac7d1ea 100644 --- a/site/_docs/github-pages.md +++ b/site/_docs/github-pages.md @@ -1,8 +1,6 @@ --- layout: docs title: GitHub Pages -prev_section: extras -next_section: deployment-methods permalink: /docs/github-pages/ --- diff --git a/site/_docs/history.md b/site/_docs/history.md index 036a4c99..346dc131 100644 --- a/site/_docs/history.md +++ b/site/_docs/history.md @@ -2,9 +2,41 @@ layout: docs title: 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 {: #v2-5-2} @@ -517,7 +549,7 @@ prev_section: contributing - Add `Jekyll::LiquidExtensions` with `.lookup_variable` method for easy looking up of variable values in a Liquid context. ([#2253]({{ site.repository }}/issues/2253)) - Remove literal lang name from class ([#2292]({{ site.repository }}/issues/2292)) -- Return `utf-8` encoding in header for webrick error page response ([#2289]({{ site.repository }}/issues/2289)) +- Return `utf-8` encoding in header for webrick error page response ([#2289]({{ site.repository }}/issues/2289)) - Make template site easier to customize ([#2268]({{ site.repository }}/issues/2268)) - Add two-digit year to permalink template option ([#2301]({{ site.repository }}/issues/2301)) - Add `site.documents` to Liquid payload (list of all docs) ([#2295]({{ site.repository }}/issues/2295)) diff --git a/site/_docs/index.md b/site/_docs/index.md index 27b2da25..bbb18087 100644 --- a/site/_docs/index.md +++ b/site/_docs/index.md @@ -1,7 +1,6 @@ --- layout: docs title: Welcome -next_section: quickstart permalink: /docs/home/ --- @@ -15,10 +14,9 @@ development of Jekyll itself. Jekyll is a simple, blog-aware, static site generator. It takes a template directory containing raw text files in various formats, runs it through -[Markdown](http://daringfireball.net/projects/markdown/) (or -[Textile](http://redcloth.org/textile)) and -[Liquid](https://github.com/Shopify/liquid/wiki) -converters, and spits out a complete, ready-to-publish static website suitable +a converter (like [Markdown](http://daringfireball.net/projects/markdown/)) +and our [Liquid](https://github.com/Shopify/liquid/wiki) renderer, 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 behind [GitHub Pages](http://pages.github.com), which means you can use Jekyll to host your project’s page, blog, or website from GitHub’s servers **for diff --git a/site/_docs/installation.md b/site/_docs/installation.md index 058879e9..0f4398b3 100644 --- a/site/_docs/installation.md +++ b/site/_docs/installation.md @@ -1,8 +1,6 @@ --- layout: docs title: Installation -prev_section: quickstart -next_section: usage permalink: /docs/installation/ --- diff --git a/site/_docs/migrations.md b/site/_docs/migrations.md index a080c6c6..0544341a 100644 --- a/site/_docs/migrations.md +++ b/site/_docs/migrations.md @@ -1,8 +1,6 @@ --- layout: docs title: Blog migrations -prev_section: assets -next_section: templates permalink: /docs/migrations/ --- diff --git a/site/_docs/pages.md b/site/_docs/pages.md index e7b837fa..d3008daf 100644 --- a/site/_docs/pages.md +++ b/site/_docs/pages.md @@ -1,8 +1,6 @@ --- layout: docs title: Creating pages -prev_section: drafts -next_section: variables permalink: /docs/pages/ --- @@ -60,7 +58,7 @@ and associated URLs might look like: ### 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 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 page’s folder. This way diff --git a/site/_docs/pagination.md b/site/_docs/pagination.md index 3bb7d139..71403d2a 100644 --- a/site/_docs/pagination.md +++ b/site/_docs/pagination.md @@ -1,8 +1,6 @@ --- layout: docs title: Pagination -prev_section: permalinks -next_section: plugins permalink: /docs/pagination/ --- @@ -32,10 +30,10 @@ paginate: 5 The number should be the maximum number of Posts you’d like to be displayed per- 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 %} -paginate_path: "blog/page:num/" +paginate_path: "/blog/page:num/" {% endhighlight %} 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 and `blog/page3/index.html` with the last 2 posts into the destination directory. +
    +
    Don't set a permalink
    +

    + Setting a permalink in the front matter of your blog page will cause pagination to break. Just omit the permalink. +

    +
    + ## Liquid Attributes Available The pagination plugin exposes the `paginator` liquid object with the following diff --git a/site/_docs/permalinks.md b/site/_docs/permalinks.md index dbcee2e2..bc9633b9 100644 --- a/site/_docs/permalinks.md +++ b/site/_docs/permalinks.md @@ -1,8 +1,6 @@ --- layout: docs title: Permalinks -prev_section: templates -next_section: pagination permalink: /docs/permalinks/ --- @@ -80,7 +78,10 @@ permalink is defined as `/:categories/:year/:month/:day/:title.html`.

    title

    -

    Title from the Post’s filename

    +

    + Title from the document’s filename. May be overridden via the + document’s slug YAML front matter. +

    @@ -137,6 +138,14 @@ enough to fix it all!

    /:categories/:year/:month/:day/:title/

    + + +

    ordinal

    + + +

    /:categories/:year/:y_day/:title.html

    + +

    none

    @@ -151,7 +160,7 @@ enough to fix it all! ## Permalink style examples -Given a post named: `/2009-04-29-slap-chop.textile` +Given a post named: `/2009-04-29-slap-chop.md`
    diff --git a/site/_docs/plugins.md b/site/_docs/plugins.md index 9f7f482c..6b62d3fe 100644 --- a/site/_docs/plugins.md +++ b/site/_docs/plugins.md @@ -1,8 +1,6 @@ --- layout: docs title: Plugins -prev_section: pagination -next_section: extras permalink: /docs/plugins/ --- @@ -13,8 +11,8 @@ having to modify the Jekyll source itself.
    Plugins on GitHub Pages

    - GitHub Pages is powered by Jekyll, - however all Pages sites are generated using the --safe option + GitHub Pages is powered by Jekyll. + However, all Pages sites are generated using the --safe option to disable custom plugins for security reasons. Unfortunately, this means your plugins won’t work if you’re deploying to GitHub Pages.

    You can still use GitHub Pages to publish your site, but you’ll need to @@ -44,20 +42,21 @@ You have 3 options for installing plugins:

    - _plugins and gems + _plugins, _config.yml and Gemfile can be used simultaneously

    - You may use both 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 + 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 others.

    -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 -2. Converters -3. Tags +1. [Generators](#generators) +2. [Converters](#converters) +3. [Commands](#commands) +4. [Tags](#tags) ## Generators @@ -66,11 +65,8 @@ based on your own rules. A generator is a subclass of `Jekyll::Generator` that defines a `generate` method, which receives an instance of -[`Jekyll::Site`]({{ site.repository }}/blob/master/lib/jekyll/site.rb). - -Generation is triggered for its side-effects, the return value of `generate` is -ignored. Jekyll does not assume any particular side-effect to happen, it just -runs the method. +[`Jekyll::Site`]({{ site.repository }}/blob/master/lib/jekyll/site.rb). The +return value of `generate` is ignored. 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 @@ -168,8 +164,9 @@ Generators are only required to implement one method: ## Converters If you have a new markup language you’d like to use with your site, you can -include it by implementing your own converter. Both the Markdown and Textile -markup languages are implemented using this method. +include it by implementing your own converter. Both the Markdown and +[Textile](https://github.com/jekyll/jekyll-textile-converter) markup +languages are implemented using this method.
    Remember your YAML Front Matter
    @@ -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, it will do so with a `.html` extension. -## Command +## Commands 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 @@ -276,7 +273,7 @@ class MyNewCommand < Jekyll::Command c.syntax "new [options]" 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| 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::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 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 +- [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. - [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. @@ -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. - [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. +- [AsciiDoc Plugin](https://github.com/asciidoctor/jekyll-asciidoc): AsciiDoc convertor for Jekyll using [Asciidoctor](http://asciidoctor.org/). #### 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-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. +- [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 @@ -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 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. -- [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. - [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. - [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 [``](http://picture.responsiveimages.org/) element, polyfilled with Scott Jehl’s [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 [``](https://html.spec.whatwg.org/multipage/embedded-content.html#the-picture-element) element, polyfilled with Scott Jehl’s [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. - [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 Twitter’s 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 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 -- [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. -- [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 -- [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. - [Jekyll plugins by Aucor](https://github.com/aucor/jekyll-plugins): Plugins for trimming unwanted newlines/whitespace and sorting pages by weight attribute. #### 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. - [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. @@ -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. - [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. -- [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. - [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 -- [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 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. diff --git a/site/_docs/posts.md b/site/_docs/posts.md index 504ea2fb..0b0e8773 100644 --- a/site/_docs/posts.md +++ b/site/_docs/posts.md @@ -1,8 +1,6 @@ --- layout: docs title: Writing posts -prev_section: frontmatter -next_section: drafts permalink: /docs/posts/ --- @@ -16,11 +14,12 @@ and web-based CMS systems, this will be a welcome change! ## The Posts Folder As explained on the [directory structure](../structure/) page, the `_posts` -folder is where your blog posts will live. These files can be either -[Markdown](http://daringfireball.net/projects/markdown/) or -[Textile](http://redcloth.org/textile) formatted text files, and as long as -they have [YAML Front Matter](../frontmatter/), they will be converted from their -source format into an HTML page that is part of your static site. +folder is where your blog posts will live. These files are generally +[Markdown](http://daringfireball.net/projects/markdown/) or HTML, but can +be other formats with the proper converter installed. +All posts must have [YAML Front Matter](../frontmatter/), and they will be +converted from their source format into an HTML page that is part of your +static site. ### Creating Post Files @@ -44,7 +43,7 @@ file. For example, the following are examples of valid post filenames:
    ProTip™: Link to other posts

    - Use the post_url + Use the post_url tag to link to other posts without having to worry about the URL's breaking when the site permalink style changes.

    @@ -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 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/) and -[Textile](http://redcloth.org/textile). These formats each have their own way -of marking up different types of content within a post, so you should -familiarize yourself with these formats and decide which one best suits your -needs. +[Markdown](http://daringfireball.net/projects/markdown/) out of the box, +and has [myriad extensions for other formats as well](/docs/plugins/#converters-1), +including the popular [Textile](http://redcloth.org/textile) format. These +formats each have their own way of marking up different types of content +within a post, so you should familiarize yourself with these formats and +decide which one best suits your needs.
    Be aware of character sets
    @@ -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. +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: +--- + +Excerpt + +Out-of-excerpt +{% endhighlight %} + ## Highlighting code snippets Jekyll also has built-in support for syntax highlighting of code snippets using diff --git a/site/_docs/quickstart.md b/site/_docs/quickstart.md index 66cd9450..666ac03d 100644 --- a/site/_docs/quickstart.md +++ b/site/_docs/quickstart.md @@ -1,8 +1,6 @@ --- layout: docs title: Quick-start guide -prev_section: home -next_section: installation permalink: /docs/quickstart/ --- diff --git a/site/_docs/resources.md b/site/_docs/resources.md index 8c29e16b..692ff58e 100644 --- a/site/_docs/resources.md +++ b/site/_docs/resources.md @@ -1,8 +1,6 @@ --- layout: docs title: Resources -prev_section: sites -next_section: upgrading permalink: /docs/resources/ --- @@ -38,10 +36,11 @@ Jekyll’s growing use is producing a wide variety of tutorials, frameworks, ext > “Jekyll is everything that I ever wanted in a blogging engine. Really. It isn’t perfect, but what’s excellent about it is that if there’s something wrong, I know exactly how it works and how to fix it. It runs on the your machine only, and is essentially an added”build" step between you and the browser. I coded this entire site in TextMate using standard HTML5 and CSS3, and then at the end I added just a few little variables to the markup. Presto-chango, my site is built and I am at peace with the world.” - [‘Build A Blog With Jekyll And GitHub Pages’, by Barry Clark](http://www.smashingmagazine.com/2014/08/01/build-blog-jekyll-github-pages/) > “I recently migrated my blog from WordPress to Jekyll, a fantastic website generator that’s designed for building minimal, static blogs to be hosted on GitHub Pages. The simplicity of Jekyll’s theming layer and writing workflow is fantastic; however, setting up my website took a lot longer than expected. In this article we'll walk through: the quickest way to set up a Jekyll powered blog, how to avoid common problems with using Jekyll, how to import your content from Wordpress, and more.” -- [Generating a Tag Cloud in Jekyll](http://www.justkez.com/generating-a-tag-cloud-in-jekyll/) +- [Generating a Tag Cloud in Jekyll](http://www.justkez.com/generating-a-tag-cloud-in-jekyll/) A guide to implementing a tag cloud and per-tag content pages using Jekyll. - A way to [extend Jekyll](https://github.com/rfelix/jekyll_ext) without forking and modifying the Jekyll gem codebase and some [portable Jekyll extensions](https://wiki.github.com/rfelix/jekyll_ext/extensions) that can be reused and shared. - [Using your Rails layouts in Jekyll](http://numbers.brighterplanet.com/2010/08/09/sharing-rails-views-with-jekyll) - [Adding Ajax pagination to Jekyll](http://eduardoboucas.com/blog/2014/11/10/adding-ajax-pagination-to-jekyll.html) +- [Using Jekyll’s Data Files to build a dynamic navbar](http://www.jordanthornquest.com/blog/building-dynamic-navbars-with-jekyll/) diff --git a/site/_docs/sites.md b/site/_docs/sites.md index 4e57aba7..c11da820 100644 --- a/site/_docs/sites.md +++ b/site/_docs/sites.md @@ -1,8 +1,6 @@ --- layout: docs title: Sites using Jekyll -prev_section: troubleshooting -next_section: resources permalink: /docs/sites/ --- diff --git a/site/_docs/structure.md b/site/_docs/structure.md index 2dca3e6b..848f1cce 100644 --- a/site/_docs/structure.md +++ b/site/_docs/structure.md @@ -1,8 +1,6 @@ --- layout: docs title: Directory structure -prev_section: usage -next_section: configuration permalink: /docs/structure/ --- diff --git a/site/_docs/templates.md b/site/_docs/templates.md index 2cd7461d..8014a2ee 100644 --- a/site/_docs/templates.md +++ b/site/_docs/templates.md @@ -1,8 +1,6 @@ --- layout: docs title: Templates -prev_section: migrations -next_section: permalinks permalink: /docs/templates/ --- @@ -177,17 +175,6 @@ common tasks easier.

    -
    - - - @@ -254,6 +250,16 @@ common tasks easier.
    -

    Textilize

    -

    Convert a Textile-formatted string into HTML, formatted via RedCloth

    -
    -

    - {% raw %}{{ page.excerpt | textilize }}{% endraw %} -

    -

    Markdownify

    @@ -214,11 +201,20 @@ common tasks easier.

    Slugify

    -

    Convert a string into a lowercase URL "slug" by replacing every sequence of spaces and non-alphanumeric characters with a hyphen.

    +

    Convert a string into a lowercase URL "slug". See below for options.

    - {% raw %}{{ page.title | slugify }}{% endraw %} + {% raw %}{{ "The _config.yml file" | slugify }}{% endraw %} +

    +

    + the-config-yml-file +

    +

    + {% raw %}{{ "The _config.yml file" | slugify: 'pretty' }}{% endraw %} +

    +

    + the-_config.yml-file

    +### Options for the `slugify` filter + +The `slugify` filter accepts an option, each specifying what to filter. +The default is `default`. They are as follows (with what they filter): + +- `none`: no characters +- `raw`: spaces +- `default`: spaces and non-alphanumeric characters +- `pretty`: spaces and non-alphanumeric characters except for `._~!$&'()+,;=@` + ## Tags ### Includes @@ -303,7 +309,7 @@ You can also choose to include file fragments relative to the current file: You won't need to place your included content within the `_includes` directory. Instead, the inclusion is specifically relative to the file where the tag is being used. For example, if `_posts/2014-09-03-my-file.markdown` uses the `include_relative` tag, the included file -must be within the `_posts` directory, or one of it's subdirectories. You cannot include +must be within the `_posts` directory, or one of its subdirectories. You cannot include files in other locations. All the other capabilities of the `include` tag are available to the `include_relative` tag, @@ -318,9 +324,9 @@ on your system and set `highlighter` to `pygments` in your site's configuration file. Alternatively, you can use [Rouge](https://github.com/jayferd/rouge) to highlight -your code snippets. It doesn't support as many languages as Pygments does but -it should fit in most cases and it's written in pure Ruby ; you don't need Python -on your system! +your code snippets. It doesn't support as many languages as Pygments, however it +should suit most use cases. Also, since [Rouge](https://github.com/jayferd/rouge) +is written in pure Ruby, you don't need Python on your system! To render a code block with syntax highlighting, surround your code as follows: diff --git a/site/_docs/troubleshooting.md b/site/_docs/troubleshooting.md index 14023094..eb65fd40 100644 --- a/site/_docs/troubleshooting.md +++ b/site/_docs/troubleshooting.md @@ -1,15 +1,18 @@ --- layout: docs title: Troubleshooting -prev_section: deployment-methods -next_section: sites permalink: /docs/troubleshooting/ --- If you ever run into problems installing or using Jekyll, here are a few tips that might be of help. If the problem you’re experiencing isn’t covered below, -please [report an issue]({{site.help_url}}/issues/new) so the -Jekyll community can make everyone’s experience better. +**please [check out our other help resources](/help/)** as well. + +- [Installation Problems](#installation-problems) +- [Problems running Jekyll](#problems-running-jekyll) +- [Base-URL Problems](#base-url-problems) +- [Configuration problems](#configuration-problems) +- [Markup Problems](#markup-problems) ## Installation Problems @@ -27,7 +30,7 @@ On Red Hat, CentOS, and Fedora systems you can do this by running: sudo yum install ruby-devel {% endhighlight %} -On [NearlyFreeSpeech](http://nearlyfreespeech.net/) you need to run the +On [NearlyFreeSpeech](https://www.nearlyfreespeech.net/) you need to run the following commands before installing Jekyll: {% highlight bash %} @@ -97,9 +100,9 @@ http://localhost:4000/blog The order of precedence for conflicting [configuration settings](../configuration/) is as follows: -1. Command-line flags -2. Configuration file settings -3. Defaults +1. Command-line flags +2. Configuration file settings +3. Defaults That is: defaults are overridden by options specified in `_config.yml`, and flags specified at the command-line will override all other settings diff --git a/site/_docs/upgrading.md b/site/_docs/upgrading.md index 3a3f1670..879546c6 100644 --- a/site/_docs/upgrading.md +++ b/site/_docs/upgrading.md @@ -1,8 +1,6 @@ --- layout: docs title: Upgrading -prev_section: resources -next_section: contributing permalink: /docs/upgrading/ --- diff --git a/site/_docs/usage.md b/site/_docs/usage.md index 4959ad45..7a424bd4 100644 --- a/site/_docs/usage.md +++ b/site/_docs/usage.md @@ -1,8 +1,6 @@ --- layout: docs title: Basic Usage -prev_section: installation -next_section: structure permalink: /docs/usage/ --- @@ -28,10 +26,14 @@ $ jekyll build --watch
    Destination folders are cleaned on site builds

    The contents of <destination> are automatically - cleaned when the site is built. Files or folders that are not - created by your site will be removed. Do not use an important - location for <destination>; instead, use it as - a staging area and copy files from there to your web server. + cleaned, by default, when the site is built. Files or folders that are not + created by your site will be removed. Files and folders you wish to retain + in <destination> may be specified within the <keep_files> + configuration directive. +

    +

    + Do not use an important location for <destination>; + instead, use it as a staging area and copy files from there to your web server.

    @@ -81,4 +83,7 @@ $ jekyll build --source _source --destination _deploy {% endhighlight %} For more about the possible configuration options, see the -[configuration](../configuration/) page. \ No newline at end of file +[configuration](../configuration/) page. + +If you're interested in browsing these docs on-the-go, install the +`jekyll-docs` gem and run `jekyll docs` in your terminal. diff --git a/site/_docs/variables.md b/site/_docs/variables.md index 1c62bf83..628a9904 100644 --- a/site/_docs/variables.md +++ b/site/_docs/variables.md @@ -1,8 +1,6 @@ --- layout: docs title: Variables -prev_section: pages -next_section: collections permalink: /docs/variables/ --- diff --git a/site/_docs/windows.md b/site/_docs/windows.md index 81e909c9..7642592c 100644 --- a/site/_docs/windows.md +++ b/site/_docs/windows.md @@ -1,8 +1,6 @@ --- layout: docs title: Jekyll on Windows -prev_section: configuration -next_section: posts permalink: /docs/windows/ --- diff --git a/site/_includes/anchor_links.html b/site/_includes/anchor_links.html index 08e37b5b..c584ce5d 100644 --- a/site/_includes/anchor_links.html +++ b/site/_includes/anchor_links.html @@ -3,7 +3,8 @@ var anchor = document.createElement("a"); anchor.className = "header-link"; anchor.href = "#" + id; - anchor.innerHTML = ""; + anchor.innerHTML = "Permalink"; + anchor.title = "Permalink"; return anchor; }; diff --git a/site/_includes/docs_ul.html b/site/_includes/docs_ul.html index 366abe9d..7cc54174 100644 --- a/site/_includes/docs_ul.html +++ b/site/_includes/docs_ul.html @@ -13,6 +13,7 @@ {% for p in site.docs %} {% if p.url == item_url %}
  • {{ p.title }}
  • + {% break %} {% endif %} {% endfor %} diff --git a/site/_includes/footer.html b/site/_includes/footer.html index c42b1a46..09bab737 100644 --- a/site/_includes/footer.html +++ b/site/_includes/footer.html @@ -1,4 +1,4 @@ -