Merge branch 'master' into frontmatter-defaults

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

View File

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

View File

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

View File

@ -1,2 +1,2 @@
source 'https://rubygems.org'
gemspec
gemspec

View File

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

View File

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

View File

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

View File

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

View File

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

65
features/data.feature Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

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

View File

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

View File

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

View File

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

View File

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

View File

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