Merge branch 'master' into remove-jruby-and-ruby-head

* master: (41 commits)
  Fix rubocop offenses on master.
  script/fmt: print Rubocop version
  Update history to reflect merge of #5030 [ci skip]
  rubocop: separate deprecator error messages
  Update history to reflect merge of #5031 [ci skip]
  Update history to reflect merge of #5032 [ci skip]
  rubocop: fix code style
  rubocop: fix code style
  rubocop: fix code style
  Update history to reflect merge of #5024 [ci skip]
  Update history to reflect merge of #5025 [ci skip]
  utils: check that the object is a hash when merging default_proc
  Update history to reflect merge of #5026 [ci skip]
  rubocop: refactor modified? method
  Add a benchmark for capture vs. assign in Liquid. [ci skip]
  Update history to reflect merge of #5027 [ci skip]
  Add generator-jekyllized to third party plugins
  rubocop: fix code style
  rubocop: fix code style
  rubocop: fix code style
  ...
This commit is contained in:
Parker Moore 2016-06-29 00:52:58 -07:00
commit b772329c60
No known key found for this signature in database
GPG Key ID: 193CDEBA72063C58
42 changed files with 422 additions and 931 deletions

View File

@ -20,7 +20,7 @@
---
- [ ] I am on (or have tested on) ***MacOS*** 10+
- [ ] I am on (or have tested on) ***macOS*** 10+
- [ ] I am on (or have tested on) ***Debian/Ubuntu*** GNU/Linux
- [ ] I am on (or have tested on) ***Fedora*** GNU/Linux
- [ ] I am on (or have tested on) ***Arch*** GNU/Linux

View File

@ -4,16 +4,10 @@ AllCops:
Include:
- lib/**/*.rb
Exclude:
- exe/jekyll
- lib/jekyll/collection.rb
- lib/jekyll/command.rb
- lib/jekyll/configuration.rb
- lib/jekyll/convertible.rb
- lib/jekyll/document.rb
- lib/jekyll/regenerator.rb
- lib/jekyll/renderer.rb
- lib/jekyll/static_file.rb
- lib/jekyll/utils.rb
- bin/**/*
- benchmark/**/*
- script/**/*

View File

