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:
commit
b772329c60
|
@ -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) ***Debian/Ubuntu*** GNU/Linux
|
||||||
- [ ] I am on (or have tested on) ***Fedora*** GNU/Linux
|
- [ ] I am on (or have tested on) ***Fedora*** GNU/Linux
|
||||||
- [ ] I am on (or have tested on) ***Arch*** GNU/Linux
|
- [ ] I am on (or have tested on) ***Arch*** GNU/Linux
|
||||||
|
|
|
@ -4,16 +4,10 @@ AllCops:
|
||||||
Include:
|
Include:
|
||||||
- lib/**/*.rb
|
- lib/**/*.rb
|
||||||
Exclude:
|
Exclude:
|
||||||
- exe/jekyll
|
|
||||||
- lib/jekyll/collection.rb
|
- lib/jekyll/collection.rb
|
||||||
- lib/jekyll/command.rb
|
|
||||||
- lib/jekyll/configuration.rb
|
|
||||||
- lib/jekyll/convertible.rb
|
- lib/jekyll/convertible.rb
|
||||||
- lib/jekyll/document.rb
|
- lib/jekyll/document.rb
|
||||||
- lib/jekyll/regenerator.rb
|
|
||||||
- lib/jekyll/renderer.rb
|
- lib/jekyll/renderer.rb
|
||||||
- lib/jekyll/static_file.rb
|
|
||||||
- lib/jekyll/utils.rb
|
|
||||||
- bin/**/*
|
- bin/**/*
|
||||||
- benchmark/**/*
|
- benchmark/**/*
|
||||||
- script/**/*
|
- script/**/*
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
* Run Site#generate for 'jekyll doctor' to catch plugin issues (#5005)
|
* Run Site#generate for 'jekyll doctor' to catch plugin issues (#5005)
|
||||||
* Add normalize_whitepace filter (#4917)
|
* Add normalize_whitepace filter (#4917)
|
||||||
* Move bin/jekyll to exe/jekyll to prevent collision with binstubs (#5014)
|
* Move bin/jekyll to exe/jekyll to prevent collision with binstubs (#5014)
|
||||||
|
* Cleaning up site template & theme updates. (#4922)
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|
||||||
|
@ -95,6 +96,15 @@
|
||||||
* Rubocop: jekyll/lib/site.rb (#4973)
|
* Rubocop: jekyll/lib/site.rb (#4973)
|
||||||
* Add timings for each scenario in cucumber & print worst offenders (#4908)
|
* Add timings for each scenario in cucumber & print worst offenders (#4908)
|
||||||
* rubocop: jekyll/lib/filters.rb (#4993)
|
* 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
|
### Site Enhancements
|
||||||
|
|
||||||
|
@ -149,6 +159,7 @@
|
||||||
* Windows docs: Command needs to be called from blog path (#5006)
|
* Windows docs: Command needs to be called from blog path (#5006)
|
||||||
* Update text to be consitent with example (#5010)
|
* Update text to be consitent with example (#5010)
|
||||||
* Update template links to point to core Liquid site (#5012)
|
* Update template links to point to core Liquid site (#5012)
|
||||||
|
* Add generator-jekyllized to third-party plugins (#5027)
|
||||||
|
|
||||||
## 3.1.6 / 2016-05-19
|
## 3.1.6 / 2016-05-19
|
||||||
|
|
||||||
|
|
|
@ -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
|
30
exe/jekyll
30
exe/jekyll
|
@ -1,10 +1,10 @@
|
||||||
#!/usr/bin/env ruby
|
#!/usr/bin/env ruby
|
||||||
STDOUT.sync = true
|
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 "jekyll"
|
||||||
require 'mercenary'
|
require "mercenary"
|
||||||
|
|
||||||
Jekyll::PluginManager.require_from_bundler
|
Jekyll::PluginManager.require_from_bundler
|
||||||
|
|
||||||
|
@ -12,22 +12,26 @@ Jekyll::Deprecator.process(ARGV)
|
||||||
|
|
||||||
Mercenary.program(:jekyll) do |p|
|
Mercenary.program(:jekyll) do |p|
|
||||||
p.version Jekyll::VERSION
|
p.version Jekyll::VERSION
|
||||||
p.description 'Jekyll is a blog-aware, static site generator in Ruby'
|
p.description "Jekyll is a blog-aware, static site generator in Ruby"
|
||||||
p.syntax 'jekyll <subcommand> [options]'
|
p.syntax "jekyll <subcommand> [options]"
|
||||||
|
|
||||||
p.option 'source', '-s', '--source [DIR]', 'Source directory (defaults to ./)'
|
p.option "source", "-s", "--source [DIR]", "Source directory (defaults to ./)"
|
||||||
p.option 'destination', '-d', '--destination [DIR]', 'Destination directory (defaults to ./_site)'
|
p.option "destination", "-d", "--destination [DIR]",
|
||||||
p.option 'safe', '--safe', 'Safe mode (defaults to false)'
|
"Destination directory (defaults to ./_site)"
|
||||||
p.option 'plugins_dir', '-p', '--plugins PLUGINS_DIR1[,PLUGINS_DIR2[,...]]', Array, 'Plugins directory (defaults to ./_plugins)'
|
p.option "safe", "--safe", "Safe mode (defaults to false)"
|
||||||
p.option 'layouts_dir', '--layouts DIR', String, 'Layouts directory (defaults to ./_layouts)'
|
p.option "plugins_dir", "-p", "--plugins PLUGINS_DIR1[,PLUGINS_DIR2[,...]]", Array,
|
||||||
p.option 'profile', '--profile', 'Generate a Liquid rendering profile'
|
"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|
|
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|
|
p.command(cmd.to_sym) do |c|
|
||||||
c.syntax cmd
|
c.syntax cmd
|
||||||
c.action do
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -72,6 +72,9 @@ ruby RUBY_VERSION
|
||||||
# Happy Jekylling!
|
# Happy Jekylling!
|
||||||
gem "jekyll", "#{Jekyll::VERSION}"
|
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
|
# If you want to use GitHub Pages, remove the "gem "jekyll"" above and
|
||||||
# uncomment the line below. To upgrade, run `bundle update github-pages`.
|
# uncomment the line below. To upgrade, run `bundle update github-pages`.
|
||||||
# gem "github-pages", group: :jekyll_plugins
|
# gem "github-pages", group: :jekyll_plugins
|
||||||
|
|
|
@ -86,8 +86,8 @@ module Jekyll
|
||||||
# Returns a Configuration filled with defaults and fixed for common
|
# Returns a Configuration filled with defaults and fixed for common
|
||||||
# problems and backwards-compatibility.
|
# problems and backwards-compatibility.
|
||||||
def from(user_config)
|
def from(user_config)
|
||||||
Utils.deep_merge_hashes(DEFAULTS, Configuration[user_config].stringify_keys).
|
Utils.deep_merge_hashes(DEFAULTS, Configuration[user_config].stringify_keys)
|
||||||
fix_common_issues.add_default_collections
|
.fix_common_issues.add_default_collections
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -123,10 +123,10 @@ module Jekyll
|
||||||
|
|
||||||
def safe_load_file(filename)
|
def safe_load_file(filename)
|
||||||
case File.extname(filename)
|
case File.extname(filename)
|
||||||
when /\.toml/i
|
when %r!\.toml!i
|
||||||
Jekyll::External.require_with_graceful_fail("toml") unless defined?(TOML)
|
Jekyll::External.require_with_graceful_fail("toml") unless defined?(TOML)
|
||||||
TOML.load_file(filename)
|
TOML.load_file(filename)
|
||||||
when /\.ya?ml/i
|
when %r!\.ya?ml!i
|
||||||
SafeYAML.load_file(filename) || {}
|
SafeYAML.load_file(filename) || {}
|
||||||
else
|
else
|
||||||
raise ArgumentError, "No parser for '#{filename}' is available.
|
raise ArgumentError, "No parser for '#{filename}' is available.
|
||||||
|
@ -191,7 +191,7 @@ module Jekyll
|
||||||
|
|
||||||
begin
|
begin
|
||||||
files.each do |config_file|
|
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)
|
new_config = read_config_file(config_file)
|
||||||
configuration = Utils.deep_merge_hashes(configuration, new_config)
|
configuration = Utils.deep_merge_hashes(configuration, new_config)
|
||||||
end
|
end
|
||||||
|
@ -220,60 +220,18 @@ module Jekyll
|
||||||
def backwards_compatibilize
|
def backwards_compatibilize
|
||||||
config = clone
|
config = clone
|
||||||
# Provide backwards-compatibility
|
# Provide backwards-compatibility
|
||||||
if config.key?("auto") || config.key?("watch")
|
check_auto(config)
|
||||||
Jekyll::Deprecator.deprecation_message "Auto-regeneration can no longer" \
|
check_server(config)
|
||||||
" 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
|
|
||||||
|
|
||||||
renamed_key "server_port", "port", config
|
renamed_key "server_port", "port", config
|
||||||
renamed_key "plugins", "plugins_dir", config
|
renamed_key "plugins", "plugins_dir", config
|
||||||
renamed_key "layouts", "layouts_dir", config
|
renamed_key "layouts", "layouts_dir", config
|
||||||
renamed_key "data_source", "data_dir", config
|
renamed_key "data_source", "data_dir", config
|
||||||
|
|
||||||
if config.key?("pygments")
|
check_pygments(config)
|
||||||
Jekyll::Deprecator.deprecation_message "The 'pygments' configuration option" \
|
check_include_exclude(config)
|
||||||
" has been renamed to 'highlighter'. Please update your" \
|
check_coderay(config)
|
||||||
" config file accordingly. The allowed values are 'rouge', " \
|
check_maruku(config)
|
||||||
"'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
|
|
||||||
|
|
||||||
config
|
config
|
||||||
end
|
end
|
||||||
|
@ -296,19 +254,19 @@ module Jekyll
|
||||||
config = clone
|
config = clone
|
||||||
|
|
||||||
# It defaults to `{}`, so this is only if someone sets it to null manually.
|
# 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.
|
# Ensure we have a hash.
|
||||||
if config['collections'].is_a?(Array)
|
if config["collections"].is_a?(Array)
|
||||||
config['collections'] = Hash[config['collections'].map { |c| [c, {}] }]
|
config["collections"] = Hash[config["collections"].map { |c| [c, {}] }]
|
||||||
end
|
end
|
||||||
|
|
||||||
config['collections'] = Utils.deep_merge_hashes(
|
config["collections"] = Utils.deep_merge_hashes(
|
||||||
{ 'posts' => {} }, config['collections']
|
{ "posts" => {} }, config["collections"]
|
||||||
).tap do |collections|
|
).tap do |collections|
|
||||||
collections['posts']['output'] = true
|
collections["posts"]["output"] = true
|
||||||
if config['permalink']
|
if config["permalink"]
|
||||||
collections['posts']['permalink'] ||= style_to_permalink(config['permalink'])
|
collections["posts"]["permalink"] ||= style_to_permalink(config["permalink"])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -325,7 +283,6 @@ module Jekyll
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def style_to_permalink(permalink_style)
|
def style_to_permalink(permalink_style)
|
||||||
case permalink_style.to_sym
|
case permalink_style.to_sym
|
||||||
when :pretty
|
when :pretty
|
||||||
|
@ -347,9 +304,78 @@ module Jekyll
|
||||||
# file - the file from which the config was extracted
|
# file - the file from which the config was extracted
|
||||||
#
|
#
|
||||||
# Raises an ArgumentError if given config is not a hash
|
# Raises an ArgumentError if given config is not a hash
|
||||||
|
private
|
||||||
def check_config_is_hash!(extracted_config, file)
|
def check_config_is_hash!(extracted_config, file)
|
||||||
unless extracted_config.is_a?(Hash)
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# encoding: UTF-8
|
# encoding: UTF-8
|
||||||
|
|
||||||
require 'set'
|
require "set"
|
||||||
|
|
||||||
# Convertible provides methods for converting a pagelike item
|
# Convertible provides methods for converting a pagelike item
|
||||||
# from a certain type of markup into actual content
|
# from a certain type of markup into actual content
|
||||||
|
@ -20,12 +20,12 @@ module Jekyll
|
||||||
module Convertible
|
module Convertible
|
||||||
# Returns the contents as a String.
|
# Returns the contents as a String.
|
||||||
def to_s
|
def to_s
|
||||||
content || ''
|
content || ""
|
||||||
end
|
end
|
||||||
|
|
||||||
# Whether the file is published or not, as indicated in YAML front-matter
|
# Whether the file is published or not, as indicated in YAML front-matter
|
||||||
def published?
|
def published?
|
||||||
!(data.key?('published') && data['published'] == false)
|
!(data.key?("published") && data["published"] == false)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Read the YAML frontmatter.
|
# Read the YAML frontmatter.
|
||||||
|
@ -47,7 +47,7 @@ module Jekyll
|
||||||
end
|
end
|
||||||
rescue SyntaxError => e
|
rescue SyntaxError => e
|
||||||
Jekyll.logger.warn "YAML Exception reading #{filename}: #{e.message}"
|
Jekyll.logger.warn "YAML Exception reading #{filename}: #{e.message}"
|
||||||
rescue Exception => e
|
rescue => e
|
||||||
Jekyll.logger.warn "Error reading file #{filename}: #{e.message}"
|
Jekyll.logger.warn "Error reading file #{filename}: #{e.message}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -61,12 +61,13 @@ module Jekyll
|
||||||
|
|
||||||
def validate_data!(filename)
|
def validate_data!(filename)
|
||||||
unless self.data.is_a?(Hash)
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_permalink!(filename)
|
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}"
|
raise Errors::InvalidPermalinkError, "Invalid permalink in #{filename}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -79,7 +80,10 @@ module Jekyll
|
||||||
begin
|
begin
|
||||||
converter.convert output
|
converter.convert output
|
||||||
rescue => e
|
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)
|
Jekyll.logger.error("", e.to_s)
|
||||||
raise e
|
raise e
|
||||||
end
|
end
|
||||||
|
@ -112,12 +116,17 @@ module Jekyll
|
||||||
def render_liquid(content, payload, info, path)
|
def render_liquid(content, payload, info, path)
|
||||||
site.liquid_renderer.file(path).parse(content).render!(payload, info)
|
site.liquid_renderer.file(path).parse(content).render!(payload, info)
|
||||||
rescue Tags::IncludeTagError => e
|
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
|
raise e
|
||||||
|
# rubocop: disable RescueException
|
||||||
rescue Exception => e
|
rescue Exception => e
|
||||||
Jekyll.logger.error "Liquid Exception:", "#{e.message} in #{path || self.path}"
|
Jekyll.logger.error "Liquid Exception:", "#{e.message} in #{path || self.path}"
|
||||||
raise e
|
raise e
|
||||||
end
|
end
|
||||||
|
# rubocop: enable RescueException
|
||||||
|
|
||||||
# Convert this Convertible's data to a Hash suitable for use by Liquid.
|
# 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.
|
# Returns true if extname == .coffee, false otherwise.
|
||||||
def coffeescript_file?
|
def coffeescript_file?
|
||||||
'.coffee'.eql?(ext)
|
".coffee" == ext
|
||||||
end
|
end
|
||||||
|
|
||||||
# Determine whether the file should be rendered with Liquid.
|
# Determine whether the file should be rendered with Liquid.
|
||||||
|
@ -205,7 +214,10 @@ module Jekyll
|
||||||
# recursively render layouts
|
# recursively render layouts
|
||||||
layout = layouts[data["layout"]]
|
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])
|
used = Set.new([layout])
|
||||||
|
|
||||||
|
@ -228,12 +240,9 @@ module Jekyll
|
||||||
site.in_source_dir(layout.path)
|
site.in_source_dir(layout.path)
|
||||||
)
|
)
|
||||||
|
|
||||||
if layout = layouts[layout.data["layout"]]
|
if (layout = layouts[layout.data["layout"]])
|
||||||
if used.include?(layout)
|
break if used.include?(layout)
|
||||||
layout = nil # avoid recursive chain
|
used << layout
|
||||||
else
|
|
||||||
used << layout
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -249,7 +258,10 @@ module Jekyll
|
||||||
|
|
||||||
Jekyll.logger.debug "Pre-Render Hooks:", self.relative_path
|
Jekyll.logger.debug "Pre-Render Hooks:", self.relative_path
|
||||||
Jekyll::Hooks.trigger hook_owner, :pre_render, self, payload
|
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)
|
# render and transform content (this becomes the final content of the object)
|
||||||
payload["highlighter_prefix"] = converters.first.highlighter_prefix
|
payload["highlighter_prefix"] = converters.first.highlighter_prefix
|
||||||
|
@ -278,9 +290,7 @@ module Jekyll
|
||||||
def write(dest)
|
def write(dest)
|
||||||
path = destination(dest)
|
path = destination(dest)
|
||||||
FileUtils.mkdir_p(File.dirname(path))
|
FileUtils.mkdir_p(File.dirname(path))
|
||||||
File.open(path, 'wb') do |f|
|
File.write(path, output, :mode => "wb")
|
||||||
f.write(output)
|
|
||||||
end
|
|
||||||
Jekyll::Hooks.trigger hook_owner, :post_write, self
|
Jekyll::Hooks.trigger hook_owner, :post_write, self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,9 @@ module Jekyll
|
||||||
attr_reader :path, :site, :extname, :collection
|
attr_reader :path, :site, :extname, :collection
|
||||||
attr_accessor :content, :output
|
attr_accessor :content, :output
|
||||||
|
|
||||||
YAML_FRONT_MATTER_REGEXP = /\A(---\s*\n.*?\n?)^((---|\.\.\.)\s*$\n?)/m
|
YAML_FRONT_MATTER_REGEXP = %r!\A(---\s*\n.*?\n?)^((---|\.\.\.)\s*$\n?)!m
|
||||||
DATELESS_FILENAME_MATCHER = /^(.+\/)*(.*)(\.[^.]+)$/
|
DATELESS_FILENAME_MATCHER = %r!^(?:.+/)*(.*)(\.[^.]+)$!
|
||||||
DATE_FILENAME_MATCHER = /^(.+\/)*(\d+-\d+-\d+)-(.*)(\.[^.]+)$/
|
DATE_FILENAME_MATCHER = %r!^(?:.+/)*(\d+-\d+-\d+)-(.*)(\.[^.]+)$!
|
||||||
|
|
||||||
# Create a new Document.
|
# Create a new Document.
|
||||||
#
|
#
|
||||||
|
@ -51,16 +51,16 @@ module Jekyll
|
||||||
#
|
#
|
||||||
# Returns the merged data.
|
# Returns the merged data.
|
||||||
def merge_data!(other, source: "YAML front matter")
|
def merge_data!(other, source: "YAML front matter")
|
||||||
if other.key?('categories') && !other['categories'].nil?
|
if other.key?("categories") && !other["categories"].nil?
|
||||||
if other['categories'].is_a?(String)
|
if other["categories"].is_a?(String)
|
||||||
other['categories'] = other['categories'].split(" ").map(&:strip)
|
other["categories"] = other["categories"].split(" ").map(&:strip)
|
||||||
end
|
end
|
||||||
other['categories'] = (data['categories'] || []) | other['categories']
|
other["categories"] = (data["categories"] || []) | other["categories"]
|
||||||
end
|
end
|
||||||
Utils.deep_merge_hashes!(data, other)
|
Utils.deep_merge_hashes!(data, other)
|
||||||
if data.key?('date') && !data['date'].is_a?(Time)
|
if data.key?("date") && !data["date"].is_a?(Time)
|
||||||
data['date'] = Utils.parse_date(
|
data["date"] = Utils.parse_date(
|
||||||
data['date'].to_s,
|
data["date"].to_s,
|
||||||
"Document '#{relative_path}' does not have a valid date in the #{source}."
|
"Document '#{relative_path}' does not have a valid date in the #{source}."
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
@ -68,7 +68,7 @@ module Jekyll
|
||||||
end
|
end
|
||||||
|
|
||||||
def date
|
def date
|
||||||
data['date'] ||= (draft? ? source_file_mtime : site.time)
|
data["date"] ||= (draft? ? source_file_mtime : site.time)
|
||||||
end
|
end
|
||||||
|
|
||||||
def source_file_mtime
|
def source_file_mtime
|
||||||
|
@ -81,7 +81,8 @@ module Jekyll
|
||||||
#
|
#
|
||||||
# Returns whether the document is a draft.
|
# Returns whether the document is a draft.
|
||||||
def 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
|
end
|
||||||
|
|
||||||
# The path to the document, relative to the site source.
|
# 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
|
# Returns a String path which represents the relative path
|
||||||
# from the site source to this document
|
# from the site source to this document
|
||||||
def relative_path
|
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
|
end
|
||||||
|
|
||||||
# The output extension of the document.
|
# The output extension of the document.
|
||||||
|
@ -103,7 +105,7 @@ module Jekyll
|
||||||
#
|
#
|
||||||
# Returns the basename without the file extname.
|
# Returns the basename without the file extname.
|
||||||
def basename_without_ext
|
def basename_without_ext
|
||||||
@basename_without_ext ||= File.basename(path, '.*')
|
@basename_without_ext ||= File.basename(path, ".*")
|
||||||
end
|
end
|
||||||
|
|
||||||
# The base filename of the document.
|
# The base filename of the document.
|
||||||
|
@ -156,7 +158,7 @@ module Jekyll
|
||||||
#
|
#
|
||||||
# Returns true if extname == .coffee, false otherwise.
|
# Returns true if extname == .coffee, false otherwise.
|
||||||
def coffeescript_file?
|
def coffeescript_file?
|
||||||
'.coffee'.eql?(extname)
|
".coffee" == extname
|
||||||
end
|
end
|
||||||
|
|
||||||
# Determine whether the file should be rendered with Liquid.
|
# 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.
|
# Returns the permalink or nil if no permalink was set in the data.
|
||||||
def permalink
|
def permalink
|
||||||
data && data.is_a?(Hash) && data['permalink']
|
data && data.is_a?(Hash) && data["permalink"]
|
||||||
end
|
end
|
||||||
|
|
||||||
# The computed URL for the document. See `Jekyll::URL#to_s` for more details.
|
# 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.
|
# Returns the computed URL for the document.
|
||||||
def url
|
def url
|
||||||
@url = URL.new({
|
@url = URL.new({
|
||||||
:template => url_template,
|
:template => url_template,
|
||||||
:placeholders => url_placeholders,
|
:placeholders => url_placeholders,
|
||||||
:permalink => permalink
|
:permalink => permalink
|
||||||
}).to_s
|
}).to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -237,18 +239,17 @@ module Jekyll
|
||||||
def write(dest)
|
def write(dest)
|
||||||
path = destination(dest)
|
path = destination(dest)
|
||||||
FileUtils.mkdir_p(File.dirname(path))
|
FileUtils.mkdir_p(File.dirname(path))
|
||||||
File.open(path, 'wb') do |f|
|
File.write(path, output, :mode => "wb")
|
||||||
f.write(output)
|
|
||||||
end
|
|
||||||
|
|
||||||
trigger_hooks(:post_write)
|
trigger_hooks(:post_write)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Whether the file is published or not, as indicated in YAML front-matter
|
# 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?
|
def published?
|
||||||
!(data.key?('published') && data['published'] == false)
|
!(data.key?("published") && data["published"] == false)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Read in the file and assign the content and data based on the file contents.
|
# 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)
|
@data = SafeYAML.load_file(path)
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
defaults = @site.frontmatter_defaults.all(relative_path, collection.label.to_sym)
|
defaults = @site.frontmatter_defaults.all(
|
||||||
merge_data!(defaults, source: "front matter defaults") unless defaults.empty?
|
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))
|
self.content = File.read(path, Utils.merged_file_read_opts(site, opts))
|
||||||
if content =~ YAML_FRONT_MATTER_REGEXP
|
if content =~ YAML_FRONT_MATTER_REGEXP
|
||||||
self.content = $POSTMATCH
|
self.content = $POSTMATCH
|
||||||
data_file = SafeYAML.load(Regexp.last_match(1))
|
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
|
end
|
||||||
|
|
||||||
post_read
|
post_read
|
||||||
rescue SyntaxError => e
|
rescue SyntaxError => e
|
||||||
Jekyll.logger.error "Error:", "YAML Exception reading #{path}: #{e.message}"
|
Jekyll.logger.error "Error:", "YAML Exception reading #{path}: #{e.message}"
|
||||||
rescue Exception => e
|
rescue => e
|
||||||
if e.is_a? Jekyll::Errors::FatalException
|
raise e if e.is_a? Jekyll::Errors::FatalException
|
||||||
raise e
|
|
||||||
end
|
|
||||||
Jekyll.logger.error "Error:", "could not read file #{path}: #{e.message}"
|
Jekyll.logger.error "Error:", "could not read file #{path}: #{e.message}"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -287,19 +289,19 @@ module Jekyll
|
||||||
|
|
||||||
def post_read
|
def post_read
|
||||||
if relative_path =~ DATE_FILENAME_MATCHER
|
if relative_path =~ DATE_FILENAME_MATCHER
|
||||||
date, slug, ext = $2, $3, $4
|
date, slug, ext = Regexp.last_match.captures
|
||||||
if !data['date'] || data['date'].to_i == site.time.to_i
|
if !data["date"] || data["date"].to_i == site.time.to_i
|
||||||
merge_data!({"date" => date}, source: "filename")
|
merge_data!({ "date" => date }, :source => "filename")
|
||||||
end
|
end
|
||||||
elsif relative_path =~ DATELESS_FILENAME_MATCHER
|
elsif relative_path =~ DATELESS_FILENAME_MATCHER
|
||||||
slug, ext = $2, $3
|
slug, ext = Regexp.last_match.captures
|
||||||
end
|
end
|
||||||
|
|
||||||
# Try to ensure the user gets a title.
|
# Try to ensure the user gets a title.
|
||||||
data["title"] ||= Utils.titleize_slug(slug)
|
data["title"] ||= Utils.titleize_slug(slug)
|
||||||
# Only overwrite slug & ext if they aren't specified.
|
# Only overwrite slug & ext if they aren't specified.
|
||||||
data['slug'] ||= slug
|
data["slug"] ||= slug
|
||||||
data['ext'] ||= ext
|
data["ext"] ||= ext
|
||||||
|
|
||||||
populate_categories
|
populate_categories
|
||||||
populate_tags
|
populate_tags
|
||||||
|
@ -312,16 +314,19 @@ module Jekyll
|
||||||
#
|
#
|
||||||
# Returns nothing.
|
# Returns nothing.
|
||||||
def categories_from_path(special_dir)
|
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)
|
c.empty? || c.eql?(special_dir) || c.eql?(basename)
|
||||||
end
|
end
|
||||||
merge_data!({ 'categories' => superdirs }, source: "file path")
|
merge_data!({ "categories" => superdirs }, :source => "file path")
|
||||||
end
|
end
|
||||||
|
|
||||||
def populate_categories
|
def populate_categories
|
||||||
merge_data!({
|
merge_data!({
|
||||||
'categories' => (
|
"categories" => (
|
||||||
Array(data['categories']) + Utils.pluralized_array_from_hash(data, 'category', 'categories')
|
Array(data["categories"]) +
|
||||||
|
Utils.pluralized_array_from_hash(data, "category", "categories")
|
||||||
).map(&:to_s).flatten.uniq
|
).map(&:to_s).flatten.uniq
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
@ -351,7 +356,7 @@ module Jekyll
|
||||||
#
|
#
|
||||||
# Returns the content of the document
|
# Returns the content of the document
|
||||||
def to_s
|
def to_s
|
||||||
output || content || 'NO CONTENT'
|
output || content || "NO CONTENT"
|
||||||
end
|
end
|
||||||
|
|
||||||
# Compare this document against another document.
|
# 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.
|
# equal or greater than the other doc's path. See String#<=> for more details.
|
||||||
def <=>(other)
|
def <=>(other)
|
||||||
return nil unless other.respond_to?(:data)
|
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 = path <=> other.path if cmp.nil? || cmp == 0
|
||||||
cmp
|
cmp
|
||||||
end
|
end
|
||||||
|
@ -380,7 +385,7 @@ module Jekyll
|
||||||
#
|
#
|
||||||
# Returns the document excerpt_separator
|
# Returns the document excerpt_separator
|
||||||
def excerpt_separator
|
def excerpt_separator
|
||||||
(data['excerpt_separator'] || site.config['excerpt_separator']).to_s
|
(data["excerpt_separator"] || site.config["excerpt_separator"]).to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
# Whether to generate an excerpt
|
# Whether to generate an excerpt
|
||||||
|
@ -394,8 +399,6 @@ module Jekyll
|
||||||
pos = collection.docs.index { |post| post.equal?(self) }
|
pos = collection.docs.index { |post| post.equal?(self) }
|
||||||
if pos && pos < collection.docs.length - 1
|
if pos && pos < collection.docs.length - 1
|
||||||
collection.docs[pos + 1]
|
collection.docs[pos + 1]
|
||||||
else
|
|
||||||
nil
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -403,8 +406,6 @@ module Jekyll
|
||||||
pos = collection.docs.index { |post| post.equal?(self) }
|
pos = collection.docs.index { |post| post.equal?(self) }
|
||||||
if pos && pos > 0
|
if pos && pos > 0
|
||||||
collection.docs[pos - 1]
|
collection.docs[pos - 1]
|
||||||
else
|
|
||||||
nil
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -414,7 +415,7 @@ module Jekyll
|
||||||
end
|
end
|
||||||
|
|
||||||
def id
|
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
|
end
|
||||||
|
|
||||||
# Calculate related posts.
|
# Calculate related posts.
|
||||||
|
@ -433,8 +434,9 @@ module Jekyll
|
||||||
# Override of method_missing to check in @data for the key.
|
# Override of method_missing to check in @data for the key.
|
||||||
def method_missing(method, *args, &blck)
|
def method_missing(method, *args, &blck)
|
||||||
if data.key?(method.to_s)
|
if data.key?(method.to_s)
|
||||||
Jekyll.logger.warn "Deprecation:", "Document##{method} is now a key in the #data hash."
|
Jekyll::Deprecator.deprecation_message "Document##{method} is now a key "\
|
||||||
Jekyll.logger.warn "", "Called by #{caller.first}."
|
"in the #data hash."
|
||||||
|
Jekyll::Deprecator.deprecation_message "Called by #{caller.first}."
|
||||||
data[method.to_s]
|
data[method.to_s]
|
||||||
else
|
else
|
||||||
super
|
super
|
||||||
|
|
|
@ -2,7 +2,7 @@ module Jekyll
|
||||||
class EntryFilter
|
class EntryFilter
|
||||||
attr_reader :site
|
attr_reader :site
|
||||||
SPECIAL_LEADING_CHARACTERS = [
|
SPECIAL_LEADING_CHARACTERS = [
|
||||||
".", "_", '#', "~"
|
".", "_", "#", "~"
|
||||||
].freeze
|
].freeze
|
||||||
|
|
||||||
def initialize(site, base_directory = nil)
|
def initialize(site, base_directory = nil)
|
||||||
|
|
|
@ -20,18 +20,14 @@ module Jekyll
|
||||||
def regenerate?(document)
|
def regenerate?(document)
|
||||||
case document
|
case document
|
||||||
when Page
|
when Page
|
||||||
document.asset_file? || document.data['regenerate'] ||
|
regenerate_page?(document)
|
||||||
source_modified_or_dest_missing?(
|
|
||||||
site.in_source_dir(document.relative_path), document.destination(@site.dest)
|
|
||||||
)
|
|
||||||
when Document
|
when Document
|
||||||
!document.write? || document.data['regenerate'] ||
|
regenerate_document?(document)
|
||||||
source_modified_or_dest_missing?(
|
|
||||||
document.path, document.destination(@site.dest)
|
|
||||||
)
|
|
||||||
else
|
else
|
||||||
source_path = document.respond_to?(:path) ? document.path : nil
|
source_path = document.respond_to?(:path) ? document.path : nil
|
||||||
dest_path = document.respond_to?(:destination) ? document.destination(@site.dest) : nil
|
dest_path = if document.respond_to?(:destination)
|
||||||
|
document.destination(@site.dest)
|
||||||
|
end
|
||||||
source_modified_or_dest_missing?(source_path, dest_path)
|
source_modified_or_dest_missing?(source_path, dest_path)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -44,7 +40,7 @@ module Jekyll
|
||||||
|
|
||||||
metadata[path] = {
|
metadata[path] = {
|
||||||
"mtime" => File.mtime(path),
|
"mtime" => File.mtime(path),
|
||||||
"deps" => []
|
"deps" => []
|
||||||
}
|
}
|
||||||
cache[path] = true
|
cache[path] = true
|
||||||
end
|
end
|
||||||
|
@ -94,23 +90,14 @@ module Jekyll
|
||||||
return cache[path]
|
return cache[path]
|
||||||
end
|
end
|
||||||
|
|
||||||
# Check path that exists in metadata
|
if metadata[path]
|
||||||
data = metadata[path]
|
# If we have seen this file before,
|
||||||
if data
|
# check if it or one of its dependencies has been modified
|
||||||
data["deps"].each do |dependency|
|
existing_file_modified?(path)
|
||||||
if modified?(dependency)
|
else
|
||||||
return cache[dependency] = cache[path] = true
|
# If we have not seen this file before, add it to the metadata and regenerate it
|
||||||
end
|
add(path)
|
||||||
end
|
|
||||||
if File.exist?(path) && data["mtime"].eql?(File.mtime(path))
|
|
||||||
return cache[path] = false
|
|
||||||
else
|
|
||||||
return add(path)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Path does not exist in metadata, add it
|
|
||||||
return add(path)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Add a dependency of a path
|
# Add a dependency of a path
|
||||||
|
@ -139,7 +126,7 @@ module Jekyll
|
||||||
#
|
#
|
||||||
# Returns the String path of the file.
|
# Returns the String path of the file.
|
||||||
def metadata_file
|
def metadata_file
|
||||||
site.in_source_dir('.jekyll-metadata')
|
site.in_source_dir(".jekyll-metadata")
|
||||||
end
|
end
|
||||||
|
|
||||||
# Check if metadata has been disabled
|
# Check if metadata has been disabled
|
||||||
|
@ -173,5 +160,40 @@ module Jekyll
|
||||||
{}
|
{}
|
||||||
end
|
end
|
||||||
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
|
||||||
end
|
end
|
||||||
|
|
|
@ -38,21 +38,21 @@ module Jekyll
|
||||||
payload["paginator"] = document.pager.to_liquid
|
payload["paginator"] = document.pager.to_liquid
|
||||||
end
|
end
|
||||||
|
|
||||||
if document.is_a?(Document) && document.collection.label == 'posts'
|
if document.is_a?(Document) && document.collection.label == "posts"
|
||||||
payload['site']['related_posts'] = document.related_posts
|
payload["site"]["related_posts"] = document.related_posts
|
||||||
else
|
else
|
||||||
payload['site']['related_posts'] = nil
|
payload["site"]["related_posts"] = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
# render and transform content (this becomes the final content of the object)
|
# render and transform content (this becomes the final content of the object)
|
||||||
payload['highlighter_prefix'] = converters.first.highlighter_prefix
|
payload["highlighter_prefix"] = converters.first.highlighter_prefix
|
||||||
payload['highlighter_suffix'] = converters.first.highlighter_suffix
|
payload["highlighter_suffix"] = converters.first.highlighter_suffix
|
||||||
|
|
||||||
Jekyll.logger.debug "Pre-Render Hooks:", document.relative_path
|
Jekyll.logger.debug "Pre-Render Hooks:", document.relative_path
|
||||||
document.trigger_hooks(:pre_render, payload)
|
document.trigger_hooks(:pre_render, payload)
|
||||||
|
|
||||||
info = {
|
info = {
|
||||||
:registers => { :site => site, :page => payload['page'] }
|
:registers => { :site => site, :page => payload["page"] }
|
||||||
}
|
}
|
||||||
|
|
||||||
output = document.content
|
output = document.content
|
||||||
|
@ -88,7 +88,9 @@ module Jekyll
|
||||||
begin
|
begin
|
||||||
converter.convert output
|
converter.convert output
|
||||||
rescue => e
|
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)
|
Jekyll.logger.error("", e.to_s)
|
||||||
raise e
|
raise e
|
||||||
end
|
end
|
||||||
|
@ -106,12 +108,16 @@ module Jekyll
|
||||||
def render_liquid(content, payload, info, path = nil)
|
def render_liquid(content, payload, info, path = nil)
|
||||||
site.liquid_renderer.file(path).parse(content).render!(payload, info)
|
site.liquid_renderer.file(path).parse(content).render!(payload, info)
|
||||||
rescue Tags::IncludeTagError => e
|
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
|
raise e
|
||||||
|
# rubocop: disable RescueException
|
||||||
rescue Exception => e
|
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
|
raise e
|
||||||
end
|
end
|
||||||
|
# rubocop: enable RescueException
|
||||||
|
|
||||||
# Checks if the layout specified in the document actually exists
|
# Checks if the layout specified in the document actually exists
|
||||||
#
|
#
|
||||||
|
@ -132,16 +138,20 @@ module Jekyll
|
||||||
output = content.dup
|
output = content.dup
|
||||||
layout = site.layouts[document.data["layout"]]
|
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.
|
# Reset the payload layout data to ensure it starts fresh for each page.
|
||||||
payload["layout"] = nil
|
payload["layout"] = nil
|
||||||
|
|
||||||
while layout
|
while layout
|
||||||
payload['content'] = output
|
payload["content"] = output
|
||||||
payload['layout'] = Utils.deep_merge_hashes(layout.data, payload["layout"] || {})
|
payload["layout"] = Utils.deep_merge_hashes(layout.data, payload["layout"] || {})
|
||||||
|
|
||||||
output = render_liquid(
|
output = render_liquid(
|
||||||
layout.content,
|
layout.content,
|
||||||
|
@ -156,12 +166,9 @@ module Jekyll
|
||||||
site.in_source_dir(layout.path)
|
site.in_source_dir(layout.path)
|
||||||
) if document.write?
|
) if document.write?
|
||||||
|
|
||||||
if layout = site.layouts[layout.data["layout"]]
|
if (layout = site.layouts[layout.data["layout"]])
|
||||||
if used.include?(layout)
|
break if used.include?(layout)
|
||||||
layout = nil # avoid recursive chain
|
used << layout
|
||||||
else
|
|
||||||
used << layout
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,25 @@
|
||||||
module Jekyll
|
module Jekyll
|
||||||
class StaticFile
|
class StaticFile
|
||||||
# The cache of last modification times [path] -> mtime.
|
|
||||||
@@mtimes = {}
|
|
||||||
|
|
||||||
attr_reader :relative_path, :extname
|
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.
|
# Initialize a new StaticFile.
|
||||||
#
|
#
|
||||||
# site - The Site.
|
# site - The Site.
|
||||||
# base - The String path to the <source>.
|
# base - The String path to the <source>.
|
||||||
# dir - The String path between <source> and the file.
|
# dir - The String path between <source> and the file.
|
||||||
# name - The String filename of the file.
|
# name - The String filename of the file.
|
||||||
|
# rubocop: disable ParameterLists
|
||||||
def initialize(site, base, dir, name, collection = nil)
|
def initialize(site, base, dir, name, collection = nil)
|
||||||
@site = site
|
@site = site
|
||||||
@base = base
|
@base = base
|
||||||
|
@ -20,6 +29,7 @@ module Jekyll
|
||||||
@relative_path = File.join(*[@dir, @name].compact)
|
@relative_path = File.join(*[@dir, @name].compact)
|
||||||
@extname = File.extname(@name)
|
@extname = File.extname(@name)
|
||||||
end
|
end
|
||||||
|
# rubocop: enable ParameterLists
|
||||||
|
|
||||||
# Returns source file path.
|
# Returns source file path.
|
||||||
def path
|
def path
|
||||||
|
@ -56,7 +66,7 @@ module Jekyll
|
||||||
#
|
#
|
||||||
# Returns true if modified since last write.
|
# Returns true if modified since last write.
|
||||||
def modified?
|
def modified?
|
||||||
@@mtimes[path] != mtime
|
self.class.mtimes[path] != mtime
|
||||||
end
|
end
|
||||||
|
|
||||||
# Whether to write the file to the filesystem
|
# Whether to write the file to the filesystem
|
||||||
|
@ -64,7 +74,7 @@ module Jekyll
|
||||||
# Returns true unless the defaults for the destination path from
|
# Returns true unless the defaults for the destination path from
|
||||||
# _config.yml contain `published: false`.
|
# _config.yml contain `published: false`.
|
||||||
def write?
|
def write?
|
||||||
defaults.fetch('published', true)
|
defaults.fetch("published", true)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Write the static file to the destination directory (if modified).
|
# Write the static file to the destination directory (if modified).
|
||||||
|
@ -76,28 +86,15 @@ module Jekyll
|
||||||
dest_path = destination(dest)
|
dest_path = destination(dest)
|
||||||
|
|
||||||
return false if File.exist?(dest_path) && !modified?
|
return false if File.exist?(dest_path) && !modified?
|
||||||
@@mtimes[path] = mtime
|
self.class.mtimes[path] = mtime
|
||||||
|
|
||||||
FileUtils.mkdir_p(File.dirname(dest_path))
|
FileUtils.mkdir_p(File.dirname(dest_path))
|
||||||
FileUtils.rm(dest_path) if File.exist?(dest_path)
|
FileUtils.rm(dest_path) if File.exist?(dest_path)
|
||||||
if @site.safe || Jekyll.env == "production"
|
copy_file(dest_path)
|
||||||
FileUtils.cp(path, dest_path)
|
|
||||||
else
|
|
||||||
FileUtils.copy_entry(path, dest_path)
|
|
||||||
end
|
|
||||||
File.utime(@@mtimes[path], @@mtimes[path], dest_path)
|
|
||||||
|
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
# Reset the mtimes cache (for testing purposes).
|
|
||||||
#
|
|
||||||
# Returns nothing.
|
|
||||||
def self.reset_cache
|
|
||||||
@@mtimes = {}
|
|
||||||
nil
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_liquid
|
def to_liquid
|
||||||
{
|
{
|
||||||
"extname" => extname,
|
"extname" => extname,
|
||||||
|
@ -109,11 +106,11 @@ module Jekyll
|
||||||
def placeholders
|
def placeholders
|
||||||
{
|
{
|
||||||
:collection => @collection.label,
|
:collection => @collection.label,
|
||||||
:path => relative_path[
|
:path => relative_path[
|
||||||
@collection.relative_directory.size..relative_path.size],
|
@collection.relative_directory.size..relative_path.size],
|
||||||
:output_ext => '',
|
:output_ext => "",
|
||||||
:name => '',
|
:name => "",
|
||||||
:title => ''
|
:title => ""
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -125,10 +122,10 @@ module Jekyll
|
||||||
relative_path
|
relative_path
|
||||||
else
|
else
|
||||||
::Jekyll::URL.new({
|
::Jekyll::URL.new({
|
||||||
:template => @collection.url_template,
|
:template => @collection.url_template,
|
||||||
:placeholders => placeholders
|
:placeholders => placeholders
|
||||||
})
|
})
|
||||||
end.to_s.gsub(/\/$/, '')
|
end.to_s.gsub(%r!/$!, "")
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns the type of the collection if present, nil otherwise.
|
# Returns the type of the collection if present, nil otherwise.
|
||||||
|
@ -141,5 +138,15 @@ module Jekyll
|
||||||
def defaults
|
def defaults
|
||||||
@defaults ||= @site.frontmatter_defaults.all url, type
|
@defaults ||= @site.frontmatter_defaults.all url, type
|
||||||
end
|
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
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
class Jekyll::ThemeBuilder
|
class Jekyll::ThemeBuilder
|
||||||
SCAFFOLD_DIRECTORIES = %w(
|
SCAFFOLD_DIRECTORIES = %w(
|
||||||
_layouts _includes _sass example example/_posts
|
_layouts _includes _sass
|
||||||
).freeze
|
).freeze
|
||||||
|
|
||||||
attr_reader :name, :path
|
attr_reader :name, :path
|
||||||
|
@ -12,6 +12,7 @@ class Jekyll::ThemeBuilder
|
||||||
|
|
||||||
def create!
|
def create!
|
||||||
create_directories
|
create_directories
|
||||||
|
create_starter_files
|
||||||
create_gemspec
|
create_gemspec
|
||||||
create_accessories
|
create_accessories
|
||||||
create_example_site
|
create_example_site
|
||||||
|
@ -55,6 +56,13 @@ class Jekyll::ThemeBuilder
|
||||||
|
|
||||||
def create_directories
|
def create_directories
|
||||||
mkdir_p(SCAFFOLD_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
|
end
|
||||||
|
|
||||||
def create_gemspec
|
def create_gemspec
|
||||||
|
@ -81,6 +89,7 @@ class Jekyll::ThemeBuilder
|
||||||
def initialize_git_repo
|
def initialize_git_repo
|
||||||
Jekyll.logger.info "initialize", path.join(".git").to_s
|
Jekyll.logger.info "initialize", path.join(".git").to_s
|
||||||
Dir.chdir(path.to_s) { `git init` }
|
Dir.chdir(path.to_s) { `git init` }
|
||||||
|
write_file(".gitignore", template("gitignore"))
|
||||||
end
|
end
|
||||||
|
|
||||||
def user_name
|
def user_name
|
||||||
|
@ -102,7 +111,7 @@ class Jekyll::ThemeBuilder
|
||||||
@theme_builder = theme_builder
|
@theme_builder = theme_builder
|
||||||
end
|
end
|
||||||
|
|
||||||
def jekyll_pessimistic_version
|
def jekyll_version_with_minor
|
||||||
Jekyll::VERSION.split(".").take(2).join(".")
|
Jekyll::VERSION.split(".").take(2).join(".")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -2,27 +2,25 @@
|
||||||
module Jekyll
|
module Jekyll
|
||||||
module Utils
|
module Utils
|
||||||
extend self
|
extend self
|
||||||
autoload :Platforms, 'jekyll/utils/platforms'
|
autoload :Platforms, "jekyll/utils/platforms"
|
||||||
autoload :Ansi, "jekyll/utils/ansi"
|
autoload :Ansi, "jekyll/utils/ansi"
|
||||||
|
|
||||||
# Constants for use in #slugify
|
# 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_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
|
SLUGIFY_PRETTY_REGEXP = Regexp.new("[^[:alnum:]._~!$&'()+,;=@]+").freeze
|
||||||
|
|
||||||
# Takes an indented string and removes the preceding spaces on each line
|
# Takes an indented string and removes the preceding spaces on each line
|
||||||
|
|
||||||
def strip_heredoc(str)
|
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
|
end
|
||||||
|
|
||||||
# Takes a slug and turns it into a simple title.
|
# Takes a slug and turns it into a simple title.
|
||||||
|
|
||||||
def titleize_slug(slug)
|
def titleize_slug(slug)
|
||||||
slug.split("-").map! do |val|
|
slug.split("-").map!(&:capitalize).join(" ")
|
||||||
val.capitalize
|
|
||||||
end.join(" ")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Non-destructive version of deep_merge_hashes! See that method.
|
# Non-destructive version of deep_merge_hashes! See that method.
|
||||||
|
@ -42,21 +40,9 @@ module Jekyll
|
||||||
#
|
#
|
||||||
# Thanks to whoever made it.
|
# Thanks to whoever made it.
|
||||||
def deep_merge_hashes!(target, overwrite)
|
def deep_merge_hashes!(target, overwrite)
|
||||||
target.merge!(overwrite) do |key, old_val, new_val|
|
merge_values(target, overwrite)
|
||||||
if new_val.nil?
|
merge_default_proc(target, overwrite)
|
||||||
old_val
|
duplicate_frozen_values(target)
|
||||||
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
|
|
||||||
|
|
||||||
target
|
target
|
||||||
end
|
end
|
||||||
|
@ -84,7 +70,9 @@ module Jekyll
|
||||||
# Returns an array
|
# Returns an array
|
||||||
def pluralized_array_from_hash(hash, singular_key, plural_key)
|
def pluralized_array_from_hash(hash, singular_key, plural_key)
|
||||||
[].tap do |array|
|
[].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.flatten.compact
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -146,11 +134,13 @@ module Jekyll
|
||||||
# Determines whether a given file has
|
# Determines whether a given file has
|
||||||
#
|
#
|
||||||
# Returns true if the YAML front matter is present.
|
# Returns true if the YAML front matter is present.
|
||||||
|
# rubocop: disable PredicateName
|
||||||
def has_yaml_header?(file)
|
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
|
rescue EOFError
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
# rubocop: enable PredicateName
|
||||||
|
|
||||||
# Slugify a filename or title.
|
# Slugify a filename or title.
|
||||||
#
|
#
|
||||||
|
@ -185,7 +175,7 @@ module Jekyll
|
||||||
#
|
#
|
||||||
# Returns the slugified string.
|
# Returns the slugified string.
|
||||||
def slugify(string, mode: nil, cased: false)
|
def slugify(string, mode: nil, cased: false)
|
||||||
mode ||= 'default'
|
mode ||= "default"
|
||||||
return nil if string.nil?
|
return nil if string.nil?
|
||||||
|
|
||||||
unless SLUGIFY_MODES.include?(mode)
|
unless SLUGIFY_MODES.include?(mode)
|
||||||
|
@ -195,21 +185,21 @@ module Jekyll
|
||||||
# Replace each character sequence with a hyphen
|
# Replace each character sequence with a hyphen
|
||||||
re =
|
re =
|
||||||
case mode
|
case mode
|
||||||
when 'raw'
|
when "raw"
|
||||||
SLUGIFY_RAW_REGEXP
|
SLUGIFY_RAW_REGEXP
|
||||||
when 'default'
|
when "default"
|
||||||
SLUGIFY_DEFAULT_REGEXP
|
SLUGIFY_DEFAULT_REGEXP
|
||||||
when 'pretty'
|
when "pretty"
|
||||||
# "._~!$&'()+,;=@" is human readable (not URI-escaped) in URL
|
# "._~!$&'()+,;=@" is human readable (not URI-escaped) in URL
|
||||||
# and is allowed in both extN and NTFS.
|
# and is allowed in both extN and NTFS.
|
||||||
SLUGIFY_PRETTY_REGEXP
|
SLUGIFY_PRETTY_REGEXP
|
||||||
end
|
end
|
||||||
|
|
||||||
# Strip according to the mode
|
# Strip according to the mode
|
||||||
slug = string.gsub(re, '-')
|
slug = string.gsub(re, "-")
|
||||||
|
|
||||||
# Remove leading/trailing hyphen
|
# Remove leading/trailing hyphen
|
||||||
slug.gsub!(/^\-|\-$/i, '')
|
slug.gsub!(%r!^\-|\-$!i, "")
|
||||||
|
|
||||||
slug.downcase! unless cased
|
slug.downcase! unless cased
|
||||||
slug
|
slug
|
||||||
|
@ -280,7 +270,7 @@ module Jekyll
|
||||||
# Returns matched pathes
|
# Returns matched pathes
|
||||||
def safe_glob(dir, patterns, flags = 0)
|
def safe_glob(dir, patterns, flags = 0)
|
||||||
return [] unless Dir.exist?(dir)
|
return [] unless Dir.exist?(dir)
|
||||||
pattern = File.join(Array patterns)
|
pattern = File.join(Array(patterns))
|
||||||
return [dir] if pattern.empty?
|
return [dir] if pattern.empty?
|
||||||
Dir.chdir(dir) do
|
Dir.chdir(dir) do
|
||||||
Dir.glob(pattern, flags).map { |f| File.join(dir, f) }
|
Dir.glob(pattern, flags).map { |f| File.join(dir, f) }
|
||||||
|
@ -297,5 +287,31 @@ module Jekyll
|
||||||
merged
|
merged
|
||||||
end
|
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
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
# which you are expected to set up once and rarely edit after that. If you find
|
# 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
|
# yourself editing these this file very often, consider using Jekyll's data files
|
||||||
# feature for the data you need to update frequently.
|
# feature for the data you need to update frequently.
|
||||||
|
#
|
||||||
# For technical reasons, this file is *NOT* reloaded automatically when you use
|
# For technical reasons, this file is *NOT* reloaded automatically when you use
|
||||||
# 'jekyll serve'. If you change this file, please restart the server process.
|
# 'jekyll serve'. If you change this file, please restart the server process.
|
||||||
|
|
||||||
|
@ -25,3 +26,4 @@ github_username: jekyll
|
||||||
|
|
||||||
# Build settings
|
# Build settings
|
||||||
markdown: kramdown
|
markdown: kramdown
|
||||||
|
theme: minima
|
||||||
|
|
|
@ -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>
|
|
|
@ -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>
|
|
|
@ -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>
|
|
|
@ -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>
|
|
|
@ -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 |
|
@ -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>
|
|
|
@ -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 |
|
@ -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>
|
|
|
@ -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>
|
|
|
@ -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>
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -3,8 +3,6 @@
|
||||||
---
|
---
|
||||||
@charset "utf-8";
|
@charset "utf-8";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Our variables
|
// Our variables
|
||||||
$base-font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
$base-font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||||
$base-font-size: 16px;
|
$base-font-size: 16px;
|
||||||
|
@ -28,8 +26,7 @@ $content-width: 800px;
|
||||||
$on-palm: 600px;
|
$on-palm: 600px;
|
||||||
$on-laptop: 800px;
|
$on-laptop: 800px;
|
||||||
|
|
||||||
|
// Minima also includes a mixin for defining media queries.
|
||||||
|
|
||||||
// Use media queries like this:
|
// Use media queries like this:
|
||||||
// @include media-query($on-palm) {
|
// @include media-query($on-palm) {
|
||||||
// .wrapper {
|
// .wrapper {
|
||||||
|
@ -37,17 +34,6 @@ $on-laptop: 800px;
|
||||||
// padding-left: $spacing-unit / 2;
|
// padding-left: $spacing-unit / 2;
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
@mixin media-query($device) {
|
|
||||||
@media screen and (max-width: $device) {
|
|
||||||
@content;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Import partials from the `minima` theme.
|
||||||
|
@import "minima";
|
||||||
// Import partials from `sass_dir` (defaults to `_sass`)
|
|
||||||
@import
|
|
||||||
"base",
|
|
||||||
"layout",
|
|
||||||
"syntax-highlighting"
|
|
||||||
;
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
{{ content }}
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
layout: default
|
||||||
|
---
|
||||||
|
|
||||||
|
{{ content }}
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
layout: default
|
||||||
|
---
|
||||||
|
|
||||||
|
{{ content }}
|
|
@ -1,6 +1,5 @@
|
||||||
---
|
---
|
||||||
# Specify a layout from your theme!
|
layout: post
|
||||||
# This will be the layout users specify for their posts.
|
|
||||||
---
|
---
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
|
@ -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.
|
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 %}
|
{% for post in site.posts %}
|
||||||
<h2>{{ post.title }}</h2>
|
<h2><a href="{{ post.url }}">{{ post.title }}</a></h2>
|
||||||
<blockquote>{{ post.excerpt }}</blockquote>
|
<blockquote>{{ post.excerpt }}</blockquote>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
.bundle
|
||||||
|
.sass-cache
|
||||||
|
_site
|
||||||
|
Gemfile.lock
|
|
@ -16,7 +16,7 @@ Gem::Specification.new do |spec|
|
||||||
spec.bindir = "exe"
|
spec.bindir = "exe"
|
||||||
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
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 "bundler", "~> 1.12"
|
||||||
spec.add_development_dependency "rake", "~> 10.0"
|
spec.add_development_dependency "rake", "~> 10.0"
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
bundle exec rubocop --version
|
||||||
bundle exec rubocop -D $@
|
bundle exec rubocop -D $@
|
||||||
|
|
|
@ -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!
|
- [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 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.
|
- [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
|
#### Editors
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ class TestFilters < JekyllUnitTest
|
||||||
"destination" => dest_dir,
|
"destination" => dest_dir,
|
||||||
"timezone" => "UTC"
|
"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")
|
@sample_date = Date.parse("2013-03-27")
|
||||||
@time_as_string = "September 11, 2001 12:46:30 -0000"
|
@time_as_string = "September 11, 2001 12:46:30 -0000"
|
||||||
@time_as_numeric = 1_399_680_607
|
@time_as_numeric = 1_399_680_607
|
||||||
|
|
|
@ -28,7 +28,7 @@ class TestKramdown < JekyllUnitTest
|
||||||
end
|
end
|
||||||
|
|
||||||
should "run Kramdown" do
|
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
|
end
|
||||||
|
|
||||||
context "when asked to convert smart quotes" do
|
context "when asked to convert smart quotes" do
|
||||||
|
|
|
@ -39,7 +39,7 @@ class TestPage < JekyllUnitTest
|
||||||
end
|
end
|
||||||
|
|
||||||
should "create url with non-alphabetic characters" do
|
should "create url with non-alphabetic characters" do
|
||||||
@page = setup_page("+", '%# +.md')
|
@page = setup_page("+", "%# +.md")
|
||||||
assert_equal "/+/%25%23%20+.html", @page.url
|
assert_equal "/+/%25%23%20+.html", @page.url
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -268,12 +268,12 @@ class TestPage < JekyllUnitTest
|
||||||
end
|
end
|
||||||
|
|
||||||
should "write even when permalink has '%# +'" do
|
should "write even when permalink has '%# +'" do
|
||||||
page = setup_page("+", '%# +.md')
|
page = setup_page("+", "%# +.md")
|
||||||
do_render(page)
|
do_render(page)
|
||||||
page.write(dest_dir)
|
page.write(dest_dir)
|
||||||
|
|
||||||
assert File.directory?(dest_dir)
|
assert File.directory?(dest_dir)
|
||||||
assert_exist dest_dir("+", '%# +.html')
|
assert_exist dest_dir("+", "%# +.html")
|
||||||
end
|
end
|
||||||
|
|
||||||
should "write properly without html extension" do
|
should "write properly without html extension" do
|
||||||
|
|
Loading…
Reference in New Issue