@ -30,6 +30,7 @@
* Run Site#generate for 'jekyll doctor' to catch plugin issues (#5005)
* Add normalize_whitepace filter (#4917)
* Move bin/jekyll to exe/jekyll to prevent collision with binstubs (#5014)
* Cleaning up site template & theme updates. (#4922)
### Bug Fixes
@ -95,6 +96,15 @@
* Rubocop: jekyll/lib/site.rb (#4973)
* Add timings for each scenario in cucumber & print worst offenders (#4908)
* rubocop: jekyll/lib/filters.rb (#4993)
* Fix rubocop offenses in exe/jekyll (#5017)
* Rubocop: lib/jekyll/command.rb (#5018)
* rubocop: lib/jekyll/static_file.rb (#5019)
* rubocop: lib/jekyll/utils.rb (#5026)
* rubocop: lib/jekyll/regenerator.rb (#5025)
* rubocop: lib/jekyll/configuration.rb (#5024)
* rubocop: lib/jekyll/renderer.rb style fixes (#5032)
* rubocop: lib/jekyll/convertible.rb style fixes (#5031)
* rubocop: lib/jekyll/document.rb style fixes (#5030)
### Site Enhancements
@ -149,6 +159,7 @@
* Windows docs: Command needs to be called from blog path (#5006)
* Update text to be consitent with example (#5010)
* Update template links to point to core Liquid site (#5012)
* Add generator-jekyllized to third-party plugins (#5027)
## 3.1.6 / 2016-05-19

View File

@ -0,0 +1,20 @@
require "liquid"
require "benchmark/ips"
puts "Ruby #{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}"
puts "Liquid #{Liquid::VERSION}"
template1 = '{% capture foobar %}foo{{ bar }}{% endcapture %}{{ foo }}{{ foobar }}'
template2 = '{% assign foobar = "foo" | append: bar %}{{ foobar }}'
def render(template)
Liquid::Template.parse(template).render("bar" => "42")
end
puts render(template1)
puts render(template2)
Benchmark.ips do |x|
x.report('capture') { render(template1) }
x.report('assign') { render(template2) }
end

View File

@ -1,10 +1,10 @@
#!/usr/bin/env ruby
STDOUT.sync = true
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), *%w( .. lib ))
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), *%w(.. lib)))
require 'jekyll'
require 'mercenary'
require "jekyll"
require "mercenary"
Jekyll::PluginManager.require_from_bundler
@ -12,22 +12,26 @@ Jekyll::Deprecator.process(ARGV)
Mercenary.program(:jekyll) do |p|
p.version Jekyll::VERSION
p.description 'Jekyll is a blog-aware, static site generator in Ruby'
p.syntax 'jekyll <subcommand> [options]'
p.description "Jekyll is a blog-aware, static site generator in Ruby"
p.syntax "jekyll <subcommand> [options]"
p.option 'source', '-s', '--source [DIR]', 'Source directory (defaults to ./)'
p.option 'destination', '-d', '--destination [DIR]', 'Destination directory (defaults to ./_site)'
p.option 'safe', '--safe', 'Safe mode (defaults to false)'
p.option 'plugins_dir', '-p', '--plugins PLUGINS_DIR1[,PLUGINS_DIR2[,...]]', Array, 'Plugins directory (defaults to ./_plugins)'
p.option 'layouts_dir', '--layouts DIR', String, 'Layouts directory (defaults to ./_layouts)'
p.option 'profile', '--profile', 'Generate a Liquid rendering profile'
p.option "source", "-s", "--source [DIR]", "Source directory (defaults to ./)"
p.option "destination", "-d", "--destination [DIR]",
"Destination directory (defaults to ./_site)"
p.option "safe", "--safe", "Safe mode (defaults to false)"
p.option "plugins_dir", "-p", "--plugins PLUGINS_DIR1[,PLUGINS_DIR2[,...]]", Array,
"Plugins directory (defaults to ./_plugins)"
p.option "layouts_dir", "--layouts DIR", String,
"Layouts directory (defaults to ./_layouts)"
p.option "profile", "--profile", "Generate a Liquid rendering profile"
Jekyll::External.require_if_present(Jekyll::External.blessed_gems) do |g|
cmd = g.split('-').last
cmd = g.split("-").last
p.command(cmd.to_sym) do |c|
c.syntax cmd
c.action do
Jekyll.logger.abort_with "You must install the '#{g}' gem to use the 'jekyll #{cmd}' command."
Jekyll.logger.abort_with "You must install the '#{g}' gem" \
" to use the 'jekyll #{cmd}' command."
end
end
end

View File

@ -72,6 +72,9 @@ ruby RUBY_VERSION
# Happy Jekylling!
gem "jekyll", "#{Jekyll::VERSION}"
# This is the default theme for new Jekyll sites. You may change this to anything you like.
gem "minima"
# If you want to use GitHub Pages, remove the "gem "jekyll"" above and
# uncomment the line below. To upgrade, run `bundle update github-pages`.
# gem "github-pages", group: :jekyll_plugins

View File

@ -86,8 +86,8 @@ module Jekyll
# Returns a Configuration filled with defaults and fixed for common
# problems and backwards-compatibility.
def from(user_config)
Utils.deep_merge_hashes(DEFAULTS, Configuration[user_config].stringify_keys).
fix_common_issues.add_default_collections
Utils.deep_merge_hashes(DEFAULTS, Configuration[user_config].stringify_keys)
.fix_common_issues.add_default_collections
end
end
@ -123,10 +123,10 @@ module Jekyll
def safe_load_file(filename)
case File.extname(filename)
when /\.toml/i
when %r!\.toml!i
Jekyll::External.require_with_graceful_fail("toml") unless defined?(TOML)
TOML.load_file(filename)
when /\.ya?ml/i
when %r!\.ya?ml!i
SafeYAML.load_file(filename) || {}
else
raise ArgumentError, "No parser for '#{filename}' is available.
@ -191,7 +191,7 @@ module Jekyll
begin
files.each do |config_file|
next if config_file.nil? or config_file.empty?
next if config_file.nil? || config_file.empty?
new_config = read_config_file(config_file)
configuration = Utils.deep_merge_hashes(configuration, new_config)
end
@ -220,60 +220,18 @@ module Jekyll
def backwards_compatibilize
config = clone
# Provide backwards-compatibility
if config.key?("auto") || config.key?("watch")
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")
config.delete("watch")
end
if config.key?("server")
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
check_auto(config)
check_server(config)
renamed_key "server_port", "port", config
renamed_key "plugins", "plugins_dir", config
renamed_key "layouts", "layouts_dir", config
renamed_key "data_source", "data_dir", config
if config.key?("pygments")
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."
config["highlighter"] = "pygments" if config["pygments"]
config.delete("pygments")
end
%w(include exclude).each do |option|
if config[option].is_a?(String)
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."
config[option] = csv_to_array(config[option])
end
config[option].map!(&:to_s) if config[option]
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.casecmp("maruku") == 0
Jekyll.logger.abort_with "Error:", "You're using the 'maruku' " \
"Markdown processor, which has been removed as of 3.0.0. " \
"We recommend you switch to Kramdown. To do this, replace " \
"`markdown: maruku` with `markdown: kramdown` in your " \
"`_config.yml` file."
end
check_pygments(config)
check_include_exclude(config)
check_coderay(config)
check_maruku(config)
config
end
@ -296,19 +254,19 @@ module Jekyll
config = clone
# It defaults to `{}`, so this is only if someone sets it to null manually.
return config if config['collections'].nil?
return config if config["collections"].nil?
# Ensure we have a hash.
if config['collections'].is_a?(Array)
config['collections'] = Hash[config['collections'].map { |c| [c, {}] }]
if config["collections"].is_a?(Array)
config["collections"] = Hash[config["collections"].map { |c| [c, {}] }]
end
config['collections'] = Utils.deep_merge_hashes(
{ 'posts' => {} }, config['collections']
config["collections"] = Utils.deep_merge_hashes(
{ "posts" => {} }, config["collections"]
).tap do |collections|
collections['posts']['output'] = true
if config['permalink']
collections['posts']['permalink'] ||= style_to_permalink(config['permalink'])
collections["posts"]["output"] = true
if config["permalink"]
collections["posts"]["permalink"] ||= style_to_permalink(config["permalink"])
end
end
@ -325,7 +283,6 @@ module Jekyll
end
private
def style_to_permalink(permalink_style)
case permalink_style.to_sym
when :pretty
@ -347,9 +304,78 @@ module Jekyll
# file - the file from which the config was extracted
#
# Raises an ArgumentError if given config is not a hash
private
def check_config_is_hash!(extracted_config, file)
unless extracted_config.is_a?(Hash)
raise ArgumentError.new("Configuration file: (INVALID) #{file}".yellow)
raise ArgumentError, "Configuration file: (INVALID) #{file}".yellow
end
end
private
def check_auto(config)
if config.key?("auto") || config.key?("watch")
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")
config.delete("watch")
end
end
private
def check_server(config)
if config.key?("server")
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
end
private
def check_pygments(config)
if config.key?("pygments")
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."
config["highlighter"] = "pygments" if config["pygments"]
config.delete("pygments")
end
end
private
def check_include_exclude(config)
%w(include exclude).each do |option|
if config[option].is_a?(String)
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."
config[option] = csv_to_array(config[option])
end
config[option].map!(&:to_s) if config[option]
end
end
private
def check_coderay(config)
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
end
private
def check_maruku(config)
if config.fetch("markdown", "kramdown").to_s.casecmp("maruku") == 0
Jekyll.logger.abort_with "Error:", "You're using the 'maruku' " \
"Markdown processor, which has been removed as of 3.0.0. " \
"We recommend you switch to Kramdown. To do this, replace " \
"`markdown: maruku` with `markdown: kramdown` in your " \
"`_config.yml` file."
end
end
end

View File

@ -1,6 +1,6 @@
# encoding: UTF-8
require 'set'
require "set"
# Convertible provides methods for converting a pagelike item
# from a certain type of markup into actual content
@ -20,12 +20,12 @@ module Jekyll
module Convertible
# Returns the contents as a String.
def to_s
content || ''
content || ""
end
# Whether the file is published or not, as indicated in YAML front-matter
def published?
!(data.key?('published') && data['published'] == false)
!(data.key?("published") && data["published"] == false)
end
# Read the YAML frontmatter.
@ -47,7 +47,7 @@ module Jekyll
end
rescue SyntaxError => e
Jekyll.logger.warn "YAML Exception reading #{filename}: #{e.message}"
rescue Exception => e
rescue => e
Jekyll.logger.warn "Error reading file #{filename}: #{e.message}"
end
@ -61,12 +61,13 @@ module Jekyll
def validate_data!(filename)
unless self.data.is_a?(Hash)
raise Errors::InvalidYAMLFrontMatterError, "Invalid YAML front matter in #{filename}"
raise Errors::InvalidYAMLFrontMatterError,
"Invalid YAML front matter in #{filename}"
end
end
def validate_permalink!(filename)
if self.data['permalink'] && self.data['permalink'].size == 0
if self.data["permalink"] && self.data["permalink"].empty?
raise Errors::InvalidPermalinkError, "Invalid permalink in #{filename}"
end
end
@ -79,7 +80,10 @@ module Jekyll
begin
converter.convert output
rescue => e
Jekyll.logger.error "Conversion error:", "#{converter.class} encountered an error while converting '#{path}':"
Jekyll.logger.error(
"Conversion error:",
"#{converter.class} encountered an error while converting '#{path}':"
)
Jekyll.logger.error("", e.to_s)
raise e
end
@ -112,12 +116,17 @@ module Jekyll
def render_liquid(content, payload, info, path)
site.liquid_renderer.file(path).parse(content).render!(payload, info)
rescue Tags::IncludeTagError => e
Jekyll.logger.error "Liquid Exception:", "#{e.message} in #{e.path}, included in #{path || self.path}"
Jekyll.logger.error(
"Liquid Exception:",
"#{e.message} in #{e.path}, included in #{path || self.path}"
)
raise e
# rubocop: disable RescueException
rescue Exception => e
Jekyll.logger.error "Liquid Exception:", "#{e.message} in #{path || self.path}"
raise e
end
# rubocop: enable RescueException
# Convert this Convertible's data to a Hash suitable for use by Liquid.
#
@ -168,7 +177,7 @@ module Jekyll
#
# Returns true if extname == .coffee, false otherwise.
def coffeescript_file?
'.coffee'.eql?(ext)
".coffee" == ext
end
# Determine whether the file should be rendered with Liquid.
@ -205,7 +214,10 @@ module Jekyll
# recursively render layouts
layout = layouts[data["layout"]]
Jekyll.logger.warn("Build Warning:", "Layout '#{data["layout"]}' requested in #{path} does not exist.") if invalid_layout? layout
Jekyll.logger.warn(
"Build Warning:",
"Layout '#{data["layout"]}' requested in #{path} does not exist."
) if invalid_layout? layout
used = Set.new([layout])
@ -228,12 +240,9 @@ module Jekyll
site.in_source_dir(layout.path)
)
if layout = layouts[layout.data["layout"]]
if used.include?(layout)
layout = nil # avoid recursive chain
else
used << layout
end
if (layout = layouts[layout.data["layout"]])
break if used.include?(layout)
used << layout
end
end
end
@ -249,7 +258,10 @@ module Jekyll
Jekyll.logger.debug "Pre-Render Hooks:", self.relative_path
Jekyll::Hooks.trigger hook_owner, :pre_render, self, payload
info = { :filters => [Jekyll::Filters], :registers => { :site => site, :page => payload["page"] } }
info = {
:filters => [Jekyll::Filters],
:registers => { :site => site, :page => payload["page"] }
}
# render and transform content (this becomes the final content of the object)
payload["highlighter_prefix"] = converters.first.highlighter_prefix
@ -278,9 +290,7 @@ module Jekyll
def write(dest)
path = destination(dest)
FileUtils.mkdir_p(File.dirname(path))
File.open(path, 'wb') do |f|
f.write(output)
end
File.write(path, output, :mode => "wb")
Jekyll::Hooks.trigger hook_owner, :post_write, self
end

View File

@ -7,9 +7,9 @@ module Jekyll
attr_reader :path, :site, :extname, :collection
attr_accessor :content, :output
YAML_FRONT_MATTER_REGEXP = /\A(---\s*\n.*?\n?)^((---|\.\.\.)\s*$\n?)/m
DATELESS_FILENAME_MATCHER = /^(.+\/)*(.*)(\.[^.]+)$/
DATE_FILENAME_MATCHER = /^(.+\/)*(\d+-\d+-\d+)-(.*)(\.[^.]+)$/
YAML_FRONT_MATTER_REGEXP = %r!\A(---\s*\n.*?\n?)^((---|\.\.\.)\s*$\n?)!m
DATELESS_FILENAME_MATCHER = %r!^(?:.+/)*(.*)(\.[^.]+)$!
DATE_FILENAME_MATCHER = %r!^(?:.+/)*(\d+-\d+-\d+)-(.*)(\.[^.]+)$!
# Create a new Document.
#
@ -51,16 +51,16 @@ module Jekyll
#
# Returns the merged data.
def merge_data!(other, source: "YAML front matter")
if other.key?('categories') && !other['categories'].nil?
if other['categories'].is_a?(String)
other['categories'] = other['categories'].split(" ").map(&:strip)
if other.key?("categories") && !other["categories"].nil?
if other["categories"].is_a?(String)
other["categories"] = other["categories"].split(" ").map(&:strip)
end
other['categories'] = (data['categories'] || []) | other['categories']
other["categories"] = (data["categories"] || []) | other["categories"]
end
Utils.deep_merge_hashes!(data, other)
if data.key?('date') && !data['date'].is_a?(Time)
data['date'] = Utils.parse_date(
data['date'].to_s,
if data.key?("date") && !data["date"].is_a?(Time)
data["date"] = Utils.parse_date(
data["date"].to_s,
"Document '#{relative_path}' does not have a valid date in the #{source}."
)
end
@ -68,7 +68,7 @@ module Jekyll
end
def date
data['date'] ||= (draft? ? source_file_mtime : site.time)
data["date"] ||= (draft? ? source_file_mtime : site.time)
end
def source_file_mtime
@ -81,7 +81,8 @@ module Jekyll
#
# Returns whether the document is a draft.
def draft?
data['draft'] ||= relative_path.index(collection.relative_directory).nil? && collection.label == "posts"
data["draft"] ||= relative_path.index(collection.relative_directory).nil? &&
collection.label == "posts"
end
# The path to the document, relative to the site source.
@ -89,7 +90,8 @@ module Jekyll
# Returns a String path which represents the relative path
# from the site source to this document
def relative_path
@relative_path ||= Pathname.new(path).relative_path_from(Pathname.new(site.source)).to_s
@relative_path ||= Pathname.new(path)
.relative_path_from(Pathname.new(site.source)).to_s
end
# The output extension of the document.
@ -103,7 +105,7 @@ module Jekyll
#
# Returns the basename without the file extname.
def basename_without_ext
@basename_without_ext ||= File.basename(path, '.*')
@basename_without_ext ||= File.basename(path, ".*")
end
# The base filename of the document.
@ -156,7 +158,7 @@ module Jekyll
#
# Returns true if extname == .coffee, false otherwise.
def coffeescript_file?
'.coffee'.eql?(extname)
".coffee" == extname
end
# Determine whether the file should be rendered with Liquid.
@ -195,7 +197,7 @@ module Jekyll
#
# Returns the permalink or nil if no permalink was set in the data.
def permalink
data && data.is_a?(Hash) && data['permalink']
data && data.is_a?(Hash) && data["permalink"]
end
# The computed URL for the document. See `Jekyll::URL#to_s` for more details.
@ -203,9 +205,9 @@ module Jekyll
# Returns the computed URL for the document.
def url
@url = URL.new({
:template => url_template,
:template => url_template,
:placeholders => url_placeholders,
:permalink => permalink
:permalink => permalink
}).to_s
end
@ -237,18 +239,17 @@ module Jekyll
def write(dest)
path = destination(dest)
FileUtils.mkdir_p(File.dirname(path))
File.open(path, 'wb') do |f|
f.write(output)
end
File.write(path, output, :mode => "wb")
trigger_hooks(:post_write)
end
# Whether the file is published or not, as indicated in YAML front-matter
#
# Returns true if the 'published' key is specified in the YAML front-matter and not `false`.
# Returns 'false' if the 'published' key is specified in the
# YAML front-matter and is 'false'. Otherwise returns 'true'.
def published?
!(data.key?('published') && data['published'] == false)
!(data.key?("published") && data["published"] == false)
end
# Read in the file and assign the content and data based on the file contents.
@ -263,23 +264,24 @@ module Jekyll
@data = SafeYAML.load_file(path)
else
begin
defaults = @site.frontmatter_defaults.all(relative_path, collection.label.to_sym)
merge_data!(defaults, source: "front matter defaults") unless defaults.empty?
defaults = @site.frontmatter_defaults.all(
relative_path,
collection.label.to_sym
)
merge_data!(defaults, :source => "front matter defaults") unless defaults.empty?
self.content = File.read(path, Utils.merged_file_read_opts(site, opts))
if content =~ YAML_FRONT_MATTER_REGEXP
self.content = $POSTMATCH
data_file = SafeYAML.load(Regexp.last_match(1))
merge_data!(data_file, source: "YAML front matter") if data_file
merge_data!(data_file, :source => "YAML front matter") if data_file
end
post_read
rescue SyntaxError => e
Jekyll.logger.error "Error:", "YAML Exception reading #{path}: #{e.message}"
rescue Exception => e
if e.is_a? Jekyll::Errors::FatalException
raise e
end
rescue => e
raise e if e.is_a? Jekyll::Errors::FatalException
Jekyll.logger.error "Error:", "could not read file #{path}: #{e.message}"
end
end
@ -287,19 +289,19 @@ module Jekyll
def post_read
if relative_path =~ DATE_FILENAME_MATCHER
date, slug, ext = $2, $3, $4
if !data['date'] || data['date'].to_i == site.time.to_i
merge_data!({"date" => date}, source: "filename")
date, slug, ext = Regexp.last_match.captures
if !data["date"] || data["date"].to_i == site.time.to_i
merge_data!({ "date" => date }, :source => "filename")
end
elsif relative_path =~ DATELESS_FILENAME_MATCHER
slug, ext = $2, $3
slug, ext = Regexp.last_match.captures
end
# Try to ensure the user gets a title.
data["title"] ||= Utils.titleize_slug(slug)
# Only overwrite slug & ext if they aren't specified.
data['slug'] ||= slug
data['ext'] ||= ext
data["slug"] ||= slug
data["ext"] ||= ext
populate_categories
populate_tags
@ -312,16 +314,19 @@ module Jekyll
#
# Returns nothing.
def categories_from_path(special_dir)
superdirs = relative_path.sub(/#{special_dir}(.*)/, '').split(File::SEPARATOR).reject do |c|
superdirs = relative_path.sub(%r!#{special_dir}(.*)!, "")
.split(File::SEPARATOR)
.reject do |c|
c.empty? || c.eql?(special_dir) || c.eql?(basename)
end
merge_data!({ 'categories' => superdirs }, source: "file path")
merge_data!({ "categories" => superdirs }, :source => "file path")
end
def populate_categories
merge_data!({
'categories' => (
Array(data['categories']) + Utils.pluralized_array_from_hash(data, 'category', 'categories')
"categories" => (
Array(data["categories"]) +
Utils.pluralized_array_from_hash(data, "category", "categories")
).map(&:to_s).flatten.uniq
})
end
@ -351,7 +356,7 @@ module Jekyll
#
# Returns the content of the document
def to_s
output || content || 'NO CONTENT'
output || content || "NO CONTENT"
end
# Compare this document against another document.
@ -361,7 +366,7 @@ module Jekyll
# equal or greater than the other doc's path. See String#<=> for more details.
def <=>(other)
return nil unless other.respond_to?(:data)
cmp = data['date'] <=> other.data['date']
cmp = data["date"] <=> other.data["date"]
cmp = path <=> other.path if cmp.nil? || cmp == 0
cmp
end
@ -380,7 +385,7 @@ module Jekyll
#
# Returns the document excerpt_separator
def excerpt_separator
(data['excerpt_separator'] || site.config['excerpt_separator']).to_s
(data["excerpt_separator"] || site.config["excerpt_separator"]).to_s
end
# Whether to generate an excerpt
@ -394,8 +399,6 @@ module Jekyll
pos = collection.docs.index { |post| post.equal?(self) }
if pos && pos < collection.docs.length - 1
collection.docs[pos + 1]
else
nil
end
end
@ -403,8 +406,6 @@ module Jekyll
pos = collection.docs.index { |post| post.equal?(self) }
if pos && pos > 0
collection.docs[pos - 1]
else
nil
end
end
@ -414,7 +415,7 @@ module Jekyll
end
def id
@id ||= File.join(File.dirname(url), (data['slug'] || basename_without_ext).to_s)
@id ||= File.join(File.dirname(url), (data["slug"] || basename_without_ext).to_s)
end
# Calculate related posts.
@ -433,8 +434,9 @@ module Jekyll
# Override of method_missing to check in @data for the key.
def method_missing(method, *args, &blck)
if data.key?(method.to_s)
Jekyll.logger.warn "Deprecation:", "Document##{method} is now a key in the #data hash."
Jekyll.logger.warn "", "Called by #{caller.first}."
Jekyll::Deprecator.deprecation_message "Document##{method} is now a key "\
"in the #data hash."
Jekyll::Deprecator.deprecation_message "Called by #{caller.first}."
data[method.to_s]
else
super

View File

@ -2,7 +2,7 @@ module Jekyll
class EntryFilter
attr_reader :site
SPECIAL_LEADING_CHARACTERS = [
".", "_", '#', "~"
".", "_", "#", "~"
].freeze
def initialize(site, base_directory = nil)

View File

@ -20,18 +20,14 @@ module Jekyll
def regenerate?(document)
case document
when Page
document.asset_file? || document.data['regenerate'] ||
source_modified_or_dest_missing?(
site.in_source_dir(document.relative_path), document.destination(@site.dest)
)
regenerate_page?(document)
when Document
!document.write? || document.data['regenerate'] ||
source_modified_or_dest_missing?(
document.path, document.destination(@site.dest)
)
regenerate_document?(document)
else
source_path = document.respond_to?(:path) ? document.path : nil
dest_path = document.respond_to?(:destination) ? document.destination(@site.dest) : nil
source_path = document.respond_to?(:path) ? document.path : nil
dest_path = if document.respond_to?(:destination)
document.destination(@site.dest)
end
source_modified_or_dest_missing?(source_path, dest_path)
end
end
@ -44,7 +40,7 @@ module Jekyll
metadata[path] = {
"mtime" => File.mtime(path),
"deps" => []
"deps" => []
}
cache[path] = true
end
@ -94,23 +90,14 @@ module Jekyll
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 File.exist?(path) && data["mtime"].eql?(File.mtime(path))
return cache[path] = false
else
return add(path)
end
if metadata[path]
# If we have seen this file before,
# check if it or one of its dependencies has been modified
existing_file_modified?(path)
else
# If we have not seen this file before, add it to the metadata and regenerate it
add(path)
end
# Path does not exist in metadata, add it
return add(path)
end
# Add a dependency of a path
@ -139,7 +126,7 @@ module Jekyll
#
# Returns the String path of the file.
def metadata_file
site.in_source_dir('.jekyll-metadata')
site.in_source_dir(".jekyll-metadata")
end
# Check if metadata has been disabled
@ -173,5 +160,40 @@ module Jekyll
{}
end
end
private
def regenerate_page?(document)
document.asset_file? || document.data["regenerate"] ||
source_modified_or_dest_missing?(
site.in_source_dir(document.relative_path), document.destination(@site.dest)
)
end
private
def regenerate_document?(document)
!document.write? || document.data["regenerate"] ||
source_modified_or_dest_missing?(
document.path, document.destination(@site.dest)
)
end
private
def existing_file_modified?(path)
# If one of this file dependencies have been modified,
# set the regeneration bit for both the dependency and the file to true
metadata[path]["deps"].each do |dependency|
if modified?(dependency)
return cache[dependency] = cache[path] = true
end
end
if File.exist?(path) && metadata[path]["mtime"].eql?(File.mtime(path))
# If this file has not been modified, set the regeneration bit to false
cache[path] = false
else
# If it has been modified, set it to true
add(path)
end
end
end
end

View File

@ -38,21 +38,21 @@ module Jekyll
payload["paginator"] = document.pager.to_liquid
end
if document.is_a?(Document) && document.collection.label == 'posts'
payload['site']['related_posts'] = document.related_posts
if document.is_a?(Document) && document.collection.label == "posts"
payload["site"]["related_posts"] = document.related_posts
else
payload['site']['related_posts'] = nil
payload["site"]["related_posts"] = nil
end
# render and transform content (this becomes the final content of the object)
payload['highlighter_prefix'] = converters.first.highlighter_prefix
payload['highlighter_suffix'] = converters.first.highlighter_suffix
payload["highlighter_prefix"] = converters.first.highlighter_prefix
payload["highlighter_suffix"] = converters.first.highlighter_suffix
Jekyll.logger.debug "Pre-Render Hooks:", document.relative_path
document.trigger_hooks(:pre_render, payload)
info = {
:registers => { :site => site, :page => payload['page'] }
:registers => { :site => site, :page => payload["page"] }
}
output = document.content
@ -88,7 +88,9 @@ module Jekyll
begin
converter.convert output
rescue => e
Jekyll.logger.error "Conversion error:", "#{converter.class} encountered an error while converting '#{document.relative_path}':"
Jekyll.logger.error "Conversion error:",
"#{converter.class} encountered an error while "\
"converting '#{document.relative_path}':"
Jekyll.logger.error("", e.to_s)
raise e
end
@ -106,12 +108,16 @@ module Jekyll
def render_liquid(content, payload, info, path = nil)
site.liquid_renderer.file(path).parse(content).render!(payload, info)
rescue Tags::IncludeTagError => e
Jekyll.logger.error "Liquid Exception:", "#{e.message} in #{e.path}, included in #{path || document.relative_path}"
Jekyll.logger.error "Liquid Exception:",
"#{e.message} in #{e.path}, included in #{path || document.relative_path}"
raise e
# rubocop: disable RescueException
rescue Exception => e
Jekyll.logger.error "Liquid Exception:", "#{e.message} in #{path || document.relative_path}"
Jekyll.logger.error "Liquid Exception:",
"#{e.message} in #{path || document.relative_path}"
raise e
end
# rubocop: enable RescueException
# Checks if the layout specified in the document actually exists
#
@ -132,16 +138,20 @@ module Jekyll
output = content.dup
layout = site.layouts[document.data["layout"]]
Jekyll.logger.warn("Build Warning:", "Layout '#{document.data["layout"]}' requested in #{document.relative_path} does not exist.") if invalid_layout? layout
Jekyll.logger.warn(
"Build Warning:",
"Layout '#{document.data["layout"]}' requested in "\
"#{document.relative_path} does not exist."
) if invalid_layout? layout
used = Set.new([layout])
used = Set.new([layout])
# Reset the payload layout data to ensure it starts fresh for each page.
payload["layout"] = nil
while layout
payload['content'] = output
payload['layout'] = Utils.deep_merge_hashes(layout.data, payload["layout"] || {})
payload["content"] = output
payload["layout"] = Utils.deep_merge_hashes(layout.data, payload["layout"] || {})
output = render_liquid(
layout.content,
@ -156,12 +166,9 @@ module Jekyll
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
else
used << layout
end
if (layout = site.layouts[layout.data["layout"]])
break if used.include?(layout)
used << layout
end
end

View File

@ -1,16 +1,25 @@
module Jekyll
class StaticFile
# The cache of last modification times [path] -> mtime.
@@mtimes = {}
attr_reader :relative_path, :extname
class << self
# The cache of last modification times [path] -> mtime.
def mtimes
@mtimes ||= {}
end
def reset_cache
@mtimes = nil
end
end
# Initialize a new StaticFile.
#
# site - The Site.
# base - The String path to the <source>.
# dir - The String path between <source> and the file.
# name - The String filename of the file.
# rubocop: disable ParameterLists
def initialize(site, base, dir, name, collection = nil)
@site = site
@base = base
@ -20,6 +29,7 @@ module Jekyll
@relative_path = File.join(*[@dir, @name].compact)
@extname = File.extname(@name)
end
# rubocop: enable ParameterLists
# Returns source file path.
def path
@ -56,7 +66,7 @@ module Jekyll
#
# Returns true if modified since last write.
def modified?
@@mtimes[path] != mtime
self.class.mtimes[path] != mtime
end
# Whether to write the file to the filesystem
@ -64,7 +74,7 @@ module Jekyll
# Returns true unless the defaults for the destination path from
# _config.yml contain `published: false`.
def write?
defaults.fetch('published', true)
defaults.fetch("published", true)
end
# Write the static file to the destination directory (if modified).
@ -76,28 +86,15 @@ module Jekyll
dest_path = destination(dest)
return false if File.exist?(dest_path) && !modified?
@@mtimes[path] = mtime
self.class.mtimes[path] = mtime
FileUtils.mkdir_p(File.dirname(dest_path))
FileUtils.rm(dest_path) if File.exist?(dest_path)
if @site.safe || Jekyll.env == "production"
FileUtils.cp(path, dest_path)
else
FileUtils.copy_entry(path, dest_path)
end
File.utime(@@mtimes[path], @@mtimes[path], dest_path)
copy_file(dest_path)
true
end
# Reset the mtimes cache (for testing purposes).
#
# Returns nothing.
def self.reset_cache
@@mtimes = {}
nil
end
def to_liquid
{
"extname" => extname,
@ -109,11 +106,11 @@ module Jekyll
def placeholders
{
:collection => @collection.label,
:path => relative_path[
:path => relative_path[
@collection.relative_directory.size..relative_path.size],
:output_ext => '',
:name => '',
:title => ''
:output_ext => "",
:name => "",
:title => ""
}
end
@ -125,10 +122,10 @@ module Jekyll
relative_path
else
::Jekyll::URL.new({
:template => @collection.url_template,
:template => @collection.url_template,
:placeholders => placeholders
})
end.to_s.gsub(/\/$/, '')
end.to_s.gsub(%r!/$!, "")
end
# Returns the type of the collection if present, nil otherwise.
@ -141,5 +138,15 @@ module Jekyll
def defaults
@defaults ||= @site.frontmatter_defaults.all url, type
end
private
def copy_file(dest_path)
if @site.safe || Jekyll.env == "production"
FileUtils.cp(path, dest_path)
else
FileUtils.copy_entry(path, dest_path)
end
File.utime(self.class.mtimes[path], self.class.mtimes[path], dest_path)
end
end
end

View File

@ -1,6 +1,6 @@
class Jekyll::ThemeBuilder
SCAFFOLD_DIRECTORIES = %w(
_layouts _includes _sass example example/_posts
_layouts _includes _sass
).freeze
attr_reader :name, :path
@ -12,6 +12,7 @@ class Jekyll::ThemeBuilder
def create!
create_directories
create_starter_files
create_gemspec
create_accessories
create_example_site
@ -55,6 +56,13 @@ class Jekyll::ThemeBuilder
def create_directories
mkdir_p(SCAFFOLD_DIRECTORIES)
mkdir_p(%w(example example/_posts))
end
def create_starter_files
%w(page post default).each do |layout|
write_file("_layouts/#{layout}.html", template("_layouts/#{layout}.html"))
end
end
def create_gemspec
@ -81,6 +89,7 @@ class Jekyll::ThemeBuilder
def initialize_git_repo
Jekyll.logger.info "initialize", path.join(".git").to_s
Dir.chdir(path.to_s) { `git init` }
write_file(".gitignore", template("gitignore"))
end
def user_name
@ -102,7 +111,7 @@ class Jekyll::ThemeBuilder
@theme_builder = theme_builder
end
def jekyll_pessimistic_version
def jekyll_version_with_minor
Jekyll::VERSION.split(".").take(2).join(".")
end

View File

@ -2,27 +2,25 @@
module Jekyll
module Utils
extend self
autoload :Platforms, 'jekyll/utils/platforms'
autoload :Platforms, "jekyll/utils/platforms"
autoload :Ansi, "jekyll/utils/ansi"
# Constants for use in #slugify
SLUGIFY_MODES = %w(raw default pretty)
SLUGIFY_MODES = %w(raw default pretty).freeze
SLUGIFY_RAW_REGEXP = Regexp.new('\\s+').freeze
SLUGIFY_DEFAULT_REGEXP = Regexp.new('[^[:alnum:]]+').freeze
SLUGIFY_DEFAULT_REGEXP = Regexp.new("[^[:alnum:]]+").freeze
SLUGIFY_PRETTY_REGEXP = Regexp.new("[^[:alnum:]._~!$&'()+,;=@]+").freeze
# Takes an indented string and removes the preceding spaces on each line
def strip_heredoc(str)
str.gsub(/^[ \t]{#{(str.scan(/^[ \t]*(?=\S)/).min || "").size}}/, "")
str.gsub(%r!^[ \t]{#{(str.scan(%r!^[ \t]*(?=\S)!).min || "").size}}!, "")
end
# Takes a slug and turns it into a simple title.
def titleize_slug(slug)
slug.split("-").map! do |val|
val.capitalize
end.join(" ")
slug.split("-").map!(&:capitalize).join(" ")
end
# Non-destructive version of deep_merge_hashes! See that method.
@ -42,21 +40,9 @@ module Jekyll
#
# Thanks to whoever made it.
def deep_merge_hashes!(target, overwrite)
target.merge!(overwrite) do |key, old_val, new_val|
if new_val.nil?
old_val
else
mergable?(old_val) && mergable?(new_val) ? deep_merge_hashes(old_val, new_val) : new_val
end
end
if target.respond_to?(:default_proc) && overwrite.respond_to?(:default_proc) && target.default_proc.nil?
target.default_proc = overwrite.default_proc
end
target.each do |key, val|
target[key] = val.dup if val.frozen? && duplicable?(val)
end
merge_values(target, overwrite)
merge_default_proc(target, overwrite)
duplicate_frozen_values(target)
target
end
@ -84,7 +70,9 @@ module Jekyll
# Returns an array
def pluralized_array_from_hash(hash, singular_key, plural_key)
[].tap do |array|
array << (value_from_singular_key(hash, singular_key) || value_from_plural_key(hash, plural_key))
value = value_from_singular_key(hash, singular_key)
value ||= value_from_plural_key(hash, plural_key)
array << value
end.flatten.compact
end
@ -146,11 +134,13 @@ module Jekyll
# Determines whether a given file has
#
# Returns true if the YAML front matter is present.
# rubocop: disable PredicateName
def has_yaml_header?(file)
!!(File.open(file, 'rb') { |f| f.readline } =~ /\A---\s*\r?\n/)
!!(File.open(file, "rb", &:readline) =~ %r!\A---\s*\r?\n!)
rescue EOFError
false
end
# rubocop: enable PredicateName
# Slugify a filename or title.
#
@ -185,7 +175,7 @@ module Jekyll
#
# Returns the slugified string.
def slugify(string, mode: nil, cased: false)
mode ||= 'default'
mode ||= "default"
return nil if string.nil?
unless SLUGIFY_MODES.include?(mode)
@ -195,21 +185,21 @@ module Jekyll
# Replace each character sequence with a hyphen
re =
case mode
when 'raw'
when "raw"
SLUGIFY_RAW_REGEXP
when 'default'
when "default"
SLUGIFY_DEFAULT_REGEXP
when 'pretty'
when "pretty"
# "._~!$&'()+,;=@" is human readable (not URI-escaped) in URL
# and is allowed in both extN and NTFS.
SLUGIFY_PRETTY_REGEXP
end
# Strip according to the mode
slug = string.gsub(re, '-')
slug = string.gsub(re, "-")
# Remove leading/trailing hyphen
slug.gsub!(/^\-|\-$/i, '')
slug.gsub!(%r!^\-|\-$!i, "")
slug.downcase! unless cased
slug
@ -280,7 +270,7 @@ module Jekyll
# Returns matched pathes
def safe_glob(dir, patterns, flags = 0)
return [] unless Dir.exist?(dir)
pattern = File.join(Array patterns)
pattern = File.join(Array(patterns))
return [dir] if pattern.empty?
Dir.chdir(dir) do
Dir.glob(pattern, flags).map { |f| File.join(dir, f) }
@ -297,5 +287,31 @@ module Jekyll
merged
end
private
def merge_values(target, overwrite)
target.merge!(overwrite) do |_key, old_val, new_val|
if new_val.nil?
old_val
elsif mergable?(old_val) && mergable?(new_val)
deep_merge_hashes(old_val, new_val)
else
new_val
end
end
end
private
def merge_default_proc(target, overwrite)
if target.is_a?(Hash) && overwrite.is_a?(Hash) && target.default_proc.nil?
target.default_proc = overwrite.default_proc
end
end
private
def duplicate_frozen_values(target)
target.each do |key, val|
target[key] = val.dup if val.frozen? && duplicable?(val)
end
end
end
end

View File

@ -4,6 +4,7 @@
# which you are expected to set up once and rarely edit after that. If you find
# yourself editing these this file very often, consider using Jekyll's data files
# feature for the data you need to update frequently.
#
# For technical reasons, this file is *NOT* reloaded automatically when you use
# 'jekyll serve'. If you change this file, please restart the server process.
@ -25,3 +26,4 @@ github_username: jekyll
# Build settings
markdown: kramdown
theme: minima

View File

@ -1,38 +0,0 @@
<footer class="site-footer">
<div class="wrapper">
<h2 class="footer-heading">{{ site.title | escape }}</h2>
<div class="footer-col-wrapper">
<div class="footer-col footer-col-1">
<ul class="contact-list">
<li>{{ site.title | escape }}</li>
<li><a href="mailto:{{ site.email }}">{{ site.email }}</a></li>
</ul>
</div>
<div class="footer-col footer-col-2">
<ul class="social-media-list">
{% if site.github_username %}
<li>
{% include icon-github.html username=site.github_username %}
</li>
{% endif %}
{% if site.twitter_username %}
<li>
{% include icon-twitter.html username=site.twitter_username %}
</li>
{% endif %}
</ul>
</div>
<div class="footer-col footer-col-3">
<p>{{ site.description | escape }}</p>
</div>
</div>
</div>
</footer>

View File

@ -1,12 +0,0 @@
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{% if page.title %}{{ page.title | escape }}{% else %}{{ site.title | escape }}{% endif %}</title>
<meta name="description" content="{% if page.excerpt %}{{ page.excerpt | strip_html | strip_newlines | truncate: 160 }}{% else %}{{ site.description | escape }}{% endif %}">
<link rel="stylesheet" href="{{ "/css/main.css" | prepend: site.baseurl }}">
<link rel="canonical" href="{{ page.url | replace:'index.html','' | prepend: site.baseurl | prepend: site.url }}">
<link rel="alternate" type="application/rss+xml" title="{{ site.title | escape }}" href="{{ "/feed.xml" | prepend: site.baseurl | prepend: site.url }}">
</head>

View File

@ -1,27 +0,0 @@
<header class="site-header" role="banner">
<div class="wrapper">
<a class="site-title" href="{{ site.baseurl }}/">{{ site.title | escape }}</a>
<nav class="site-nav">
<a href="#" class="menu-icon">
<svg viewBox="0 0 18 15">
<path fill="#424242" d="M18,1.484c0,0.82-0.665,1.484-1.484,1.484H1.484C0.665,2.969,0,2.304,0,1.484l0,0C0,0.665,0.665,0,1.484,0 h15.031C17.335,0,18,0.665,18,1.484L18,1.484z"/>
<path fill="#424242" d="M18,7.516C18,8.335,17.335,9,16.516,9H1.484C0.665,9,0,8.335,0,7.516l0,0c0-0.82,0.665-1.484,1.484-1.484 h15.031C17.335,6.031,18,6.696,18,7.516L18,7.516z"/>
<path fill="#424242" d="M18,13.516C18,14.335,17.335,15,16.516,15H1.484C0.665,15,0,14.335,0,13.516l0,0 c0-0.82,0.665-1.484,1.484-1.484h15.031C17.335,12.031,18,12.696,18,13.516L18,13.516z"/>
</svg>
</a>
<div class="trigger">
{% for my_page in site.pages %}
{% if my_page.title %}
<a class="page-link" href="{{ my_page.url | prepend: site.baseurl }}">{{ my_page.title | escape }}</a>
{% endif %}
{% endfor %}
</div>
</nav>
</div>
</header>

View File

@ -1 +0,0 @@
<a href="https://github.com/{{ include.username }}"><span class="icon icon--github">{% include icon-github.svg %}</span><span class="username">{{ include.username }}</span></a>

View File

@ -1 +0,0 @@
<svg viewBox="0 0 16 16"><path fill="#828282" d="M7.999,0.431c-4.285,0-7.76,3.474-7.76,7.761 c0,3.428,2.223,6.337,5.307,7.363c0.388,0.071,0.53-0.168,0.53-0.374c0-0.184-0.007-0.672-0.01-1.32 c-2.159,0.469-2.614-1.04-2.614-1.04c-0.353-0.896-0.862-1.135-0.862-1.135c-0.705-0.481,0.053-0.472,0.053-0.472 c0.779,0.055,1.189,0.8,1.189,0.8c0.692,1.186,1.816,0.843,2.258,0.645c0.071-0.502,0.271-0.843,0.493-1.037 C4.86,11.425,3.049,10.76,3.049,7.786c0-0.847,0.302-1.54,0.799-2.082C3.768,5.507,3.501,4.718,3.924,3.65 c0,0,0.652-0.209,2.134,0.796C6.677,4.273,7.34,4.187,8,4.184c0.659,0.003,1.323,0.089,1.943,0.261 c1.482-1.004,2.132-0.796,2.132-0.796c0.423,1.068,0.157,1.857,0.077,2.054c0.497,0.542,0.798,1.235,0.798,2.082 c0,2.981-1.814,3.637-3.543,3.829c0.279,0.24,0.527,0.713,0.527,1.437c0,1.037-0.01,1.874-0.01,2.129 c0,0.208,0.14,0.449,0.534,0.373c3.081-1.028,5.302-3.935,5.302-7.362C15.76,3.906,12.285,0.431,7.999,0.431z"/></svg>

Before

Width:  |  Height:  |  Size: 926 B

View File

@ -1 +0,0 @@
<a href="https://twitter.com/{{ include.username }}"><span class="icon icon--twitter">{% include icon-twitter.svg %}</span><span class="username">{{ include.username }}</span></a>

View File

@ -1 +0,0 @@
<svg viewBox="0 0 16 16"><path fill="#828282" d="M15.969,3.058c-0.586,0.26-1.217,0.436-1.878,0.515c0.675-0.405,1.194-1.045,1.438-1.809c-0.632,0.375-1.332,0.647-2.076,0.793c-0.596-0.636-1.446-1.033-2.387-1.033c-1.806,0-3.27,1.464-3.27,3.27 c0,0.256,0.029,0.506,0.085,0.745C5.163,5.404,2.753,4.102,1.14,2.124C0.859,2.607,0.698,3.168,0.698,3.767 c0,1.134,0.577,2.135,1.455,2.722C1.616,6.472,1.112,6.325,0.671,6.08c0,0.014,0,0.027,0,0.041c0,1.584,1.127,2.906,2.623,3.206 C3.02,9.402,2.731,9.442,2.433,9.442c-0.211,0-0.416-0.021-0.615-0.059c0.416,1.299,1.624,2.245,3.055,2.271 c-1.119,0.877-2.529,1.4-4.061,1.4c-0.264,0-0.524-0.015-0.78-0.046c1.447,0.928,3.166,1.469,5.013,1.469 c6.015,0,9.304-4.983,9.304-9.304c0-0.142-0.003-0.283-0.009-0.423C14.976,4.29,15.531,3.714,15.969,3.058z"/></svg>

Before

Width:  |  Height:  |  Size: 787 B

View File

@ -1,20 +0,0 @@
<!DOCTYPE html>
<html lang="en">
{% include head.html %}
<body>
{% include header.html %}
<main class="page-content" aria-label="Content">
<div class="wrapper">
{{ content }}
</div>
</main>
{% include footer.html %}
</body>
</html>

View File

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

View File

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

View File

@ -1,200 +0,0 @@
/**
* Reset some basic elements
*/
body, h1, h2, h3, h4, h5, h6,
p, blockquote, pre, hr,
dl, dd, ol, ul, figure {
margin: 0;
padding: 0;
}
/**
* Basic styling
*/
body {
font: $base-font-weight #{$base-font-size}/#{$base-line-height} $base-font-family;
color: $text-color;
background-color: $background-color;
-webkit-text-size-adjust: 100%;
-webkit-font-feature-settings: "kern" 1;
-moz-font-feature-settings: "kern" 1;
-o-font-feature-settings: "kern" 1;
font-feature-settings: "kern" 1;
font-kerning: normal;
}
/**
* Set `margin-bottom` to maintain vertical rhythm
*/
h1, h2, h3, h4, h5, h6,
p, blockquote, pre,
ul, ol, dl, figure,
%vertical-rhythm {
margin-bottom: $spacing-unit / 2;
}
/**
* Images
*/
img {
max-width: 100%;
vertical-align: middle;
}
/**
* Figures
*/
figure > img {
display: block;
}
figcaption {
font-size: $small-font-size;
}
/**
* Lists
*/
ul, ol {
margin-left: $spacing-unit;
}
li {
> ul,
> ol {
margin-bottom: 0;
}
}
/**
* Headings
*/
h1, h2, h3, h4, h5, h6 {
font-weight: $base-font-weight;
}
/**
* Links
*/
a {
color: $brand-color;
text-decoration: none;
&:visited {
color: darken($brand-color, 15%);
}
&:hover {
color: $text-color;
text-decoration: underline;
}
}
/**
* Blockquotes
*/
blockquote {
color: $grey-color;
border-left: 4px solid $grey-color-light;
padding-left: $spacing-unit / 2;
font-size: 18px;
letter-spacing: -1px;
font-style: italic;
> :last-child {
margin-bottom: 0;
}
}
/**
* Code formatting
*/
pre,
code {
font-size: 15px;
border: 1px solid $grey-color-light;
border-radius: 3px;
background-color: #eef;
}
code {
padding: 1px 5px;
}
pre {
padding: 8px 12px;
overflow-x: auto;
> code {
border: 0;
padding-right: 0;
padding-left: 0;
}
}
/**
* Wrapper
*/
.wrapper {
max-width: -webkit-calc(#{$content-width} - (#{$spacing-unit} * 2));
max-width: calc(#{$content-width} - (#{$spacing-unit} * 2));
margin-right: auto;
margin-left: auto;
padding-right: $spacing-unit;
padding-left: $spacing-unit;
@extend %clearfix;
@include media-query($on-laptop) {
max-width: -webkit-calc(#{$content-width} - (#{$spacing-unit}));
max-width: calc(#{$content-width} - (#{$spacing-unit}));
padding-right: $spacing-unit / 2;
padding-left: $spacing-unit / 2;
}
}
/**
* Clearfix
*/
%clearfix:after {
content: "";
display: table;
clear: both;
}
/**
* Icons
*/
.icon > svg {
display: inline-block;
width: 16px;
height: 16px;
vertical-align: middle;
path {
fill: $grey-color;
}
}

View File

@ -1,242 +0,0 @@
/**
* Site header
*/
.site-header {
border-top: 5px solid $grey-color-dark;
border-bottom: 1px solid $grey-color-light;
min-height: 56px;
// Positioning context for the mobile navigation icon
position: relative;
}
.site-title {
font-size: 26px;
font-weight: 300;
line-height: 56px;
letter-spacing: -1px;
margin-bottom: 0;
float: left;
&,
&:visited {
color: $grey-color-dark;
}
}
.site-nav {
float: right;
line-height: 56px;
.menu-icon {
display: none;
}
.page-link {
color: $text-color;
line-height: $base-line-height;
// Gaps between nav items, but not on the last one
&:not(:last-child) {
margin-right: 20px;
}
}
@include media-query($on-palm) {
position: absolute;
top: 9px;
right: $spacing-unit / 2;
background-color: $background-color;
border: 1px solid $grey-color-light;
border-radius: 5px;
text-align: right;
.menu-icon {
display: block;
float: right;
width: 36px;
height: 26px;
line-height: 0;
padding-top: 10px;
text-align: center;
> svg {
width: 18px;
height: 15px;
path {
fill: $grey-color-dark;
}
}
}
.trigger {
clear: both;
display: none;
}
&:hover .trigger {
display: block;
padding-bottom: 5px;
}
.page-link {
display: block;
padding: 5px 10px;
&:not(:last-child) {
margin-right: 0;
}
margin-left: 20px;
}
}
}
/**
* Site footer
*/
.site-footer {
border-top: 1px solid $grey-color-light;
padding: $spacing-unit 0;
}
.footer-heading {
font-size: 18px;
margin-bottom: $spacing-unit / 2;
}
.contact-list,
.social-media-list {
list-style: none;
margin-left: 0;
}
.footer-col-wrapper {
font-size: 15px;
color: $grey-color;
margin-left: -$spacing-unit / 2;
@extend %clearfix;
}
.footer-col {
float: left;
margin-bottom: $spacing-unit / 2;
padding-left: $spacing-unit / 2;
}
.footer-col-1 {
width: -webkit-calc(35% - (#{$spacing-unit} / 2));
width: calc(35% - (#{$spacing-unit} / 2));
}
.footer-col-2 {
width: -webkit-calc(20% - (#{$spacing-unit} / 2));
width: calc(20% - (#{$spacing-unit} / 2));
}
.footer-col-3 {
width: -webkit-calc(45% - (#{$spacing-unit} / 2));
width: calc(45% - (#{$spacing-unit} / 2));
}
@include media-query($on-laptop) {
.footer-col-1,
.footer-col-2 {
width: -webkit-calc(50% - (#{$spacing-unit} / 2));
width: calc(50% - (#{$spacing-unit} / 2));
}
.footer-col-3 {
width: -webkit-calc(100% - (#{$spacing-unit} / 2));
width: calc(100% - (#{$spacing-unit} / 2));
}
}
@include media-query($on-palm) {
.footer-col {
float: none;
width: -webkit-calc(100% - (#{$spacing-unit} / 2));
width: calc(100% - (#{$spacing-unit} / 2));
}
}
/**
* Page content
*/
.page-content {
padding: $spacing-unit 0;
}
.page-heading {
font-size: 20px;
}
.post-list {
margin-left: 0;
list-style: none;
> li {
margin-bottom: $spacing-unit;
}
}
.post-meta {
font-size: $small-font-size;
color: $grey-color;
}
.post-link {
display: block;
font-size: 24px;
}
/**
* Posts
*/
.post-header {
margin-bottom: $spacing-unit;
}
.post-title {
font-size: 42px;
letter-spacing: -1px;
line-height: 1;
@include media-query($on-laptop) {
font-size: 36px;
}
}
.post-content {
margin-bottom: $spacing-unit;
h2 {
font-size: 32px;
@include media-query($on-laptop) {
font-size: 28px;
}
}
h3 {
font-size: 26px;
@include media-query($on-laptop) {
font-size: 22px;
}
}
h4 {
font-size: 20px;
@include media-query($on-laptop) {
font-size: 18px;
}
}
}

View File

@ -1,71 +0,0 @@
/**
* Syntax highlighting styles
*/
.highlight {
background: #fff;
@extend %vertical-rhythm;
.highlighter-rouge & {
background: #eef;
}
.c { color: #998; font-style: italic } // Comment
.err { color: #a61717; background-color: #e3d2d2 } // Error
.k { font-weight: bold } // Keyword
.o { font-weight: bold } // Operator
.cm { color: #998; font-style: italic } // Comment.Multiline
.cp { color: #999; font-weight: bold } // Comment.Preproc
.c1 { color: #998; font-style: italic } // Comment.Single
.cs { color: #999; font-weight: bold; font-style: italic } // Comment.Special
.gd { color: #000; background-color: #fdd } // Generic.Deleted
.gd .x { color: #000; background-color: #faa } // Generic.Deleted.Specific
.ge { font-style: italic } // Generic.Emph
.gr { color: #a00 } // Generic.Error
.gh { color: #999 } // Generic.Heading
.gi { color: #000; background-color: #dfd } // Generic.Inserted
.gi .x { color: #000; background-color: #afa } // Generic.Inserted.Specific
.go { color: #888 } // Generic.Output
.gp { color: #555 } // Generic.Prompt
.gs { font-weight: bold } // Generic.Strong
.gu { color: #aaa } // Generic.Subheading
.gt { color: #a00 } // Generic.Traceback
.kc { font-weight: bold } // Keyword.Constant
.kd { font-weight: bold } // Keyword.Declaration
.kp { font-weight: bold } // Keyword.Pseudo
.kr { font-weight: bold } // Keyword.Reserved
.kt { color: #458; font-weight: bold } // Keyword.Type
.m { color: #099 } // Literal.Number
.s { color: #d14 } // Literal.String
.na { color: #008080 } // Name.Attribute
.nb { color: #0086B3 } // Name.Builtin
.nc { color: #458; font-weight: bold } // Name.Class
.no { color: #008080 } // Name.Constant
.ni { color: #800080 } // Name.Entity
.ne { color: #900; font-weight: bold } // Name.Exception
.nf { color: #900; font-weight: bold } // Name.Function
.nn { color: #555 } // Name.Namespace
.nt { color: #000080 } // Name.Tag
.nv { color: #008080 } // Name.Variable
.ow { font-weight: bold } // Operator.Word
.w { color: #bbb } // Text.Whitespace
.mf { color: #099 } // Literal.Number.Float
.mh { color: #099 } // Literal.Number.Hex
.mi { color: #099 } // Literal.Number.Integer
.mo { color: #099 } // Literal.Number.Oct
.sb { color: #d14 } // Literal.String.Backtick
.sc { color: #d14 } // Literal.String.Char
.sd { color: #d14 } // Literal.String.Doc
.s2 { color: #d14 } // Literal.String.Double
.se { color: #d14 } // Literal.String.Escape
.sh { color: #d14 } // Literal.String.Heredoc
.si { color: #d14 } // Literal.String.Interpol
.sx { color: #d14 } // Literal.String.Other
.sr { color: #009926 } // Literal.String.Regex
.s1 { color: #d14 } // Literal.String.Single
.ss { color: #990073 } // Literal.String.Symbol
.bp { color: #999 } // Name.Builtin.Pseudo
.vc { color: #008080 } // Name.Variable.Class
.vg { color: #008080 } // Name.Variable.Global
.vi { color: #008080 } // Name.Variable.Instance
.il { color: #099 } // Literal.Number.Integer.Long
}

View File

@ -3,8 +3,6 @@
---
@charset "utf-8";
// Our variables
$base-font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
$base-font-size: 16px;
@ -28,8 +26,7 @@ $content-width: 800px;
$on-palm: 600px;
$on-laptop: 800px;
// Minima also includes a mixin for defining media queries.
// Use media queries like this:
// @include media-query($on-palm) {
// .wrapper {
@ -37,17 +34,6 @@ $on-laptop: 800px;
// padding-left: $spacing-unit / 2;
// }
// }
@mixin media-query($device) {
@media screen and (max-width: $device) {
@content;
}
}
// Import partials from `sass_dir` (defaults to `_sass`)
@import
"base",
"layout",
"syntax-highlighting"
;
// Import partials from the `minima` theme.
@import "minima";

View File

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

View File

@ -0,0 +1,5 @@
---
layout: default
---
{{ content }}

View File

@ -0,0 +1,5 @@
---
layout: default
---
{{ content }}

View File

@ -1,6 +1,5 @@
---
# Specify a layout from your theme!
# This will be the layout users specify for their posts.
layout: post
---
Eos eu docendi tractatos sapientem, brute option menandri in vix, quando vivendo accommodare te ius. Nec melius fastidii constituam id, viderer theophrastus ad sit, hinc semper periculis cum id. Noluisse postulant assentior est in, no choro sadipscing repudiandae vix. Vis in euismod delenit dignissim. Ex quod nostrum sit, suas decore animal id ius, nobis solet detracto quo te.

View File

@ -1,11 +1,11 @@
---
# Specify a layout from your theme!
layout: page
---
Lorem ipsum dolor sit amet, quo id prima corrumpit pertinacia, id ius dolor dolores, an veri pertinax explicari mea. Agam solum et qui, his id ludus graeco adipiscing. Duis theophrastus nam in, at his vidisse atomorum. Tantas gloriatur scripserit ne eos. Est wisi tempor habemus at, ei graeco dissentiet eos. Ne usu aliquip sanctus conceptam, te vis ignota animal, modus latine contentiones ius te.
{% for post in site.posts %}
<h2>{{ post.title }}</h2>
<h2><a href="{{ post.url }}">{{ post.title }}</a></h2>
<blockquote>{{ post.excerpt }}</blockquote>
{% endfor %}

View File

@ -0,0 +1,4 @@
.bundle
.sass-cache
_site
Gemfile.lock

View File

@ -16,7 +16,7 @@ Gem::Specification.new do |spec|
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.add_development_dependency "jekyll", "~> <%= jekyll_pessimistic_version %>"
spec.add_development_dependency "jekyll", "~> <%= jekyll_version_with_minor %>"
spec.add_development_dependency "bundler", "~> 1.12"
spec.add_development_dependency "rake", "~> 10.0"
end

View File

@ -1,3 +1,3 @@
#!/bin/sh
bundle exec rubocop --version
bundle exec rubocop -D $@

View File

@ -904,6 +904,7 @@ LESS.js files during generation.
- [Hawkins](https://github.com/awood/hawkins): Adds a `liveserve` sub-command to Jekyll that incorporates [LiveReload](http://livereload.com/) into your pages while you preview them. No more hitting the refresh button in your browser!
- [Jekyll Autoprefixer](https://github.com/vwochnik/jekyll-autoprefixer): Autoprefixer integration for Jekyll
- [Jekyll-breadcrumbs](https://github.com/git-no/jekyll-breadcrumbs): Creates breadcrumbs for Jekyll 3.x, includes features like SEO optimization, optional breadcrumb item translation and more.
- [generator-jekyllized](https://github.com/sondr3/generator-jekyllized): A Yeoman generator for rapidly developing sites with Gulp. Live reload your site, automatically minify and optimize your assets and much more.
#### Editors

View File

@ -22,7 +22,7 @@ class TestFilters < JekyllUnitTest
"destination" => dest_dir,
"timezone" => "UTC"
})
@sample_time = Time.utc(2013, 03, 27, 11, 22, 33)
@sample_time = Time.utc(2013, 3, 27, 11, 22, 33)
@sample_date = Date.parse("2013-03-27")
@time_as_string = "September 11, 2001 12:46:30 -0000"
@time_as_numeric = 1_399_680_607

View File

@ -28,7 +28,7 @@ class TestKramdown < JekyllUnitTest
end
should "run Kramdown" do
assert_equal "<h1>Some Header</h1>", @markdown.convert('# Some Header #').strip
assert_equal "<h1>Some Header</h1>", @markdown.convert("# Some Header #").strip
end
context "when asked to convert smart quotes" do

View File

@ -39,7 +39,7 @@ class TestPage < JekyllUnitTest
end
should "create url with non-alphabetic characters" do
@page = setup_page("+", '%# +.md')
@page = setup_page("+", "%# +.md")
assert_equal "/+/%25%23%20+.html", @page.url
end
@ -268,12 +268,12 @@ class TestPage < JekyllUnitTest
end
should "write even when permalink has '%# +'" do
page = setup_page("+", '%# +.md')
page = setup_page("+", "%# +.md")
do_render(page)
page.write(dest_dir)
assert File.directory?(dest_dir)
assert_exist dest_dir("+", '%# +.html')
assert_exist dest_dir("+", "%# +.html")
end
should "write properly without html extension" do