mirror of
https://github.com/jekyll/jekyll.git
synced 2026-04-28 03:01:03 -04:00
Compare commits
2 Commits
fix-more-t
...
roadmap
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fb04d0db3b | ||
|
|
f9411bd362 |
2
.github/CONTRIBUTING.markdown
vendored
2
.github/CONTRIBUTING.markdown
vendored
@@ -49,7 +49,7 @@ That's it! You'll be automatically subscribed to receive updates as others revie
|
||||
### Submitting a pull request via Git command line
|
||||
|
||||
1. Fork the project by clicking "Fork" in the top right corner of [`jekyll/jekyll`](https://github.com/jekyll/jekyll).
|
||||
2. Clone the repository locally `git clone https://github.com/<you-username>/jekyll`.
|
||||
2. Clone the repository lcoally `git clone https://github.com/<you-username>/jekyll`.
|
||||
3. Create a new, descriptively named branch to contain your change ( `git checkout -b my-awesome-feature` ).
|
||||
4. Hack away, add tests. Not necessarily in that order.
|
||||
5. Make sure everything still passes by running `script/cibuild` (see [the tests section](#running-tests-locally) below)
|
||||
|
||||
74
.github/ISSUE_TEMPLATE.md
vendored
74
.github/ISSUE_TEMPLATE.md
vendored
@@ -1,78 +1,20 @@
|
||||
<!--
|
||||
Hi! Thanks for considering to file a bug with Jekyll. Please take the time to
|
||||
answer the basic questions. You can convert `[ ]` into `[x]` to check boxes (or submit
|
||||
and check.) If there is no need for certain fields like output and redirection, please delete
|
||||
those headers before submitting. We know not all tickets require those steps.
|
||||
Otherwise, please try to be as detailed as possible.
|
||||
|
||||
If you are unsure this is a bug in Jekyll, or this is a bug caused
|
||||
by a plugin that isn't directly related to Jekyll, or if this is just
|
||||
a generic usage question, please consider asking your question at
|
||||
https://talk.jekyllrb.com where non-bug questions go.
|
||||
|
||||
Thanks!
|
||||
-->
|
||||
###### What version of Jekyll are you using (`jekyll -v`)?
|
||||
|
||||
- [ ] I believe this to be a bug, not a question about using Jekyll.
|
||||
- [ ] I Updated to the latest Jekyll (or) if on Github Pages to the latest `github-pages`
|
||||
- [ ] I Read the CONTRIBUTION file at https://jekyllrb.com/docs/contributing/
|
||||
- [ ] This is a feature request.
|
||||
|
||||
---
|
||||
|
||||
- [ ] I am on (or have tested on) ***macOS*** 10+
|
||||
- [ ] I am on (or have tested on) ***Debian/Ubuntu*** GNU/Linux
|
||||
- [ ] I am on (or have tested on) ***Fedora*** GNU/Linux
|
||||
- [ ] I am on (or have tested on) ***Arch*** GNU/Linux
|
||||
- [ ] I am on (or have tested on) ***Other*** GNU/Linux
|
||||
- [ ] I am on (or have tested on) ***Windows*** 10+
|
||||
###### What operating system are you using?
|
||||
|
||||
<!--
|
||||
Other GNU/Linux includes Scientific GNU/Linux, CentOS GNU/Linux, and others.
|
||||
If you are on a minor sub-distro (such as ElementaryOS which does not diverge from
|
||||
Ubuntu much, please check the parent distro. Kubuntu, Edubuntu, Lubuntu should
|
||||
also be flagged as Ubuntu as their packages come from upstream Ubuntu.
|
||||
-->
|
||||
|
||||
---
|
||||
|
||||
- [ ] I was trying to install.
|
||||
- [ ] There is a broken Plugin API.
|
||||
- [ ] I had an error on Github Pages, and I have not tested locally.
|
||||
- [ ] I had an error on Github Pages, and Github Support said it was a Jekyll Bug.
|
||||
- [ ] I had an error on Github Pages and I did not test it locally.
|
||||
- [ ] I was trying to build.
|
||||
- [ ] It was another bug.
|
||||
###### What did you do?
|
||||
(Please include the content causing the issue, any relevant configuration settings, and the command you ran)
|
||||
|
||||
## My Reproduction Steps
|
||||
|
||||
<!--
|
||||
If this error occured on Github Pages, please try to provide us with logs,
|
||||
and look at them yourself, to determine if this is an actual Jekyll bug. In
|
||||
the event you are unsure, file a ticket, however, when you do please provide
|
||||
the logs (strip them of personal information.)
|
||||
|
||||
If you have trouble finding your logs, please email support@github.com and
|
||||
they will happily help you. If you cannot find logs, please try your best to
|
||||
replicate it locally because we cannot fix a problem if we do not know
|
||||
exactly what caused it, or within a relatively close distance.
|
||||
-->
|
||||
|
||||
<!--
|
||||
Insert the steps you took to for this problem to exist. Such as the
|
||||
directories you created and, the full command you ran, and include any
|
||||
plugins you have installed, this is very important.
|
||||
|
||||
If your steps are complicated, you can also submit a Github
|
||||
repository (please no zips, they will be removed and rejected by maintainers,)
|
||||
and just supply a command for us to reproduce it ourselves.
|
||||
-->
|
||||
###### What did you expect to see?
|
||||
|
||||
## The Output I Wanted
|
||||
|
||||
<!--
|
||||
Insert the output from the command. Alter it as little as you can.
|
||||
The minimum should be personal information. Though we normally don't log
|
||||
anything like that so there should be no need to alter it.
|
||||
-->
|
||||
|
||||
###### What did you see instead?
|
||||
|
||||
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -13,7 +13,6 @@
|
||||
/vendor
|
||||
Gemfile.lock
|
||||
_site/
|
||||
bin/
|
||||
bbin/
|
||||
coverage
|
||||
gh-pages/
|
||||
|
||||
197
.rubocop.yml
197
.rubocop.yml
@@ -1,129 +1,80 @@
|
||||
---
|
||||
Metrics/MethodLength: { Max: 24 }
|
||||
Metrics/ClassLength: { Max: 240 }
|
||||
Metrics/ModuleLength: { Max: 240 }
|
||||
Metrics/LineLength: { Max: 112 }
|
||||
Metrics/CyclomaticComplexity: { Max: 8 }
|
||||
Metrics/PerceivedComplexity: { Max: 8 }
|
||||
Metrics/ParameterLists: { Max: 4 }
|
||||
Metrics/MethodLength: { Max: 24 }
|
||||
Metrics/AbcSize: { Max: 20 }
|
||||
|
||||
Style/IndentHash: { EnforcedStyle: consistent }
|
||||
Style/HashSyntax: { EnforcedStyle: hash_rockets }
|
||||
Style/SignalException: { EnforcedStyle: only_raise }
|
||||
Style/AlignParameters: { EnforcedStyle: with_fixed_indentation }
|
||||
Style/StringLiteralsInInterpolation: { EnforcedStyle: double_quotes }
|
||||
Style/MultilineMethodCallIndentation: { EnforcedStyle: indented }
|
||||
Style/MultilineOperationIndentation: { EnforcedStyle: indented }
|
||||
Style/FirstParameterIndentation: { EnforcedStyle: consistent }
|
||||
Style/StringLiterals: { EnforcedStyle: double_quotes }
|
||||
Style/RegexpLiteral: { EnforcedStyle: slashes }
|
||||
Style/IndentArray: { EnforcedStyle: consistent }
|
||||
Style/ExtraSpacing: { AllowForAlignment: true }
|
||||
|
||||
Style/PercentLiteralDelimiters:
|
||||
PreferredDelimiters:
|
||||
'%q': '{}'
|
||||
'%Q': '{}'
|
||||
'%r': '!!'
|
||||
'%s': '()'
|
||||
'%w': '()'
|
||||
'%W': '()'
|
||||
'%x': '()'
|
||||
|
||||
Style/AlignArray: { Enabled: false }
|
||||
Style/StringLiterals: { Enabled: false }
|
||||
Style/Documentation: { Enabled: false }
|
||||
Style/DoubleNegation: { Enabled: false }
|
||||
Style/UnneededCapitalW: { Enabled: false }
|
||||
Style/EmptyLinesAroundModuleBody: { Enabled: false }
|
||||
Style/EmptyLinesAroundAccessModifier: { Enabled: false }
|
||||
Style/BracesAroundHashParameters: { Enabled: false }
|
||||
Style/SpaceInsideBrackets: { Enabled: false }
|
||||
Style/IfUnlessModifier: { Enabled: false }
|
||||
Style/ModuleFunction: { Enabled: false }
|
||||
Style/RescueModifier: { Enabled: false }
|
||||
Style/GuardClause: { Enabled: false }
|
||||
Style/FileName: { Enabled: false }
|
||||
Lint/UselessAccessModifier: { Enabled: false }
|
||||
Style/SpaceAroundOperators: { Enabled: false }
|
||||
Style/RedundantReturn: { Enabled: false }
|
||||
Style/SingleLineMethods: { Enabled: false }
|
||||
|
||||
AllCops:
|
||||
TargetRubyVersion: 2.0
|
||||
Include:
|
||||
- lib/**/*.rb
|
||||
|
||||
Exclude:
|
||||
- lib/jekyll/collection.rb
|
||||
- lib/jekyll/convertible.rb
|
||||
- lib/jekyll/document.rb
|
||||
- lib/jekyll/renderer.rb
|
||||
- bin/**/*
|
||||
- benchmark/**/*
|
||||
- script/**/*
|
||||
- .rubocop.yml
|
||||
- .codeclimate.yml
|
||||
- .travis.yml
|
||||
- .gitignore
|
||||
- .rspec
|
||||
|
||||
- Gemfile.lock
|
||||
- CHANGELOG.{md,markdown,txt,textile}
|
||||
- CONTRIBUTING.{md,markdown,txt,textile}
|
||||
- readme.{md,markdown,txt,textile}
|
||||
- README.{md,markdown,txt,textile}
|
||||
- Readme.{md,markdown,txt,textile}
|
||||
- ReadMe.{md,markdown,txt,textile}
|
||||
- COPYING
|
||||
- LICENSE
|
||||
|
||||
- site/**/*
|
||||
- test/**/*
|
||||
- vendor/**/*
|
||||
Lint/EndAlignment:
|
||||
Severity: error
|
||||
Lint/UnreachableCode:
|
||||
Severity: error
|
||||
Lint/UselessAccessModifier:
|
||||
Enabled: false
|
||||
Metrics/AbcSize:
|
||||
Max: 20
|
||||
Metrics/ClassLength:
|
||||
Max: 300
|
||||
Exclude:
|
||||
- !ruby/regexp /features\/.*.rb$/
|
||||
- !ruby/regexp /test\/.*.rb$/
|
||||
Metrics/CyclomaticComplexity:
|
||||
Max: 8
|
||||
Metrics/LineLength:
|
||||
Max: 90
|
||||
Severity: warning
|
||||
Exclude:
|
||||
- !ruby/regexp /features\/.*.rb/
|
||||
Metrics/MethodLength:
|
||||
Max: 20
|
||||
CountComments: false
|
||||
Severity: error
|
||||
Metrics/ModuleLength:
|
||||
Max: 240
|
||||
Metrics/ParameterLists:
|
||||
Max: 4
|
||||
Metrics/PerceivedComplexity:
|
||||
Max: 8
|
||||
Style/Alias:
|
||||
Enabled: false
|
||||
Style/AlignArray:
|
||||
Enabled: false
|
||||
Style/AlignHash:
|
||||
EnforcedHashRocketStyle: table
|
||||
Style/AlignParameters:
|
||||
EnforcedStyle: with_fixed_indentation
|
||||
Enabled: false
|
||||
Style/AndOr:
|
||||
Severity: error
|
||||
Style/Attr:
|
||||
Enabled: false
|
||||
Style/BracesAroundHashParameters:
|
||||
Enabled: false
|
||||
Style/ClassAndModuleChildren:
|
||||
Enabled: false
|
||||
Style/Documentation:
|
||||
Enabled: false
|
||||
Exclude:
|
||||
- !ruby/regexp /features\/.*.rb$/
|
||||
Style/DoubleNegation:
|
||||
Enabled: false
|
||||
Style/EmptyLinesAroundAccessModifier:
|
||||
Enabled: false
|
||||
Style/EmptyLinesAroundModuleBody:
|
||||
Enabled: false
|
||||
Style/ExtraSpacing:
|
||||
AllowForAlignment: true
|
||||
Style/FileName:
|
||||
Enabled: false
|
||||
Style/FirstParameterIndentation:
|
||||
EnforcedStyle: consistent
|
||||
Style/GuardClause:
|
||||
Enabled: false
|
||||
Style/HashSyntax:
|
||||
EnforcedStyle: hash_rockets
|
||||
Severity: error
|
||||
Style/IfUnlessModifier:
|
||||
Enabled: false
|
||||
Style/IndentArray:
|
||||
EnforcedStyle: consistent
|
||||
Style/IndentHash:
|
||||
EnforcedStyle: consistent
|
||||
Style/IndentationWidth:
|
||||
Severity: error
|
||||
Style/ModuleFunction:
|
||||
Enabled: false
|
||||
Style/MultilineMethodCallIndentation:
|
||||
EnforcedStyle: indented
|
||||
Style/MultilineOperationIndentation:
|
||||
EnforcedStyle: indented
|
||||
Style/MultilineTernaryOperator:
|
||||
Severity: error
|
||||
Style/PercentLiteralDelimiters:
|
||||
PreferredDelimiters:
|
||||
"%q": "{}"
|
||||
"%Q": "{}"
|
||||
"%r": "!!"
|
||||
"%s": "()"
|
||||
"%w": "()"
|
||||
"%W": "()"
|
||||
"%x": "()"
|
||||
Style/RedundantReturn:
|
||||
Enabled: false
|
||||
Style/RedundantSelf:
|
||||
Enabled: false
|
||||
Style/RegexpLiteral:
|
||||
EnforcedStyle: percent_r
|
||||
Style/RescueModifier:
|
||||
Enabled: false
|
||||
Style/SignalException:
|
||||
EnforcedStyle: only_raise
|
||||
Style/SingleLineMethods:
|
||||
Enabled: false
|
||||
Style/SpaceAroundOperators:
|
||||
Enabled: false
|
||||
Style/SpaceInsideBrackets:
|
||||
Enabled: false
|
||||
Style/StringLiterals:
|
||||
EnforcedStyle: double_quotes
|
||||
Style/StringLiteralsInInterpolation:
|
||||
EnforcedStyle: double_quotes
|
||||
Style/UnneededCapitalW:
|
||||
Enabled: false
|
||||
- features/**/*
|
||||
- script/**/*
|
||||
- spec/**/*
|
||||
|
||||
17
.travis.yml
17
.travis.yml
@@ -1,3 +1,4 @@
|
||||
before_script: bundle update
|
||||
bundler_args: --without benchmark:site:development
|
||||
script: script/cibuild
|
||||
cache: bundler
|
||||
@@ -8,13 +9,14 @@ rvm:
|
||||
- &ruby1 2.3.0
|
||||
- &ruby2 2.2.4
|
||||
- &ruby3 2.1.8
|
||||
- &jruby jruby-9.0.4.0
|
||||
- &rhead ruby-head
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- rvm: 2.3.0
|
||||
env: TEST_SUITE=fmt
|
||||
- rvm: jruby-9.0.5.0
|
||||
env: TEST_SUITE=test
|
||||
fast_finish: true
|
||||
allow_failures:
|
||||
- rvm: *jruby
|
||||
- rvm: *rhead
|
||||
env:
|
||||
matrix:
|
||||
- TEST_SUITE=test
|
||||
@@ -23,9 +25,12 @@ env:
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- themes
|
||||
|
||||
notifications:
|
||||
irc:
|
||||
template: "%{repository}#%{build_number} (%{branch}) %{message} %{build_url}"
|
||||
channels: irc.freenode.org#jekyll
|
||||
|
||||
email:
|
||||
recipients:
|
||||
- jordon@envygeeks.io
|
||||
|
||||
6
Gemfile
6
Gemfile
@@ -4,6 +4,7 @@ gemspec :name => "jekyll"
|
||||
gem "rake", "~> 11.0"
|
||||
group :development do
|
||||
gem "launchy", "~> 2.3"
|
||||
gem "rubocop", :branch => :master, :github => "bbatsov/rubocop"
|
||||
gem "pry"
|
||||
|
||||
unless RUBY_ENGINE == "jruby"
|
||||
@@ -14,7 +15,6 @@ end
|
||||
#
|
||||
|
||||
group :test do
|
||||
gem "rubocop"
|
||||
gem "cucumber", "~> 2.1"
|
||||
gem "jekyll_test_plugin"
|
||||
gem "jekyll_test_plugin_malicious"
|
||||
@@ -22,9 +22,6 @@ group :test do
|
||||
gem "rspec-mocks"
|
||||
gem "nokogiri"
|
||||
gem "rspec"
|
||||
gem "test-theme", path: File.expand_path("./test/fixtures/test-theme", File.dirname(__FILE__))
|
||||
|
||||
gem "jruby-openssl" if RUBY_ENGINE == "jruby"
|
||||
end
|
||||
|
||||
#
|
||||
@@ -88,5 +85,4 @@ group :site do
|
||||
gem "jekyll-sitemap"
|
||||
gem "jekyll-seo-tag", "~> 1.1"
|
||||
gem "jekyll-avatar"
|
||||
gem "jekyll-mentions"
|
||||
end
|
||||
|
||||
133
History.markdown
133
History.markdown
@@ -19,18 +19,6 @@
|
||||
* Allow static files to be symlinked in unsafe mode or non-prod environments (#4640)
|
||||
* Add `:after_init` hook & add `Site#config=` to make resetting config easy (#4703)
|
||||
* DocumentDrop: add `#<=>` which sorts by date (falling back to path) (#4741)
|
||||
* Add a where_exp filter for filtering by expression (#4478)
|
||||
* Globalize Jekyll's Filters. (#4792)
|
||||
* Gem-based themes (#4595)
|
||||
* Allow symlinks if they point to stuff inside site.source (#4710)
|
||||
* Update colorator dependency to v1.x (#4855)
|
||||
* Move EntryFilter to use Pathutil & fix `glob_include?` (#4859)
|
||||
* Add 'jekyll new-theme' command to help users get up and running creating a theme (#4848)
|
||||
* markdownify and smartify should convert input to string before conversion (#4958)
|
||||
* Run Site#generate for 'jekyll doctor' to catch plugin issues (#5005)
|
||||
* Add normalize_whitepace filter (#4917)
|
||||
* Move bin/jekyll to exe/jekyll to prevent collision with binstubs (#5014)
|
||||
* Cleaning up site template & theme updates. (#4922)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -42,21 +30,6 @@
|
||||
* Ensures related_posts are only set for a post (#4620)
|
||||
* EntryFilter#special?: ignore filenames which begin with '~' (#4491)
|
||||
* Cleaner: `keep_files` should only apply to the beginning of paths, not substrings with index > 0 (#3849)
|
||||
* Use SSLEnable instead of EnableSSL and make URL HTTPS. (#4693)
|
||||
* convertible: use Document::YAML_FRONT_MATTER_REGEXP to parse transformable files (#4786)
|
||||
* Example in the site template should be IANA-approved example.com (#4793)
|
||||
* 3.2.x/master: Fix defaults for Documents (posts/collection docs) (#4808)
|
||||
* Don't rescue LoadError or bundler load errors for Bundler. (#4857)
|
||||
* `Serve.process` should receive same config as `Build.process` (#4953)
|
||||
* Prevent reset of page in Liquid payload right before rendering layouts (#5009)
|
||||
|
||||
### Forward Ports
|
||||
|
||||
* From v3.1.4: Add ExcerptDrop and remove excerpt's ability to refer to itself in Liquid (#4941)
|
||||
* From v3.1.4: Configuration permalink fix and addition of Configuration.from and sorting `site.collections` by label (#4942)
|
||||
* From v3.1.4: Fix `{{ layout }}` oddities (proper inheritance & fixing overflow of old data) (#4943)
|
||||
* From v3.1.5: Sort the results of the `require_all` glob (#4944)
|
||||
* From v3.1.6: Add ability to render drops as JSON (#4945)
|
||||
|
||||
### Development Fixes
|
||||
|
||||
@@ -68,44 +41,6 @@
|
||||
* Update Rake & disable warnings when running tests (#4720)
|
||||
* Fix many warnings (#4537)
|
||||
* Don't blindly assume the last system when determining "open" cmd (#4717)
|
||||
* Fix "locally" typo in contributing documentation (#4756)
|
||||
* Update Rubocop rules (#4886)
|
||||
* Flesh out the issue template to be much more detailed (#4849)
|
||||
* Fixing rubocop offenses in lib/jekyll/cleaner.rb (#4892)
|
||||
* Update `jekyll/commands*` to pass rubocop rules (#4888)
|
||||
* Clean up many test files to pass Rubocop rules (#4902)
|
||||
* Rubocop cleanup for some utils and further test files (#4916)
|
||||
* Rubocop: Low hanging fruit (#4936)
|
||||
* Rubocop: `Drop` changes from v3.1 forward-ports (#4949)
|
||||
* Rubocop: cleanup for misc files (#4946)
|
||||
* Rubocop: Stevenson (#4951)
|
||||
* Rubocop: lib/jekyll/entry_filter.rb (#4950)
|
||||
* Rubocop: `test/*` (#4947)
|
||||
* Rubocop: features (#4934)
|
||||
* Rubocop: Liquid renderer (#4933)
|
||||
* Rubocop: converters (#4931)
|
||||
* Rubocop: Site Drop (#4948)
|
||||
* Rubocop: tags (#4938)
|
||||
* Rubocop: Readers (#4932)
|
||||
* rubocop: jekyll/lib/frontmatter_defaults.rb (#4974)
|
||||
* rubocop: features/step_definitions.rb (#4956)
|
||||
* Rubocop theme and url jekyll libs (#4959)
|
||||
* Rubocop jekyll.rb (#4966)
|
||||
* Rubocop: use %r for all regular expressions. (#4979)
|
||||
* Cleanup and make misc files compliant with Rubocop. (#4940)
|
||||
* Rubocop: jekyll/lib/site.rb (#4973)
|
||||
* Add timings for each scenario in cucumber & print worst offenders (#4908)
|
||||
* rubocop: jekyll/lib/filters.rb (#4993)
|
||||
* Fix rubocop offenses in exe/jekyll (#5017)
|
||||
* Rubocop: lib/jekyll/command.rb (#5018)
|
||||
* rubocop: lib/jekyll/static_file.rb (#5019)
|
||||
* rubocop: lib/jekyll/utils.rb (#5026)
|
||||
* rubocop: lib/jekyll/regenerator.rb (#5025)
|
||||
* rubocop: lib/jekyll/configuration.rb (#5024)
|
||||
* rubocop: lib/jekyll/renderer.rb style fixes (#5032)
|
||||
* rubocop: lib/jekyll/convertible.rb style fixes (#5031)
|
||||
* rubocop: lib/jekyll/document.rb style fixes (#5030)
|
||||
* Remove ruby-head from Travis matrix & fix jruby failures (#5015)
|
||||
|
||||
### Site Enhancements
|
||||
|
||||
@@ -130,65 +65,6 @@
|
||||
* Add Hawkins to the list of third-party plugins (#4755)
|
||||
* Fix a typo in pagination doc (#4763)
|
||||
* Switch second GitHub Pages link to HTTPS (#4760)
|
||||
* Explain data file format requirements more clearly in documentation (#4781)
|
||||
* Add jekyll-i18n_tags to list of third-party plugins (#4775)
|
||||
* Remove Leonard Lamprecht's website from Sites page (#4771)
|
||||
* Updates documentation for collections to include `date` property (#4769)
|
||||
* Added an explicit rerun note to configuration.md, defaults section (#4734)
|
||||
* Update Rack-Jekyll Heroku deployment blog post url (#4789)
|
||||
* Added missing single quote on rsync client side command (#4813)
|
||||
* Organize Form Platforms-as-a-Service into unified list & add FormSpree.io (#4754)
|
||||
* Fixed typo on Configuration page (#4804)
|
||||
* Update FormKeep URL on the Resources doc (#4844)
|
||||
* site: use liquid & reduce some whitespace noise (#4854)
|
||||
* Add jekyll-breadcrumbs to list of third-party plugins (#4874)
|
||||
* Added Pug converter to list of third-party plugins (#4872)
|
||||
* Add jekyll-ideal-image-slider to list of third-party plugins (#4863)
|
||||
* Add Jekyll Tips and the Cheatsheet to the list of resources (#4887)
|
||||
* Removed extra `</p>` from `site/_docs/permalinks.md` (#4890)
|
||||
* Add pubstorm deployment instructions to docs (#4881)
|
||||
* Corrected pagination docs for hidden: true feature (#4903)
|
||||
* Remove a Broken Link for Refheap Plugin (#4971)
|
||||
* Instructions on how to install github-gem on Windows (#4975)
|
||||
* Minor tweak to fix missing apostrophne (#4962)
|
||||
* Instructions on how to install github-gem on Windows (v2) (#4977)
|
||||
* Fix inaccurate HTTP response header field name (#4976)
|
||||
* Add post about GSoC project (#4980)
|
||||
* Link to the HTML page instead of Markdown (#4985)
|
||||
* Update normalize.css to v4.0.0. (#4989)
|
||||
* Add jekyll-tags-list-plugin to list of third-party plugins (#5000)
|
||||
* Windows docs: Command needs to be called from blog path (#5006)
|
||||
* Update text to be consitent with example (#5010)
|
||||
* Update template links to point to core Liquid site (#5012)
|
||||
* Add generator-jekyllized to third-party plugins (#5027)
|
||||
|
||||
## 3.1.6 / 2016-05-19
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Add ability to `jsonify` Drops such that, e.g. `site | jsonify`, works. (#4914)
|
||||
|
||||
## 3.1.5 / 2016-05-18
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Sort the results of the `require_all` glob (affects Linux only). (#4912)
|
||||
|
||||
## 3.1.4 / 2016-05-18
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Add `ExcerptDrop` and remove excerpt's ability to refer to itself in Liquid (#4907)
|
||||
* Configuration permalink fix where `collections.posts.permalink` inherits properly from `permalink` only when it doesn't exist (#4910)
|
||||
* Add `Configuration.from` to make it easier to build configs from just a hash
|
||||
* Sorting `site.collections` in Liquid by label (#4910)
|
||||
* Fix bug where `layout` in Liquid would inherit from previously-rendered layouts' metadatas (#4909)
|
||||
* Fix bug where `layout` in Liquid would override in the wrong direction (more-specific layouts' data were overwritten by their parent layouts' data; this has now been reversed) (#4909)
|
||||
|
||||
## 3.1.3 / 2016-04-18
|
||||
|
||||
* Fix defaults for Documents to lookup defaults based on `relative_path` instead of `url` (#4807)
|
||||
* Use SSLEnable instead of EnableSSL and make URL HTTPS (WEBrick) (#4693)
|
||||
|
||||
## 3.1.2 / 2016-02-19
|
||||
|
||||
@@ -337,15 +213,6 @@
|
||||
* Add Contentful Extension to list of third-party plugins (#4390)
|
||||
* Correct Minor spelling error (#4394)
|
||||
|
||||
## 3.0.5 / 2016-04-26
|
||||
|
||||
* Remove call to `#backwards_compatibilize` in `Configuration.from` (#4846)
|
||||
|
||||
## 3.0.4 / 2016-04-18
|
||||
|
||||
* Fix defaults for Documents to lookup defaults based on `relative_path` instead of `url` (#4806)
|
||||
* Configuration: allow users to specify a `collections.posts.permalink` directly without `permalink` clobbering it (#4753)
|
||||
|
||||
## 3.0.3 / 2016-02-08
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
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
|
||||
@@ -1,10 +1,10 @@
|
||||
#!/usr/bin/env ruby
|
||||
STDOUT.sync = true
|
||||
|
||||
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), *%w(.. lib)))
|
||||
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), *%w( .. lib ))
|
||||
|
||||
require "jekyll"
|
||||
require "mercenary"
|
||||
require 'jekyll'
|
||||
require 'mercenary'
|
||||
|
||||
Jekyll::PluginManager.require_from_bundler
|
||||
|
||||
@@ -12,26 +12,22 @@ Jekyll::Deprecator.process(ARGV)
|
||||
|
||||
Mercenary.program(:jekyll) do |p|
|
||||
p.version Jekyll::VERSION
|
||||
p.description "Jekyll is a blog-aware, static site generator in Ruby"
|
||||
p.syntax "jekyll <subcommand> [options]"
|
||||
p.description 'Jekyll is a blog-aware, static site generator in Ruby'
|
||||
p.syntax 'jekyll <subcommand> [options]'
|
||||
|
||||
p.option "source", "-s", "--source [DIR]", "Source directory (defaults to ./)"
|
||||
p.option "destination", "-d", "--destination [DIR]",
|
||||
"Destination directory (defaults to ./_site)"
|
||||
p.option "safe", "--safe", "Safe mode (defaults to false)"
|
||||
p.option "plugins_dir", "-p", "--plugins PLUGINS_DIR1[,PLUGINS_DIR2[,...]]", Array,
|
||||
"Plugins directory (defaults to ./_plugins)"
|
||||
p.option "layouts_dir", "--layouts DIR", String,
|
||||
"Layouts directory (defaults to ./_layouts)"
|
||||
p.option "profile", "--profile", "Generate a Liquid rendering profile"
|
||||
p.option 'source', '-s', '--source [DIR]', 'Source directory (defaults to ./)'
|
||||
p.option 'destination', '-d', '--destination [DIR]', 'Destination directory (defaults to ./_site)'
|
||||
p.option 'safe', '--safe', 'Safe mode (defaults to false)'
|
||||
p.option 'plugins_dir', '-p', '--plugins PLUGINS_DIR1[,PLUGINS_DIR2[,...]]', Array, 'Plugins directory (defaults to ./_plugins)'
|
||||
p.option 'layouts_dir', '--layouts DIR', String, 'Layouts directory (defaults to ./_layouts)'
|
||||
p.option 'profile', '--profile', 'Generate a Liquid rendering profile'
|
||||
|
||||
Jekyll::External.require_if_present(Jekyll::External.blessed_gems) do |g|
|
||||
cmd = g.split("-").last
|
||||
cmd = g.split('-').last
|
||||
p.command(cmd.to_sym) do |c|
|
||||
c.syntax cmd
|
||||
c.action do
|
||||
Jekyll.logger.abort_with "You must install the '#{g}' gem" \
|
||||
" to use the 'jekyll #{cmd}' command."
|
||||
Jekyll.logger.abort_with "You must install the '#{g}' gem to use the 'jekyll #{cmd}' command."
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -80,26 +80,6 @@ Feature: frontmatter defaults
|
||||
And I should see "main: <p>content of site/special/2013/10/14/about1.html</p>" in "_site/special/2013/10/14/about1.html"
|
||||
And I should see "main: <p>content of site/special/2013/10/14/about2.html</p>" in "_site/special/2013/10/14/about2.html"
|
||||
|
||||
Scenario: Use frontmatter scopes for subdirectories
|
||||
Given I have a _layouts directory
|
||||
And I have a main layout that contains "main: {{ content }}"
|
||||
|
||||
And I have a _posts/en directory
|
||||
And I have the following post under "en":
|
||||
| title | date | content |
|
||||
| helloworld | 2014-09-01 | {{page.lang}} is the current language |
|
||||
And I have a _posts/de directory
|
||||
And I have the following post under "de":
|
||||
| title | date | content |
|
||||
| hallowelt | 2014-09-01 | {{page.lang}} is the current language |
|
||||
|
||||
And I have a configuration file with "defaults" set to "[{scope: {path: "_posts/en"}, values: {layout: "main", lang: "en"}}, {scope: {path: "_posts/de"}, values: {layout: "main", lang: "de"}}]"
|
||||
|
||||
When I run jekyll build
|
||||
Then the _site directory should exist
|
||||
And I should see "main: <p>en is the current language</p>" in "_site/2014/09/01/helloworld.html"
|
||||
And I should see "main: <p>de is the current language</p>" in "_site/2014/09/01/hallowelt.html"
|
||||
|
||||
Scenario: Override frontmatter defaults by type
|
||||
Given I have a _posts directory
|
||||
And I have the following post:
|
||||
|
||||
@@ -333,28 +333,3 @@ Feature: Hooks
|
||||
Then I should get a zero exit status
|
||||
And the _site directory should exist
|
||||
And I should see "Wrote document 0" in "_site/document-build.log"
|
||||
|
||||
Scenario: Set a custom payload['page'] property
|
||||
Given I have a _plugins directory
|
||||
And I have a "_plugins/ext.rb" file with content:
|
||||
"""
|
||||
Jekyll::Hooks.register :pages, :pre_render do |page, payload|
|
||||
payload['page']['foo'] = "hello world"
|
||||
end
|
||||
"""
|
||||
And I have a _layouts directory
|
||||
And I have a "_layouts/custom.html" file with content:
|
||||
"""
|
||||
---
|
||||
---
|
||||
{{ content }} {% include foo.html %}
|
||||
"""
|
||||
And I have a _includes directory
|
||||
And I have a "_includes/foo.html" file with content:
|
||||
"""
|
||||
{{page.foo}}
|
||||
"""
|
||||
And I have an "index.html" page with layout "custom" that contains "page content"
|
||||
When I run jekyll build
|
||||
Then the "_site/index.html" file should exist
|
||||
And I should see "page content\n hello world" in "_site/index.html"
|
||||
|
||||
@@ -35,36 +35,3 @@ Feature: Layout data
|
||||
When I run jekyll build
|
||||
Then the "_site/index.html" file should exist
|
||||
And I should see "page content\n foo: my custom data" in "_site/index.html"
|
||||
|
||||
Scenario: Inherit custom layout data and clear when not present
|
||||
Given I have a _layouts directory
|
||||
And I have a "_layouts/default.html" file with content:
|
||||
"""
|
||||
---
|
||||
bar: i'm default
|
||||
---
|
||||
{{ content }} foo: '{{ layout.foo }}' bar: '{{ layout.bar }}'
|
||||
"""
|
||||
And I have a "_layouts/special.html" file with content:
|
||||
"""
|
||||
---
|
||||
layout: default
|
||||
foo: my special data
|
||||
bar: im special
|
||||
---
|
||||
{{ content }}
|
||||
"""
|
||||
And I have a "_layouts/page.html" file with content:
|
||||
"""
|
||||
---
|
||||
layout: default
|
||||
bar: im page
|
||||
---
|
||||
{{ content }}
|
||||
"""
|
||||
And I have an "index.html" page with layout "special" that contains "page content"
|
||||
And I have an "jekyll.html" page with layout "page" that contains "page content"
|
||||
When I run jekyll build
|
||||
Then the "_site/index.html" file should exist
|
||||
And I should see "page content\n foo: 'my special data' bar: 'im special'" in "_site/index.html"
|
||||
And I should see "page content\n foo: '' bar: 'im page'" in "_site/jekyll.html"
|
||||
|
||||
@@ -14,24 +14,24 @@ end
|
||||
|
||||
#
|
||||
|
||||
Given(%r!^I have a blank site in "(.*)"$!) do |path|
|
||||
unless File.exist?(path)
|
||||
Given %r{^I have a blank site in "(.*)"$} do |path|
|
||||
if !File.exist?(path)
|
||||
then FileUtils.mkdir_p(path)
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
|
||||
Given(%r!^I do not have a "(.*)" directory$!) do |path|
|
||||
Given %r{^I do not have a "(.*)" directory$} do |path|
|
||||
Paths.test_dir.join(path).directory?
|
||||
end
|
||||
|
||||
#
|
||||
|
||||
Given(%r!^I have an? "(.*)" page(?: with (.*) "(.*)")? that contains "(.*)"$!) do |file, key, value, text|
|
||||
Given %r{^I have an? "(.*)" page(?: with (.*) "(.*)")? that contains "(.*)"$} do |file, key, value, text|
|
||||
File.write(file, Jekyll::Utils.strip_heredoc(<<-DATA))
|
||||
---
|
||||
#{key || "layout"}: #{value || "nil"}
|
||||
#{key || 'layout'}: #{value || 'nil'}
|
||||
---
|
||||
|
||||
#{text}
|
||||
@@ -40,13 +40,13 @@ end
|
||||
|
||||
#
|
||||
|
||||
Given(%r!^I have an? "(.*)" file that contains "(.*)"$!) do |file, text|
|
||||
Given %r{^I have an? "(.*)" file that contains "(.*)"$} do |file, text|
|
||||
File.write(file, text)
|
||||
end
|
||||
|
||||
#
|
||||
|
||||
Given(%r!^I have an? (.*) (layout|theme) that contains "(.*)"$!) do |name, type, text|
|
||||
Given %r{^I have an? (.*) (layout|theme) that contains "(.*)"$} do |name, type, text|
|
||||
folder = type == "layout" ? "_layouts" : "_theme"
|
||||
|
||||
destination_file = Pathname.new(File.join(folder, "#{name}.html"))
|
||||
@@ -56,33 +56,33 @@ end
|
||||
|
||||
#
|
||||
|
||||
Given(%r!^I have an? "(.*)" file with content:$!) do |file, text|
|
||||
Given %r{^I have an? "(.*)" file with content:$} do |file, text|
|
||||
File.write(file, text)
|
||||
end
|
||||
|
||||
#
|
||||
|
||||
Given(%r!^I have an? (.*) directory$!) do |dir|
|
||||
unless File.directory?(dir)
|
||||
Given %r{^I have an? (.*) directory$} do |dir|
|
||||
if !File.directory?(dir)
|
||||
then FileUtils.mkdir_p(dir)
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
|
||||
Given(%r!^I have the following (draft|page|post)s?(?: (in|under) "([^"]+)")?:$!) do |status, direction, folder, table|
|
||||
Given %r{^I have the following (draft|page|post)s?(?: (in|under) "([^"]+)")?:$} do |status, direction, folder, table|
|
||||
table.hashes.each do |input_hash|
|
||||
title = slug(input_hash["title"])
|
||||
ext = input_hash["type"] || "markdown"
|
||||
filename = "#{title}.#{ext}" if %w(draft page).include?(status)
|
||||
filename = filename = "#{title}.#{ext}" if %w(draft page).include?(status)
|
||||
before, after = location(folder, direction)
|
||||
dest_folder = "_drafts" if status == "draft"
|
||||
dest_folder = "_posts" if status == "post"
|
||||
dest_folder = "_posts" if status == "post"
|
||||
dest_folder = "" if status == "page"
|
||||
|
||||
if status == "post"
|
||||
parsed_date = Time.xmlschema(input_hash["date"]) rescue Time.parse(input_hash["date"])
|
||||
filename = "#{parsed_date.strftime("%Y-%m-%d")}-#{title}.#{ext}"
|
||||
parsed_date = Time.xmlschema(input_hash['date']) rescue Time.parse(input_hash['date'])
|
||||
filename = "#{parsed_date.strftime('%Y-%m-%d')}-#{title}.#{ext}"
|
||||
end
|
||||
|
||||
path = File.join(before, dest_folder, after, filename)
|
||||
@@ -92,20 +92,19 @@ end
|
||||
|
||||
#
|
||||
|
||||
Given(%r!^I have a configuration file with "(.*)" set to "(.*)"$!) do |key, value|
|
||||
config = \
|
||||
if source_dir.join("_config.yml").exist?
|
||||
SafeYAML.load_file(source_dir.join("_config.yml"))
|
||||
else
|
||||
{}
|
||||
end
|
||||
Given %r{^I have a configuration file with "(.*)" set to "(.*)"$} do |key, value|
|
||||
config = if source_dir.join("_config.yml").exist?
|
||||
SafeYAML.load_file(source_dir.join("_config.yml"))
|
||||
else
|
||||
{}
|
||||
end
|
||||
config[key] = YAML.load(value)
|
||||
File.write("_config.yml", YAML.dump(config))
|
||||
end
|
||||
|
||||
#
|
||||
|
||||
Given(%r!^I have a configuration file with:$!) do |table|
|
||||
Given %r{^I have a configuration file with:$} do |table|
|
||||
table.hashes.each do |row|
|
||||
step %(I have a configuration file with "#{row["key"]}" set to "#{row["value"]}")
|
||||
end
|
||||
@@ -113,7 +112,7 @@ end
|
||||
|
||||
#
|
||||
|
||||
Given(%r!^I have a configuration file with "([^\"]*)" set to:$!) do |key, table|
|
||||
Given %r{^I have a configuration file with "([^\"]*)" set to:$} do |key, table|
|
||||
File.open("_config.yml", "w") do |f|
|
||||
f.write("#{key}:\n")
|
||||
table.hashes.each do |row|
|
||||
@@ -124,20 +123,20 @@ end
|
||||
|
||||
#
|
||||
|
||||
Given(%r!^I have fixture collections$!) do
|
||||
Given %r{^I have fixture collections$} do
|
||||
FileUtils.cp_r Paths.source_dir.join("test", "source", "_methods"), source_dir
|
||||
FileUtils.cp_r Paths.source_dir.join("test", "source", "_thanksgiving"), source_dir
|
||||
end
|
||||
|
||||
#
|
||||
|
||||
Given(%r!^I wait (\d+) second(s?)$!) do |time, _|
|
||||
Given %r{^I wait (\d+) second(s?)$} do |time, plural|
|
||||
sleep(time.to_f)
|
||||
end
|
||||
|
||||
#
|
||||
|
||||
When(%r!^I run jekyll(.*)$!) do |args|
|
||||
When %r{^I run jekyll(.*)$} do |args|
|
||||
run_jekyll(args)
|
||||
if args.include?("--verbose") || ENV["DEBUG"]
|
||||
$stderr.puts "\n#{jekyll_run_output}\n"
|
||||
@@ -146,16 +145,16 @@ end
|
||||
|
||||
#
|
||||
|
||||
When(%r!^I run bundle(.*)$!) do |args|
|
||||
When %r{^I run bundle(.*)$} do |args|
|
||||
run_bundle(args)
|
||||
if args.include?("--verbose") || ENV["DEBUG"]
|
||||
if args.include?("--verbose") || ENV['DEBUG']
|
||||
$stderr.puts "\n#{jekyll_run_output}\n"
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
|
||||
When(%r!^I change "(.*)" to contain "(.*)"$!) do |file, text|
|
||||
When %r{^I change "(.*)" to contain "(.*)"$} do |file, text|
|
||||
File.open(file, "a") do |f|
|
||||
f.write(text)
|
||||
end
|
||||
@@ -163,13 +162,13 @@ end
|
||||
|
||||
#
|
||||
|
||||
When(%r!^I delete the file "(.*)"$!) do |file|
|
||||
When %r{^I delete the file "(.*)"$} do |file|
|
||||
File.delete(file)
|
||||
end
|
||||
|
||||
#
|
||||
|
||||
Then(%r!^the (.*) directory should +(not )?exist$!) do |dir, negative|
|
||||
Then %r{^the (.*) directory should +(not )?exist$} do |dir, negative|
|
||||
if negative.nil?
|
||||
expect(Pathname.new(dir)).to exist
|
||||
else
|
||||
@@ -178,7 +177,7 @@ Then(%r!^the (.*) directory should +(not )?exist$!) do |dir, negative|
|
||||
end
|
||||
|
||||
#
|
||||
Then(%r!^I should (not )?see "(.*)" in "(.*)"$!) do |negative, text, file|
|
||||
Then %r{^I should (not )?see "(.*)" in "(.*)"$} do |negative, text, file|
|
||||
step %(the "#{file}" file should exist)
|
||||
regexp = Regexp.new(text, Regexp::MULTILINE)
|
||||
if negative.nil? || negative.empty?
|
||||
@@ -190,20 +189,20 @@ end
|
||||
|
||||
#
|
||||
|
||||
Then(%r!^I should see exactly "(.*)" in "(.*)"$!) do |text, file|
|
||||
Then %r{^I should see exactly "(.*)" in "(.*)"$} do |text, file|
|
||||
step %(the "#{file}" file should exist)
|
||||
expect(file_contents(file).strip).to eq text
|
||||
end
|
||||
|
||||
#
|
||||
|
||||
Then(%r!^I should see escaped "(.*)" in "(.*)"$!) do |text, file|
|
||||
Then %r{^I should see escaped "(.*)" in "(.*)"$} do |text, file|
|
||||
step %(I should see "#{Regexp.escape(text)}" in "#{file}")
|
||||
end
|
||||
|
||||
#
|
||||
|
||||
Then(%r!^the "(.*)" file should +(not )?exist$!) do |file, negative|
|
||||
Then %r{^the "(.*)" file should +(not )?exist$} do |file, negative|
|
||||
if negative.nil?
|
||||
expect(Pathname.new(file)).to exist
|
||||
else
|
||||
@@ -213,19 +212,19 @@ end
|
||||
|
||||
#
|
||||
|
||||
Then(%r!^I should see today's time in "(.*)"$!) do |file|
|
||||
Then %r{^I should see today's time in "(.*)"$} do |file|
|
||||
step %(I should see "#{seconds_agnostic_time(Time.now)}" in "#{file}")
|
||||
end
|
||||
|
||||
#
|
||||
|
||||
Then(%r!^I should see today's date in "(.*)"$!) do |file|
|
||||
step %(I should see "#{Date.today}" in "#{file}")
|
||||
Then %r{^I should see today's date in "(.*)"$} do |file|
|
||||
step %(I should see "#{Date.today.to_s}" in "#{file}")
|
||||
end
|
||||
|
||||
#
|
||||
|
||||
Then(%r!^I should (not )?see "(.*)" in the build output$!) do |negative, text|
|
||||
Then %r{^I should (not )?see "(.*)" in the build output$} do |negative, text|
|
||||
if negative.nil? || negative.empty?
|
||||
expect(jekyll_run_output).to match Regexp.new(text)
|
||||
else
|
||||
@@ -235,12 +234,12 @@ end
|
||||
|
||||
#
|
||||
|
||||
Then(%r!^I should get a zero exit(?:\-| )status$!) do
|
||||
Then %r{^I should get a zero exit(?:\-| )status$} do
|
||||
step %(I should see "EXIT STATUS: 0" in the build output)
|
||||
end
|
||||
|
||||
#
|
||||
|
||||
Then(%r!^I should get a non-zero exit(?:\-| )status$!) do
|
||||
Then %r{^I should get a non-zero exit(?:\-| )status$} do
|
||||
step %(I should not see "EXIT STATUS: 0" in the build output)
|
||||
end
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
require "fileutils"
|
||||
require "colorator"
|
||||
require "cucumber/formatter/console"
|
||||
require "cucumber/formatter/io"
|
||||
require 'fileutils'
|
||||
require 'colorator'
|
||||
require 'cucumber/formatter/console'
|
||||
require 'cucumber/formatter/io'
|
||||
|
||||
module Jekyll
|
||||
module Cucumber
|
||||
@@ -17,7 +17,7 @@ module Jekyll
|
||||
:undefined => "\u2718".red,
|
||||
:passed => "\u2714".green,
|
||||
:skipped => "\u203D".blue
|
||||
}.freeze
|
||||
}
|
||||
|
||||
#
|
||||
|
||||
@@ -30,12 +30,11 @@ module Jekyll
|
||||
@options = options
|
||||
@exceptions = []
|
||||
@indent = 0
|
||||
@timings = {}
|
||||
end
|
||||
|
||||
#
|
||||
|
||||
def before_features(_features)
|
||||
def before_features(features)
|
||||
print_profile_information
|
||||
end
|
||||
|
||||
@@ -43,49 +42,33 @@ module Jekyll
|
||||
|
||||
def after_features(features)
|
||||
@io.puts
|
||||
print_worst_offenders
|
||||
print_summary(features)
|
||||
end
|
||||
|
||||
#
|
||||
|
||||
def before_feature(_feature)
|
||||
def before_feature(feature)
|
||||
@exceptions = []
|
||||
@indent = 0
|
||||
end
|
||||
|
||||
#
|
||||
|
||||
def feature_element_timing_key(feature_element)
|
||||
"\"#{feature_element.name.to_s.sub("Scenario: ", "")}\" (#{feature_element.location})"
|
||||
end
|
||||
def tag_name(tag_name); end
|
||||
def comment_line(comment_line); end
|
||||
def after_feature_element(feature_element); end
|
||||
def after_tags(tags); end
|
||||
|
||||
#
|
||||
|
||||
def before_feature_element(feature_element)
|
||||
@indent = 2
|
||||
@scenario_indent = 2
|
||||
@timings[feature_element_timing_key(feature_element)] = Time.now
|
||||
end
|
||||
|
||||
#
|
||||
|
||||
def after_feature_element(feature_element)
|
||||
@timings[feature_element_timing_key(feature_element)] = Time.now - @timings[feature_element_timing_key(feature_element)]
|
||||
@io.print " (#{@timings[feature_element_timing_key(feature_element)]}s)"
|
||||
end
|
||||
|
||||
#
|
||||
|
||||
def tag_name(tag_name); end
|
||||
|
||||
def comment_line(comment_line); end
|
||||
|
||||
def after_tags(tags); end
|
||||
|
||||
#
|
||||
|
||||
def before_background(_background)
|
||||
def before_background(background)
|
||||
@scenario_indent = 2
|
||||
@in_background = true
|
||||
@indent = 2
|
||||
@@ -93,15 +76,15 @@ module Jekyll
|
||||
|
||||
#
|
||||
|
||||
def after_background(_background)
|
||||
def after_background(background)
|
||||
@in_background = nil
|
||||
end
|
||||
|
||||
#
|
||||
|
||||
def background_name(keyword, name, source_line, indent)
|
||||
def background_name(keyword, name, source_line, indend)
|
||||
print_feature_element_name(
|
||||
keyword, name, source_line, indent
|
||||
keyword, name, source_line, indend
|
||||
)
|
||||
end
|
||||
|
||||
@@ -121,9 +104,8 @@ module Jekyll
|
||||
|
||||
#
|
||||
|
||||
# rubocop:disable Metrics/ParameterLists
|
||||
def before_step_result(_keyword, _step_match, _multiline_arg, status, exception, \
|
||||
_source_indent, background, _file_colon_line)
|
||||
def before_step_result(keyword, step_match, multiline_arg, status, exception, \
|
||||
source_indent, background, file_colon_line)
|
||||
|
||||
@hide_this_step = false
|
||||
if exception
|
||||
@@ -145,11 +127,10 @@ module Jekyll
|
||||
|
||||
#
|
||||
|
||||
def step_name(_keyword, _step_match, status, _source_indent, _background, _file_colon_line)
|
||||
def step_name(keyword, step_match, status, source_indent, background, file_colon_line)
|
||||
@io.print CHARS[status]
|
||||
@io.print " "
|
||||
end
|
||||
# rubocop:enable Metrics/ParameterLists
|
||||
|
||||
#
|
||||
|
||||
@@ -172,7 +153,7 @@ module Jekyll
|
||||
#
|
||||
|
||||
private
|
||||
def print_feature_element_name(keyword, name, source_line, _indent)
|
||||
def print_feature_element_name(keyword, name, source_line, indent)
|
||||
@io.puts
|
||||
|
||||
names = name.empty? ? [name] : name.each_line.to_a
|
||||
@@ -192,17 +173,6 @@ module Jekyll
|
||||
|
||||
#
|
||||
|
||||
def print_worst_offenders
|
||||
@io.puts
|
||||
@io.puts "Worst offenders:"
|
||||
@timings.sort_by { |_f, t| -t }.take(10).each do |(f, t)|
|
||||
@io.puts " #{t}s for #{f}"
|
||||
end
|
||||
@io.puts
|
||||
end
|
||||
|
||||
#
|
||||
|
||||
def print_summary(features)
|
||||
@io.puts
|
||||
print_stats(features, @options)
|
||||
|
||||
@@ -7,36 +7,31 @@ require "safe_yaml/load"
|
||||
class Paths
|
||||
SOURCE_DIR = Pathname.new(File.expand_path("../..", __dir__))
|
||||
def self.test_dir; source_dir.join("tmp", "jekyll"); end
|
||||
|
||||
def self.output_file; test_dir.join("jekyll_output.txt"); end
|
||||
|
||||
def self.status_file; test_dir.join("jekyll_status.txt"); end
|
||||
|
||||
def self.jekyll_bin; source_dir.join("exe", "jekyll"); end
|
||||
|
||||
def self.jekyll_bin; source_dir.join("bin", "jekyll"); end
|
||||
def self.source_dir; SOURCE_DIR; end
|
||||
end
|
||||
|
||||
#
|
||||
|
||||
def file_content_from_hash(input_hash)
|
||||
matter_hash = input_hash.reject { |k, _v| k == "content" }
|
||||
matter = matter_hash.map do |k, v|
|
||||
"#{k}: #{v}\n"
|
||||
matter_hash = input_hash.reject { |k, v| k == "content" }
|
||||
matter = matter_hash.map do |k, v| "#{k}: #{v}\n"
|
||||
end
|
||||
|
||||
matter = matter.join.chomp
|
||||
content = \
|
||||
if !input_hash["input"] || !input_hash["filter"]
|
||||
then input_hash["content"]
|
||||
else "{{ #{input_hash["input"]} | " \
|
||||
"#{input_hash["filter"]} }}"
|
||||
end
|
||||
if !input_hash['input'] || !input_hash['filter']
|
||||
then input_hash['content']
|
||||
else "{{ #{input_hash['input']} | " \
|
||||
"#{input_hash['filter']} }}"
|
||||
end
|
||||
|
||||
Jekyll::Utils.strip_heredoc(<<-EOF)
|
||||
---
|
||||
#{matter.gsub(
|
||||
%r!\n!, "\n "
|
||||
/\n/, "\n "
|
||||
)}
|
||||
---
|
||||
#{content}
|
||||
@@ -83,7 +78,7 @@ end
|
||||
#
|
||||
|
||||
def run_bundle(args)
|
||||
run_in_shell("bundle", *args.strip.split(" "))
|
||||
run_in_shell("bundle", *args.strip.split(' '))
|
||||
end
|
||||
|
||||
#
|
||||
@@ -96,13 +91,14 @@ end
|
||||
|
||||
#
|
||||
|
||||
# rubocop:disable Metrics/AbcSize
|
||||
def run_in_shell(*args)
|
||||
i, o, e, p = Open3.popen3(*args)
|
||||
out = o.read.strip
|
||||
err = e.read.strip
|
||||
|
||||
[i, o, e].each(&:close)
|
||||
[i, o, e].each do |m|
|
||||
m.close
|
||||
end
|
||||
|
||||
File.write(Paths.status_file, p.value.exitstatus)
|
||||
File.open(Paths.output_file, "wb") do |f|
|
||||
@@ -114,14 +110,13 @@ def run_in_shell(*args)
|
||||
|
||||
p.value
|
||||
end
|
||||
# rubocop:enable Metrics/AbcSize
|
||||
|
||||
#
|
||||
|
||||
def slug(title = nil)
|
||||
if !title
|
||||
then Time.now.strftime("%s%9N") # nanoseconds since the Epoch
|
||||
else title.downcase.gsub(%r![^\w]!, " ").strip.gsub(%r!\s+!, "-")
|
||||
else title.downcase.gsub(/[^\w]/, " ").strip.gsub(/\s+/, '-')
|
||||
end
|
||||
end
|
||||
|
||||
@@ -129,12 +124,12 @@ end
|
||||
|
||||
def location(folder, direction)
|
||||
if folder
|
||||
before = folder if direction == "in"
|
||||
before = folder if direction == "in"
|
||||
after = folder if direction == "under"
|
||||
end
|
||||
|
||||
[before || ".",
|
||||
after || "."]
|
||||
[before || '.',
|
||||
after || '.']
|
||||
end
|
||||
|
||||
#
|
||||
@@ -154,13 +149,13 @@ def seconds_agnostic_datetime(datetime = Time.now)
|
||||
"#{time}:\\d{2}",
|
||||
Regexp.escape(zone)
|
||||
] \
|
||||
.join("\\ ")
|
||||
.join("\\ ")
|
||||
end
|
||||
|
||||
#
|
||||
|
||||
def seconds_agnostic_time(time)
|
||||
time = time.strftime("%H:%M:%S") if time.is_a?(Time)
|
||||
hour, minutes, = time.split(":")
|
||||
hour, minutes, _ = time.split(":")
|
||||
"#{hour}:#{minutes}"
|
||||
end
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
Feature: Writing themes
|
||||
As a hacker who likes to share my expertise
|
||||
I want to be able to make a gemified theme
|
||||
In order to share my awesome style skillz with other Jekyllites
|
||||
|
||||
Scenario: Generating a new theme scaffold
|
||||
When I run jekyll new-theme my-cool-theme
|
||||
Then I should get a zero exit status
|
||||
And the my-cool-theme directory should exist
|
||||
|
||||
Scenario: Generating a new theme scaffold with a code of conduct
|
||||
When I run jekyll new-theme my-cool-theme --code-of-conduct
|
||||
Then I should get a zero exit status
|
||||
And the my-cool-theme directory should exist
|
||||
And the "my-cool-theme/CODE_OF_CONDUCT.md" file should exist
|
||||
|
||||
Scenario: A theme with SCSS
|
||||
Given I have a configuration file with "theme" set to "test-theme"
|
||||
And I have a css directory
|
||||
And I have a "css/main.scss" page that contains "@import 'style';"
|
||||
When I run jekyll build
|
||||
Then I should get a zero exit status
|
||||
And the _site directory should exist
|
||||
And I should see ".sample {\n color: black; }" in "_site/css/main.css"
|
||||
|
||||
Scenario: A theme with an include
|
||||
Given I have a configuration file with "theme" set to "test-theme"
|
||||
And I have an _includes directory
|
||||
And I have an "_includes/in_project.html" file that contains "I'm in the project."
|
||||
And I have an "index.html" page that contains "{% include in_project.html %} {% include include.html %}"
|
||||
When I run jekyll build
|
||||
Then I should get a zero exit status
|
||||
And the _site directory should exist
|
||||
And I should see "I'm in the project." in "_site/index.html"
|
||||
And I should see "<span class=\"sample\">include.html from test-theme</span>" in "_site/index.html"
|
||||
|
||||
Scenario: A theme with a layout
|
||||
Given I have a configuration file with "theme" set to "test-theme"
|
||||
And I have an _layouts directory
|
||||
And I have an "_layouts/post.html" file that contains "post.html from the project: {{ content }}"
|
||||
And I have an "index.html" page with layout "default" that contains "I'm content."
|
||||
And I have a "post.html" page with layout "post" that contains "I'm more content."
|
||||
When I run jekyll build
|
||||
Then I should get a zero exit status
|
||||
And the _site directory should exist
|
||||
And I should see "default.html from test-theme: I'm content." in "_site/index.html"
|
||||
And I should see "post.html from the project: I'm more content." in "_site/post.html"
|
||||
|
||||
Scenario: Complicated site that puts it all together
|
||||
Given I have a configuration file with "theme" set to "test-theme"
|
||||
And I have a _posts directory
|
||||
And I have the following posts:
|
||||
| title | date | layout | content |
|
||||
| entry1 | 2016-04-21 | post | I am using a local layout. {% include include.html %} |
|
||||
| entry2 | 2016-04-21 | default | I am using a themed layout. {% include include.html %} {% include in_project.html %} |
|
||||
And I have a _layouts directory
|
||||
And I have a "_layouts/post.html" page with layout "default" that contains "I am a post layout! {{ content }}"
|
||||
And I have an _includes directory
|
||||
And I have an "_includes/in_project.html" file that contains "I am in the project, not the theme."
|
||||
When I run jekyll build
|
||||
Then I should get a zero exit status
|
||||
And the _site directory should exist
|
||||
And I should see "I am in the project, not the theme." in "_site/2016/04/21/entry2.html"
|
||||
And I should see "<span class=\"sample\">include.html from test-theme</span>" in "_site/2016/04/21/entry2.html"
|
||||
And I should see "default.html from test-theme:" in "_site/2016/04/21/entry2.html"
|
||||
And I should see "I am using a themed layout." in "_site/2016/04/21/entry2.html"
|
||||
And I should not see "I am a post layout!" in "_site/2016/04/21/entry2.html"
|
||||
And I should not see "I am in the project, not the theme." in "_site/2016/04/21/entry1.html"
|
||||
And I should see "<span class=\"sample\">include.html from test-theme</span>" in "_site/2016/04/21/entry1.html"
|
||||
And I should see "default.html from test-theme:" in "_site/2016/04/21/entry1.html"
|
||||
And I should see "I am using a local layout." in "_site/2016/04/21/entry1.html"
|
||||
And I should see "I am a post layout!" in "_site/2016/04/21/entry1.html"
|
||||
@@ -21,9 +21,8 @@ Gem::Specification.new do |s|
|
||||
s.homepage = 'https://github.com/jekyll/jekyll'
|
||||
|
||||
all_files = `git ls-files -z`.split("\x0")
|
||||
s.files = all_files.grep(%r{^(exe|lib)/|^.rubocop.yml$})
|
||||
s.executables = all_files.grep(%r{^exe/}) { |f| File.basename(f) }
|
||||
s.bindir = "exe"
|
||||
s.files = all_files.grep(%r{^(bin|lib)/|^.rubocop.yml$})
|
||||
s.executables = all_files.grep(%r{^bin/}) { |f| File.basename(f) }
|
||||
s.require_paths = ['lib']
|
||||
|
||||
s.rdoc_options = ['--charset=UTF-8']
|
||||
@@ -33,9 +32,8 @@ Gem::Specification.new do |s|
|
||||
s.add_runtime_dependency('kramdown', '~> 1.3')
|
||||
s.add_runtime_dependency('mercenary', '~> 0.3.3')
|
||||
s.add_runtime_dependency('safe_yaml', '~> 1.0')
|
||||
s.add_runtime_dependency('colorator', '~> 1.0')
|
||||
s.add_runtime_dependency('colorator', '~> 0.1')
|
||||
s.add_runtime_dependency('rouge', '~> 1.7')
|
||||
s.add_runtime_dependency('jekyll-sass-converter', '~> 1.0')
|
||||
s.add_runtime_dependency('jekyll-watch', '~> 1.1')
|
||||
s.add_runtime_dependency("pathutil", "~> 0.9")
|
||||
end
|
||||
|
||||
155
lib/jekyll.rb
155
lib/jekyll.rb
@@ -6,80 +6,77 @@ $LOAD_PATH.unshift File.dirname(__FILE__) # For use/testing when no gem is insta
|
||||
#
|
||||
# Returns nothing.
|
||||
def require_all(path)
|
||||
glob = File.join(File.dirname(__FILE__), path, "*.rb")
|
||||
Dir[glob].sort.each do |f|
|
||||
glob = File.join(File.dirname(__FILE__), path, '*.rb')
|
||||
Dir[glob].each do |f|
|
||||
require f
|
||||
end
|
||||
end
|
||||
|
||||
# rubygems
|
||||
require "rubygems"
|
||||
require 'rubygems'
|
||||
|
||||
# stdlib
|
||||
require "pathutil"
|
||||
require "forwardable"
|
||||
require "fileutils"
|
||||
require "time"
|
||||
require "English"
|
||||
require "pathname"
|
||||
require "logger"
|
||||
require "set"
|
||||
require 'forwardable'
|
||||
require 'fileutils'
|
||||
require 'time'
|
||||
require 'English'
|
||||
require 'pathname'
|
||||
require 'logger'
|
||||
require 'set'
|
||||
|
||||
# 3rd party
|
||||
require "safe_yaml/load"
|
||||
require "liquid"
|
||||
require "kramdown"
|
||||
require "colorator"
|
||||
require 'safe_yaml/load'
|
||||
require 'liquid'
|
||||
require 'kramdown'
|
||||
require 'colorator'
|
||||
|
||||
SafeYAML::OPTIONS[:suppress_warnings] = true
|
||||
|
||||
module Jekyll
|
||||
# internal requires
|
||||
autoload :Cleaner, "jekyll/cleaner"
|
||||
autoload :Collection, "jekyll/collection"
|
||||
autoload :Configuration, "jekyll/configuration"
|
||||
autoload :Convertible, "jekyll/convertible"
|
||||
autoload :Deprecator, "jekyll/deprecator"
|
||||
autoload :Document, "jekyll/document"
|
||||
autoload :Draft, "jekyll/draft"
|
||||
autoload :EntryFilter, "jekyll/entry_filter"
|
||||
autoload :Errors, "jekyll/errors"
|
||||
autoload :Excerpt, "jekyll/excerpt"
|
||||
autoload :External, "jekyll/external"
|
||||
autoload :FrontmatterDefaults, "jekyll/frontmatter_defaults"
|
||||
autoload :Hooks, "jekyll/hooks"
|
||||
autoload :Layout, "jekyll/layout"
|
||||
autoload :CollectionReader, "jekyll/readers/collection_reader"
|
||||
autoload :DataReader, "jekyll/readers/data_reader"
|
||||
autoload :LayoutReader, "jekyll/readers/layout_reader"
|
||||
autoload :PostReader, "jekyll/readers/post_reader"
|
||||
autoload :PageReader, "jekyll/readers/page_reader"
|
||||
autoload :StaticFileReader, "jekyll/readers/static_file_reader"
|
||||
autoload :LogAdapter, "jekyll/log_adapter"
|
||||
autoload :Page, "jekyll/page"
|
||||
autoload :PluginManager, "jekyll/plugin_manager"
|
||||
autoload :Publisher, "jekyll/publisher"
|
||||
autoload :Reader, "jekyll/reader"
|
||||
autoload :Regenerator, "jekyll/regenerator"
|
||||
autoload :RelatedPosts, "jekyll/related_posts"
|
||||
autoload :Renderer, "jekyll/renderer"
|
||||
autoload :LiquidRenderer, "jekyll/liquid_renderer"
|
||||
autoload :Site, "jekyll/site"
|
||||
autoload :StaticFile, "jekyll/static_file"
|
||||
autoload :Stevenson, "jekyll/stevenson"
|
||||
autoload :Theme, "jekyll/theme"
|
||||
autoload :ThemeBuilder, "jekyll/theme_builder"
|
||||
autoload :URL, "jekyll/url"
|
||||
autoload :Utils, "jekyll/utils"
|
||||
autoload :VERSION, "jekyll/version"
|
||||
autoload :Cleaner, 'jekyll/cleaner'
|
||||
autoload :Collection, 'jekyll/collection'
|
||||
autoload :Configuration, 'jekyll/configuration'
|
||||
autoload :Convertible, 'jekyll/convertible'
|
||||
autoload :Deprecator, 'jekyll/deprecator'
|
||||
autoload :Document, 'jekyll/document'
|
||||
autoload :Draft, 'jekyll/draft'
|
||||
autoload :EntryFilter, 'jekyll/entry_filter'
|
||||
autoload :Errors, 'jekyll/errors'
|
||||
autoload :Excerpt, 'jekyll/excerpt'
|
||||
autoload :External, 'jekyll/external'
|
||||
autoload :Filters, 'jekyll/filters'
|
||||
autoload :FrontmatterDefaults, 'jekyll/frontmatter_defaults'
|
||||
autoload :Hooks, 'jekyll/hooks'
|
||||
autoload :Layout, 'jekyll/layout'
|
||||
autoload :CollectionReader, 'jekyll/readers/collection_reader'
|
||||
autoload :DataReader, 'jekyll/readers/data_reader'
|
||||
autoload :LayoutReader, 'jekyll/readers/layout_reader'
|
||||
autoload :PostReader, 'jekyll/readers/post_reader'
|
||||
autoload :PageReader, 'jekyll/readers/page_reader'
|
||||
autoload :StaticFileReader, 'jekyll/readers/static_file_reader'
|
||||
autoload :LogAdapter, 'jekyll/log_adapter'
|
||||
autoload :Page, 'jekyll/page'
|
||||
autoload :PluginManager, 'jekyll/plugin_manager'
|
||||
autoload :Publisher, 'jekyll/publisher'
|
||||
autoload :Reader, 'jekyll/reader'
|
||||
autoload :Regenerator, 'jekyll/regenerator'
|
||||
autoload :RelatedPosts, 'jekyll/related_posts'
|
||||
autoload :Renderer, 'jekyll/renderer'
|
||||
autoload :LiquidRenderer, 'jekyll/liquid_renderer'
|
||||
autoload :Site, 'jekyll/site'
|
||||
autoload :StaticFile, 'jekyll/static_file'
|
||||
autoload :Stevenson, 'jekyll/stevenson'
|
||||
autoload :URL, 'jekyll/url'
|
||||
autoload :Utils, 'jekyll/utils'
|
||||
autoload :VERSION, 'jekyll/version'
|
||||
|
||||
# extensions
|
||||
require "jekyll/plugin"
|
||||
require "jekyll/converter"
|
||||
require "jekyll/generator"
|
||||
require "jekyll/command"
|
||||
require "jekyll/liquid_extensions"
|
||||
require "jekyll/filters"
|
||||
require 'jekyll/plugin'
|
||||
require 'jekyll/converter'
|
||||
require 'jekyll/generator'
|
||||
require 'jekyll/command'
|
||||
require 'jekyll/liquid_extensions'
|
||||
|
||||
class << self
|
||||
# Public: Tells you which Jekyll environment you are building in so you can skip tasks
|
||||
@@ -94,21 +91,22 @@ module Jekyll
|
||||
# options with anything in _config.yml, and adding the given options on top.
|
||||
#
|
||||
# override - A Hash of config directives that override any options in both
|
||||
# the defaults and the config file.
|
||||
# See Jekyll::Configuration::DEFAULTS for a
|
||||
# the defaults and the config file. See Jekyll::Configuration::DEFAULTS for a
|
||||
# list of option names and their defaults.
|
||||
#
|
||||
# Returns the final configuration Hash.
|
||||
def configuration(override = {})
|
||||
config = Configuration.new
|
||||
unless override.delete("skip_config_files")
|
||||
config = Configuration[Configuration::DEFAULTS]
|
||||
override = Configuration[override].stringify_keys
|
||||
unless override.delete('skip_config_files')
|
||||
config = config.read_config_files(config.config_files(override))
|
||||
end
|
||||
|
||||
# Merge DEFAULTS < _config.yml < override
|
||||
Configuration.from(Utils.deep_merge_hashes(config, override)).tap do |obj|
|
||||
set_timezone(obj["timezone"]) if obj["timezone"]
|
||||
end
|
||||
config = Utils.deep_merge_hashes(config, override).stringify_keys
|
||||
set_timezone(config['timezone']) if config['timezone']
|
||||
|
||||
config
|
||||
end
|
||||
|
||||
# Public: Set the TZ environment variable to use the timezone specified
|
||||
@@ -116,11 +114,9 @@ module Jekyll
|
||||
# timezone - the IANA Time Zone
|
||||
#
|
||||
# Returns nothing
|
||||
# rubocop:disable Style/AccessorMethodName
|
||||
def set_timezone(timezone)
|
||||
ENV["TZ"] = timezone
|
||||
ENV['TZ'] = timezone
|
||||
end
|
||||
# rubocop:enable Style/AccessorMethodName
|
||||
|
||||
# Public: Fetch the logger instance for this Jekyll process.
|
||||
#
|
||||
@@ -157,11 +153,11 @@ module Jekyll
|
||||
def sanitized_path(base_directory, questionable_path)
|
||||
return base_directory if base_directory.eql?(questionable_path)
|
||||
|
||||
questionable_path.insert(0, "/") if questionable_path.start_with?("~")
|
||||
questionable_path.insert(0, '/') if questionable_path.start_with?('~')
|
||||
clean_path = File.expand_path(questionable_path, "/")
|
||||
clean_path.sub!(%r!\A\w:/!, "/")
|
||||
clean_path.sub!(/\A\w\:\//, '/')
|
||||
|
||||
if clean_path.start_with?(base_directory.sub(%r!\A\w:/!, "/"))
|
||||
if clean_path.start_with?(base_directory.sub(/\A\w\:\//, '/'))
|
||||
clean_path
|
||||
else
|
||||
File.join(base_directory, clean_path)
|
||||
@@ -169,17 +165,16 @@ module Jekyll
|
||||
end
|
||||
|
||||
# Conditional optimizations
|
||||
Jekyll::External.require_if_present("liquid-c")
|
||||
Jekyll::External.require_if_present('liquid-c')
|
||||
end
|
||||
end
|
||||
|
||||
require "jekyll/drops/drop"
|
||||
require "jekyll/drops/document_drop"
|
||||
require_all "jekyll/commands"
|
||||
require_all "jekyll/converters"
|
||||
require_all "jekyll/converters/markdown"
|
||||
require_all "jekyll/drops"
|
||||
require_all "jekyll/generators"
|
||||
require_all "jekyll/tags"
|
||||
require_all 'jekyll/commands'
|
||||
require_all 'jekyll/converters'
|
||||
require_all 'jekyll/converters/markdown'
|
||||
require_all 'jekyll/drops'
|
||||
require_all 'jekyll/generators'
|
||||
require_all 'jekyll/tags'
|
||||
|
||||
require "jekyll-sass-converter"
|
||||
require 'jekyll-sass-converter'
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
require "set"
|
||||
require 'set'
|
||||
|
||||
module Jekyll
|
||||
# Handles the cleanup of a site's destination before it is built.
|
||||
class Cleaner
|
||||
HIDDEN_FILE_REGEX = %r!\/\.{1,2}$!
|
||||
HIDDEN_FILE_REGEX = /\/\.{1,2}$/
|
||||
attr_reader :site
|
||||
|
||||
def initialize(site)
|
||||
@@ -32,8 +32,7 @@ module Jekyll
|
||||
[site.regenerator.metadata_file]
|
||||
end
|
||||
|
||||
# Private: The list of existing files, apart from those included in
|
||||
# keep_files and hidden files.
|
||||
# Private: The list of existing files, apart from those included in keep_files and hidden files.
|
||||
#
|
||||
# Returns a Set with the file paths
|
||||
def existing_files
|
||||
@@ -78,16 +77,15 @@ module Jekyll
|
||||
end
|
||||
end
|
||||
|
||||
# Private: The list of existing files that will be replaced by a directory
|
||||
# during build
|
||||
# Private: The list of existing files that will be replaced by a directory during build
|
||||
#
|
||||
# Returns a Set with the file paths
|
||||
def replaced_files
|
||||
new_dirs.select { |dir| File.file?(dir) }.to_set
|
||||
end
|
||||
|
||||
# Private: The list of directories that need to be kept because they are
|
||||
# parent directories of files specified in keep_files
|
||||
# Private: The list of directories that need to be kept because they are parent directories
|
||||
# of files specified in keep_files
|
||||
#
|
||||
# Returns a Set with the directory paths
|
||||
def keep_dirs
|
||||
@@ -97,12 +95,12 @@ module Jekyll
|
||||
# Private: Creates a regular expression from the config's keep_files array
|
||||
#
|
||||
# Examples
|
||||
# ['.git','.svn'] with site.dest "/myblog/_site" creates
|
||||
# ['.git','.svn'] with site.dest "/myblog/_site" creates
|
||||
# the following regex: /\A\/myblog\/_site\/(\.git|\/.svn)/
|
||||
#
|
||||
# Returns the regular expression
|
||||
def keep_file_regex
|
||||
%r!\A#{Regexp.quote(site.dest)}\/(#{Regexp.union(site.keep_files).source})!
|
||||
/\A#{Regexp.quote(site.dest)}\/(#{Regexp.union(site.keep_files).source})/
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -32,8 +32,7 @@ module Jekyll
|
||||
# Override of method_missing to check in @data for the key.
|
||||
def method_missing(method, *args, &blck)
|
||||
if docs.respond_to?(method.to_sym)
|
||||
Jekyll.logger.warn "Deprecation:", "#{label}.#{method} should be changed to" \
|
||||
"#{label}.docs.#{method}."
|
||||
Jekyll.logger.warn "Deprecation:", "#{label}.#{method} should be changed to #{label}.docs.#{method}."
|
||||
Jekyll.logger.warn "", "Called by #{caller.first}."
|
||||
docs.public_send(method.to_sym, *args, &blck)
|
||||
else
|
||||
@@ -65,10 +64,8 @@ module Jekyll
|
||||
Jekyll.logger.debug "Skipped From Publishing:", doc.relative_path
|
||||
end
|
||||
else
|
||||
relative_dir = Jekyll.sanitized_path(relative_directory,
|
||||
File.dirname(file_path)).chomp("/.")
|
||||
files << StaticFile.new(site, site.source, relative_dir,
|
||||
File.basename(full_path), self)
|
||||
relative_dir = Jekyll.sanitized_path(relative_directory, File.dirname(file_path)).chomp("/.")
|
||||
files << StaticFile.new(site, site.source, relative_dir, File.basename(full_path), self)
|
||||
end
|
||||
end
|
||||
docs.sort!
|
||||
@@ -82,7 +79,7 @@ module Jekyll
|
||||
return [] unless exists?
|
||||
@entries ||=
|
||||
Utils.safe_glob(collection_dir, ["**", "*"]).map do |entry|
|
||||
entry["#{collection_dir}/"] = ""
|
||||
entry["#{collection_dir}/"] = ''
|
||||
entry
|
||||
end
|
||||
end
|
||||
@@ -97,7 +94,7 @@ module Jekyll
|
||||
Dir.chdir(directory) do
|
||||
entry_filter.filter(entries).reject do |f|
|
||||
path = collection_dir(f)
|
||||
File.directory?(path) || entry_filter.symlink?(f)
|
||||
File.directory?(path) || (File.symlink?(f) && site.safe)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -138,7 +135,7 @@ module Jekyll
|
||||
# Returns false if the directory doesn't exist or if it's a symlink
|
||||
# and we're in safe mode.
|
||||
def exists?
|
||||
File.directory?(directory) && !entry_filter.symlink?(directory)
|
||||
File.directory?(directory) && !(File.symlink?(directory) && site.safe)
|
||||
end
|
||||
|
||||
# The entry filter for this collection.
|
||||
@@ -164,7 +161,7 @@ module Jekyll
|
||||
#
|
||||
# Returns a sanitized version of the label.
|
||||
def sanitize_label(label)
|
||||
label.gsub(/[^a-z0-9_\-\.]/i, "")
|
||||
label.gsub(/[^a-z0-9_\-\.]/i, '')
|
||||
end
|
||||
|
||||
# Produce a representation of this Collection for use in Liquid.
|
||||
@@ -182,14 +179,14 @@ module Jekyll
|
||||
#
|
||||
# Returns true if the 'write' metadata is true, false otherwise.
|
||||
def write?
|
||||
!!metadata.fetch("output", false)
|
||||
!!metadata.fetch('output', false)
|
||||
end
|
||||
|
||||
# The URL template to render collection's documents at.
|
||||
#
|
||||
# Returns the URL template to render collection's documents at.
|
||||
def url_template
|
||||
@url_template ||= metadata.fetch("permalink") do
|
||||
@url_template ||= metadata.fetch('permalink') do
|
||||
Utils.add_permalink_suffix("/:collection/:path", site.permalink_style)
|
||||
end
|
||||
end
|
||||
@@ -198,8 +195,8 @@ module Jekyll
|
||||
#
|
||||
# Returns the metadata for this collection
|
||||
def extract_metadata
|
||||
if site.config["collections"].is_a?(Hash)
|
||||
site.config["collections"][label] || {}
|
||||
if site.config['collections'].is_a?(Hash)
|
||||
site.config['collections'][label] || {}
|
||||
else
|
||||
{}
|
||||
end
|
||||
|
||||
@@ -46,23 +46,19 @@ module Jekyll
|
||||
#
|
||||
# Returns nothing
|
||||
def add_build_options(c)
|
||||
c.option "config", "--config CONFIG_FILE[,CONFIG_FILE2,...]",
|
||||
Array, "Custom configuration file"
|
||||
c.option "destination", "-d", "--destination DESTINATION",
|
||||
"The current folder will be generated into DESTINATION"
|
||||
c.option "source", "-s", "--source SOURCE", "Custom source directory"
|
||||
c.option "future", "--future", "Publishes posts with a future date"
|
||||
c.option "limit_posts", "--limit_posts MAX_POSTS", Integer,
|
||||
"Limits the number of posts to parse and publish"
|
||||
c.option "watch", "-w", "--[no-]watch", "Watch for changes and rebuild"
|
||||
c.option "force_polling", "--force_polling", "Force watch to use polling"
|
||||
c.option "lsi", "--lsi", "Use LSI for improved related posts"
|
||||
c.option "show_drafts", "-D", "--drafts", "Render posts in the _drafts folder"
|
||||
c.option "unpublished", "--unpublished",
|
||||
"Render posts that were marked as unpublished"
|
||||
c.option "quiet", "-q", "--quiet", "Silence output."
|
||||
c.option "verbose", "-V", "--verbose", "Print verbose output."
|
||||
c.option "incremental", "-I", "--incremental", "Enable incremental rebuild."
|
||||
c.option 'config', '--config CONFIG_FILE[,CONFIG_FILE2,...]', Array, 'Custom configuration file'
|
||||
c.option 'destination', '-d', '--destination DESTINATION', 'The current folder will be generated into DESTINATION'
|
||||
c.option 'source', '-s', '--source SOURCE', 'Custom source directory'
|
||||
c.option 'future', '--future', 'Publishes posts with a future date'
|
||||
c.option 'limit_posts', '--limit_posts MAX_POSTS', Integer, 'Limits the number of posts to parse and publish'
|
||||
c.option 'watch', '-w', '--[no-]watch', 'Watch for changes and rebuild'
|
||||
c.option 'force_polling', '--force_polling', 'Force watch to use polling'
|
||||
c.option 'lsi', '--lsi', 'Use LSI for improved related posts'
|
||||
c.option 'show_drafts', '-D', '--drafts', 'Render posts in the _drafts folder'
|
||||
c.option 'unpublished', '--unpublished', 'Render posts that were marked as unpublished'
|
||||
c.option 'quiet', '-q', '--quiet', 'Silence output.'
|
||||
c.option 'verbose', '-V', '--verbose', 'Print verbose output.'
|
||||
c.option 'incremental', '-I', '--incremental', 'Enable incremental rebuild.'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5,8 +5,8 @@ module Jekyll
|
||||
# Create the Mercenary command for the Jekyll CLI for this Command
|
||||
def init_with_program(prog)
|
||||
prog.command(:build) do |c|
|
||||
c.syntax "build [options]"
|
||||
c.description "Build your site"
|
||||
c.syntax 'build [options]'
|
||||
c.description 'Build your site'
|
||||
c.alias :b
|
||||
|
||||
add_build_options(c)
|
||||
@@ -27,17 +27,15 @@ module Jekyll
|
||||
options = configuration_from_options(options)
|
||||
site = Jekyll::Site.new(options)
|
||||
|
||||
if options.fetch("skip_initial_build", false)
|
||||
Jekyll.logger.warn "Build Warning:", "Skipping the initial build." \
|
||||
" This may result in an out-of-date site."
|
||||
if options.fetch('skip_initial_build', false)
|
||||
Jekyll.logger.warn "Build Warning:", "Skipping the initial build. This may result in an out-of-date site."
|
||||
else
|
||||
build(site, options)
|
||||
end
|
||||
|
||||
if options.fetch("detach", false)
|
||||
Jekyll.logger.info "Auto-regeneration:",
|
||||
"disabled when running server detached."
|
||||
elsif options.fetch("watch", false)
|
||||
if options.fetch('detach', false)
|
||||
Jekyll.logger.info "Auto-regeneration:", "disabled when running server detached."
|
||||
elsif options.fetch('watch', false)
|
||||
watch(site, options)
|
||||
else
|
||||
Jekyll.logger.info "Auto-regeneration:", "disabled. Use --watch to enable."
|
||||
@@ -52,13 +50,12 @@ module Jekyll
|
||||
# Returns nothing.
|
||||
def build(site, options)
|
||||
t = Time.now
|
||||
source = options["source"]
|
||||
destination = options["destination"]
|
||||
incremental = options["incremental"]
|
||||
source = options['source']
|
||||
destination = options['destination']
|
||||
incremental = options['incremental']
|
||||
Jekyll.logger.info "Source:", source
|
||||
Jekyll.logger.info "Destination:", destination
|
||||
Jekyll.logger.info "Incremental build:",
|
||||
(incremental ? "enabled" : "disabled. Enable with --incremental")
|
||||
Jekyll.logger.info "Incremental build:", (incremental ? "enabled" : "disabled. Enable with --incremental")
|
||||
Jekyll.logger.info "Generating..."
|
||||
process_site(site)
|
||||
Jekyll.logger.info "", "done in #{(Time.now - t).round(3)} seconds."
|
||||
@@ -71,7 +68,7 @@ module Jekyll
|
||||
#
|
||||
# Returns nothing.
|
||||
def watch(_site, options)
|
||||
External.require_with_graceful_fail "jekyll-watch"
|
||||
External.require_with_graceful_fail 'jekyll-watch'
|
||||
Jekyll::Watcher.watch(options)
|
||||
end
|
||||
end # end of class << self
|
||||
|
||||
@@ -4,9 +4,8 @@ module Jekyll
|
||||
class << self
|
||||
def init_with_program(prog)
|
||||
prog.command(:clean) do |c|
|
||||
c.syntax "clean [subcommand]"
|
||||
c.description "Clean the site " \
|
||||
"(removes site output and metadata file) without building."
|
||||
c.syntax 'clean [subcommand]'
|
||||
c.description 'Clean the site (removes site output and metadata file) without building.'
|
||||
|
||||
add_build_options(c)
|
||||
|
||||
@@ -18,13 +17,13 @@ module Jekyll
|
||||
|
||||
def process(options)
|
||||
options = configuration_from_options(options)
|
||||
destination = options["destination"]
|
||||
metadata_file = File.join(options["source"], ".jekyll-metadata")
|
||||
sass_cache = File.join(options["source"], ".sass-cache")
|
||||
destination = options['destination']
|
||||
metadata_file = File.join(options['source'], '.jekyll-metadata')
|
||||
sass_cache = File.join(options['source'], '.sass-cache')
|
||||
|
||||
remove(destination, :checker_func => :directory?)
|
||||
remove(metadata_file, :checker_func => :file?)
|
||||
remove(sass_cache, :checker_func => :directory?)
|
||||
remove(destination, checker_func: :directory?)
|
||||
remove(metadata_file, checker_func: :file?)
|
||||
remove(sass_cache, checker_func: :directory?)
|
||||
end
|
||||
|
||||
def remove(filename, checker_func: :file?)
|
||||
|
||||
@@ -4,12 +4,11 @@ module Jekyll
|
||||
class << self
|
||||
def init_with_program(prog)
|
||||
prog.command(:doctor) do |c|
|
||||
c.syntax "doctor"
|
||||
c.description "Search site and print specific deprecation warnings"
|
||||
c.syntax 'doctor'
|
||||
c.description 'Search site and print specific deprecation warnings'
|
||||
c.alias(:hyde)
|
||||
|
||||
c.option "config", "--config CONFIG_FILE[,CONFIG_FILE2,...]", Array,
|
||||
"Custom configuration file"
|
||||
c.option 'config', '--config CONFIG_FILE[,CONFIG_FILE2,...]', Array, 'Custom configuration file'
|
||||
|
||||
c.action do |_, options|
|
||||
Jekyll::Commands::Doctor.process(options)
|
||||
@@ -19,9 +18,7 @@ module Jekyll
|
||||
|
||||
def process(options)
|
||||
site = Jekyll::Site.new(configuration_from_options(options))
|
||||
site.reset
|
||||
site.read
|
||||
site.generate
|
||||
|
||||
if healthy?(site)
|
||||
Jekyll.logger.info "Your test results", "are in. Everything looks fine."
|
||||
@@ -40,7 +37,7 @@ module Jekyll
|
||||
end
|
||||
|
||||
def deprecated_relative_permalinks(site)
|
||||
if site.config["relative_permalinks"]
|
||||
if site.config['relative_permalinks']
|
||||
Jekyll::Deprecator.deprecation_message "Your site still uses relative" \
|
||||
" permalinks, which was removed in" \
|
||||
" Jekyll v3.0.0."
|
||||
@@ -65,7 +62,7 @@ module Jekyll
|
||||
def fsnotify_buggy?(_site)
|
||||
return true unless Utils::Platforms.osx?
|
||||
if Dir.pwd != `pwd`.strip
|
||||
Jekyll.logger.error " " + <<-STR.strip.gsub(%r!\n\s+!, "\n ")
|
||||
Jekyll.logger.error " " + <<-STR.strip.gsub(/\n\s+/, "\n ")
|
||||
We have detected that there might be trouble using fsevent on your
|
||||
operating system, you can read https://github.com/thibaudgg/rb-fsevent/wiki/no-fsevents-fired-(OSX-bug)
|
||||
for possible work arounds or you can work around it immediately
|
||||
@@ -81,7 +78,7 @@ module Jekyll
|
||||
def urls_only_differ_by_case(site)
|
||||
urls_only_differ_by_case = false
|
||||
urls = case_insensitive_urls(site.pages + site.docs_to_write, site.dest)
|
||||
urls.each do |_case_insensitive_url, real_urls|
|
||||
urls.each do |case_insensitive_url, real_urls|
|
||||
next unless real_urls.uniq.size > 1
|
||||
urls_only_differ_by_case = true
|
||||
Jekyll.logger.warn "Warning:", "The following URLs only differ" \
|
||||
@@ -105,9 +102,10 @@ module Jekyll
|
||||
end
|
||||
|
||||
def case_insensitive_urls(things, destination)
|
||||
things.each_with_object({}) do |thing, memo|
|
||||
things.inject({}) do |memo, thing|
|
||||
dest = thing.destination(destination)
|
||||
(memo[dest.downcase] ||= []) << dest
|
||||
memo
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,8 +4,8 @@ module Jekyll
|
||||
class << self
|
||||
def init_with_program(prog)
|
||||
prog.command(:help) do |c|
|
||||
c.syntax "help [subcommand]"
|
||||
c.description "Show the help message, optionally for a given subcommand."
|
||||
c.syntax 'help [subcommand]'
|
||||
c.description 'Show the help message, optionally for a given subcommand.'
|
||||
|
||||
c.action do |args, _|
|
||||
cmd = (args.first || "").to_sym
|
||||
@@ -22,8 +22,7 @@ module Jekyll
|
||||
end
|
||||
|
||||
def invalid_command(prog, cmd)
|
||||
Jekyll.logger.error "Error:",
|
||||
"Hmm... we don't know what the '#{cmd}' command is."
|
||||
Jekyll.logger.error "Error:", "Hmm... we don't know what the '#{cmd}' command is."
|
||||
Jekyll.logger.info "Valid commands:", prog.commands.keys.join(", ")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require "erb"
|
||||
require 'erb'
|
||||
|
||||
module Jekyll
|
||||
module Commands
|
||||
@@ -6,11 +6,11 @@ module Jekyll
|
||||
class << self
|
||||
def init_with_program(prog)
|
||||
prog.command(:new) do |c|
|
||||
c.syntax "new PATH"
|
||||
c.description "Creates a new Jekyll site scaffold in PATH"
|
||||
c.syntax 'new PATH'
|
||||
c.description 'Creates a new Jekyll site scaffold in PATH'
|
||||
|
||||
c.option "force", "--force", "Force creation even if PATH already exists"
|
||||
c.option "blank", "--blank", "Creates scaffolding but with empty files"
|
||||
c.option 'force', '--force', 'Force creation even if PATH already exists'
|
||||
c.option 'blank', '--blank', 'Creates scaffolding but with empty files'
|
||||
|
||||
c.action do |args, options|
|
||||
Jekyll::Commands::New.process(args, options)
|
||||
@@ -19,19 +19,26 @@ module Jekyll
|
||||
end
|
||||
|
||||
def process(args, options = {})
|
||||
raise ArgumentError, "You must specify a path." if args.empty?
|
||||
raise ArgumentError.new('You must specify a path.') if args.empty?
|
||||
|
||||
new_blog_path = File.expand_path(args.join(" "), Dir.pwd)
|
||||
FileUtils.mkdir_p new_blog_path
|
||||
if preserve_source_location?(new_blog_path, options)
|
||||
Jekyll.logger.abort_with "Conflict:",
|
||||
"#{new_blog_path} exists and is not empty."
|
||||
Jekyll.logger.abort_with "Conflict:", "#{new_blog_path} exists and is not empty."
|
||||
end
|
||||
|
||||
if options["blank"]
|
||||
create_blank_site new_blog_path
|
||||
else
|
||||
create_site new_blog_path
|
||||
create_sample_files new_blog_path
|
||||
|
||||
File.open(File.expand_path(initialized_post_name, new_blog_path), "w") do |f|
|
||||
f.write(scaffold_post_content)
|
||||
end
|
||||
|
||||
File.open(File.expand_path("Gemfile", new_blog_path), "w") do |f|
|
||||
f.write(gemfile_contents)
|
||||
end
|
||||
end
|
||||
|
||||
Jekyll.logger.info "New jekyll site installed in #{new_blog_path}."
|
||||
@@ -52,16 +59,15 @@ module Jekyll
|
||||
#
|
||||
# Returns the filename of the sample post, as a String
|
||||
def initialized_post_name
|
||||
"_posts/#{Time.now.strftime("%Y-%m-%d")}-welcome-to-jekyll.markdown"
|
||||
"_posts/#{Time.now.strftime('%Y-%m-%d')}-welcome-to-jekyll.markdown"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
|
||||
def gemfile_contents
|
||||
<<-RUBY
|
||||
source "https://rubygems.org"
|
||||
ruby RUBY_VERSION
|
||||
|
||||
|
||||
# Hello! This is where you manage which Jekyll version is used to run.
|
||||
# When you want to use a different version, change it below, save the
|
||||
# file and run `bundle install`. Run Jekyll with `bundle exec`, like so:
|
||||
@@ -72,13 +78,10 @@ ruby RUBY_VERSION
|
||||
# Happy Jekylling!
|
||||
gem "jekyll", "#{Jekyll::VERSION}"
|
||||
|
||||
# This is the default theme for new Jekyll sites. You may change this to anything you like.
|
||||
gem "minima"
|
||||
|
||||
# If you want to use GitHub Pages, remove the "gem "jekyll"" above and
|
||||
# uncomment the line below. To upgrade, run `bundle update github-pages`.
|
||||
# gem "github-pages", group: :jekyll_plugins
|
||||
|
||||
|
||||
# If you have any plugins, put them here!
|
||||
# group :jekyll_plugins do
|
||||
# gem "jekyll-github-metadata", "~> 1.0"
|
||||
@@ -86,24 +89,12 @@ gem "minima"
|
||||
RUBY
|
||||
end
|
||||
|
||||
def create_site(new_blog_path)
|
||||
create_sample_files new_blog_path
|
||||
|
||||
File.open(File.expand_path(initialized_post_name, new_blog_path), "w") do |f|
|
||||
f.write(scaffold_post_content)
|
||||
end
|
||||
|
||||
File.open(File.expand_path("Gemfile", new_blog_path), "w") do |f|
|
||||
f.write(gemfile_contents)
|
||||
end
|
||||
end
|
||||
|
||||
def preserve_source_location?(path, options)
|
||||
!options["force"] && !Dir["#{path}/**/*"].empty?
|
||||
end
|
||||
|
||||
def create_sample_files(path)
|
||||
FileUtils.cp_r site_template + "/.", path
|
||||
FileUtils.cp_r site_template + '/.', path
|
||||
FileUtils.rm File.expand_path(scaffold_path, path)
|
||||
end
|
||||
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
require "erb"
|
||||
|
||||
class Jekyll::Commands::NewTheme < Jekyll::Command
|
||||
class << self
|
||||
def init_with_program(prog)
|
||||
prog.command(:"new-theme") do |c|
|
||||
c.syntax "new-theme NAME"
|
||||
c.description "Creates a new Jekyll theme scaffold"
|
||||
c.option "code_of_conduct", \
|
||||
"-c", "--code-of-conduct", \
|
||||
"Include a Code of Conduct. (defaults to false)"
|
||||
|
||||
c.action do |args, opts|
|
||||
Jekyll::Commands::NewTheme.process(args, opts)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def process(args, opts)
|
||||
if !args || args.empty?
|
||||
raise Jekyll::Errors::InvalidThemeName, "You must specify a theme name."
|
||||
end
|
||||
|
||||
new_theme_name = args.join("_")
|
||||
theme = Jekyll::ThemeBuilder.new(new_theme_name, opts)
|
||||
if theme.path.exist?
|
||||
Jekyll.logger.abort_with "Conflict:", "#{theme.path} already exists."
|
||||
end
|
||||
|
||||
theme.create!
|
||||
Jekyll.logger.info "Your new Jekyll theme, #{theme.name}," \
|
||||
" is ready for you in #{theme.path}!"
|
||||
Jekyll.logger.info "For help getting started, read #{theme.path}/README.md."
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -3,18 +3,18 @@ module Jekyll
|
||||
class Serve < Command
|
||||
class << self
|
||||
COMMAND_OPTIONS = {
|
||||
"ssl_cert" => ["--ssl-cert [CERT]", "X.509 (SSL) certificate."],
|
||||
"host" => ["host", "-H", "--host [HOST]", "Host to bind to"],
|
||||
"open_url" => ["-o", "--open-url", "Launch your site in a browser"],
|
||||
"detach" => ["-B", "--detach", "Run the server in the background"],
|
||||
"ssl_key" => ["--ssl-key [KEY]", "X.509 (SSL) Private Key."],
|
||||
"port" => ["-P", "--port [PORT]", "Port to listen on"],
|
||||
"baseurl" => ["-b", "--baseurl [URL]", "Base URL"],
|
||||
"show_dir_listing" => ["--show-dir-listing",
|
||||
"ssl_cert" => ["--ssl-cert [CERT]", "X.509 (SSL) certificate."],
|
||||
"host" => ["host", "-H", "--host [HOST]", "Host to bind to"],
|
||||
"open_url" => ["-o", "--open-url", "Launch your browser with your site."],
|
||||
"detach" => ["-B", "--detach", "Run the server in the background (detach)"],
|
||||
"ssl_key" => ["--ssl-key [KEY]", "X.509 (SSL) Private Key."],
|
||||
"port" => ["-P", "--port [PORT]", "Port to listen on"],
|
||||
"baseurl" => ["-b", "--baseurl [URL]", "Base URL"],
|
||||
"show_dir_listing" => ["--show-dir-listing",
|
||||
"Show a directory listing instead of loading your index file."],
|
||||
"skip_initial_build" => ["skip_initial_build", "--skip-initial-build",
|
||||
"Skips the initial site build which occurs before the server is started."]
|
||||
}.freeze
|
||||
}
|
||||
|
||||
#
|
||||
|
||||
@@ -33,9 +33,7 @@ module Jekyll
|
||||
cmd.action do |_, opts|
|
||||
opts["serving"] = true
|
||||
opts["watch" ] = true unless opts.key?("watch")
|
||||
config = opts["config"]
|
||||
Build.process(opts)
|
||||
opts["config"] = config
|
||||
Serve.process(opts)
|
||||
end
|
||||
end
|
||||
@@ -95,7 +93,7 @@ module Jekyll
|
||||
)
|
||||
}
|
||||
|
||||
opts[:DirectoryIndex] = [] if opts[:JekyllOptions]["show_dir_listing"]
|
||||
opts[:DirectoryIndex] = [] if opts[:JekyllOptions]['show_dir_listing']
|
||||
|
||||
enable_ssl(opts)
|
||||
enable_logging(opts)
|
||||
@@ -109,7 +107,7 @@ module Jekyll
|
||||
WEBrick::Config::FileHandler.merge({
|
||||
:FancyIndexing => true,
|
||||
:NondisclosureName => [
|
||||
".ht*", "~*"
|
||||
'.ht*', '~*'
|
||||
]
|
||||
})
|
||||
end
|
||||
@@ -118,12 +116,11 @@ module Jekyll
|
||||
|
||||
private
|
||||
def server_address(server, opts)
|
||||
format("%{prefix}://%{address}:%{port}%{baseurl}", {
|
||||
:prefix => server.config[:SSLEnable] ? "https" : "http",
|
||||
:baseurl => opts["baseurl"] ? "#{opts["baseurl"]}/" : "",
|
||||
:address => server.config[:BindAddress],
|
||||
:port => server.config[:Port]
|
||||
})
|
||||
address = server.config[:BindAddress]
|
||||
baseurl = "#{opts["baseurl"]}/" if opts["baseurl"]
|
||||
port = server.config[:Port]
|
||||
|
||||
"http://#{address}:#{port}#{baseurl}"
|
||||
end
|
||||
|
||||
#
|
||||
@@ -173,27 +170,22 @@ module Jekyll
|
||||
# forget to add one of the certificates.
|
||||
|
||||
private
|
||||
# rubocop:disable Metrics/AbcSize
|
||||
def enable_ssl(opts)
|
||||
return if !opts[:JekyllOptions]["ssl_cert"] && !opts[:JekyllOptions]["ssl_key"]
|
||||
if !opts[:JekyllOptions]["ssl_cert"] || !opts[:JekyllOptions]["ssl_key"]
|
||||
# rubocop:disable Style/RedundantException
|
||||
raise RuntimeError, "--ssl-cert or --ssl-key missing."
|
||||
end
|
||||
|
||||
require "openssl"
|
||||
require "webrick/https"
|
||||
source_key = Jekyll.sanitized_path(opts[:JekyllOptions]["source"], \
|
||||
opts[:JekyllOptions]["ssl_key" ])
|
||||
source_certificate = Jekyll.sanitized_path(opts[:JekyllOptions]["source"], \
|
||||
opts[:JekyllOptions]["ssl_cert"])
|
||||
opts[:SSLCertificate] =
|
||||
OpenSSL::X509::Certificate.new(File.read(source_certificate))
|
||||
source_key = Jekyll.sanitized_path(opts[:JekyllOptions]["source"], opts[:JekyllOptions]["ssl_key" ])
|
||||
source_certificate = Jekyll.sanitized_path(opts[:JekyllOptions]["source"], opts[:JekyllOptions]["ssl_cert"])
|
||||
opts[:SSLCertificate] = OpenSSL::X509::Certificate.new(File.read(source_certificate))
|
||||
opts[:SSLPrivateKey ] = OpenSSL::PKey::RSA.new(File.read(source_key))
|
||||
opts[:SSLEnable] = true
|
||||
opts[:EnableSSL] = true
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def start_callback(detached)
|
||||
unless detached
|
||||
proc do
|
||||
@@ -204,7 +196,7 @@ module Jekyll
|
||||
|
||||
private
|
||||
def mime_types
|
||||
file = File.expand_path("../mime.types", File.dirname(__FILE__))
|
||||
file = File.expand_path('../mime.types', File.dirname(__FILE__))
|
||||
WEBrick::HTTPUtils.load_mime_types(file)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -7,7 +7,7 @@ module Jekyll
|
||||
DEFAULTS = {
|
||||
"Cache-Control" => "private, max-age=0, proxy-revalidate, " \
|
||||
"no-store, no-cache, must-revalidate"
|
||||
}.freeze
|
||||
}
|
||||
|
||||
def initialize(server, root, callbacks)
|
||||
# So we can access them easily.
|
||||
@@ -25,7 +25,8 @@ module Jekyll
|
||||
super || super(req, res, "#{basename}.html")
|
||||
end
|
||||
|
||||
# rubocop:disable Style/MethodName
|
||||
#
|
||||
|
||||
def do_GET(req, res)
|
||||
rtn = super
|
||||
validate_and_ensure_charset(req, res)
|
||||
@@ -37,10 +38,10 @@ module Jekyll
|
||||
|
||||
private
|
||||
def validate_and_ensure_charset(_req, res)
|
||||
key = res.header.keys.grep(%r!content-type!i).first
|
||||
key = res.header.keys.grep(/content-type/i).first
|
||||
typ = res.header[key]
|
||||
|
||||
unless typ =~ %r!;\s*charset=!
|
||||
unless typ =~ /;\s*charset=/
|
||||
res.header[key] = "#{typ}; charset=#{@jekyll_opts["encoding"]}"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -6,90 +6,73 @@ module Jekyll
|
||||
# Strings rather than symbols are used for compatibility with YAML.
|
||||
DEFAULTS = Configuration[{
|
||||
# Where things are
|
||||
"source" => Dir.pwd,
|
||||
"destination" => File.join(Dir.pwd, "_site"),
|
||||
"plugins_dir" => "_plugins",
|
||||
"layouts_dir" => "_layouts",
|
||||
"data_dir" => "_data",
|
||||
"includes_dir" => "_includes",
|
||||
"collections" => {},
|
||||
'source' => Dir.pwd,
|
||||
'destination' => File.join(Dir.pwd, '_site'),
|
||||
'plugins_dir' => '_plugins',
|
||||
'layouts_dir' => '_layouts',
|
||||
'data_dir' => '_data',
|
||||
'includes_dir' => '_includes',
|
||||
'collections' => {},
|
||||
|
||||
# Handling Reading
|
||||
"safe" => false,
|
||||
"include" => [".htaccess"],
|
||||
"exclude" => [],
|
||||
"keep_files" => [".git", ".svn"],
|
||||
"encoding" => "utf-8",
|
||||
"markdown_ext" => "markdown,mkdown,mkdn,mkd,md",
|
||||
'safe' => false,
|
||||
'include' => ['.htaccess'],
|
||||
'exclude' => [],
|
||||
'keep_files' => ['.git', '.svn'],
|
||||
'encoding' => 'utf-8',
|
||||
'markdown_ext' => 'markdown,mkdown,mkdn,mkd,md',
|
||||
|
||||
# Filtering Content
|
||||
"show_drafts" => nil,
|
||||
"limit_posts" => 0,
|
||||
"future" => false,
|
||||
"unpublished" => false,
|
||||
'show_drafts' => nil,
|
||||
'limit_posts' => 0,
|
||||
'future' => false,
|
||||
'unpublished' => false,
|
||||
|
||||
# Plugins
|
||||
"whitelist" => [],
|
||||
"gems" => [],
|
||||
'whitelist' => [],
|
||||
'gems' => [],
|
||||
|
||||
# Conversion
|
||||
"markdown" => "kramdown",
|
||||
"highlighter" => "rouge",
|
||||
"lsi" => false,
|
||||
"excerpt_separator" => "\n\n",
|
||||
"incremental" => false,
|
||||
'markdown' => 'kramdown',
|
||||
'highlighter' => 'rouge',
|
||||
'lsi' => false,
|
||||
'excerpt_separator' => "\n\n",
|
||||
'incremental' => false,
|
||||
|
||||
# Serving
|
||||
"detach" => false, # default to not detaching the server
|
||||
"port" => "4000",
|
||||
"host" => "127.0.0.1",
|
||||
"baseurl" => "",
|
||||
"show_dir_listing" => false,
|
||||
'detach' => false, # default to not detaching the server
|
||||
'port' => '4000',
|
||||
'host' => '127.0.0.1',
|
||||
'baseurl' => '',
|
||||
'show_dir_listing' => false,
|
||||
|
||||
# Output Configuration
|
||||
"permalink" => "date",
|
||||
"paginate_path" => "/page:num",
|
||||
"timezone" => nil, # use the local timezone
|
||||
'permalink' => 'date',
|
||||
'paginate_path' => '/page:num',
|
||||
'timezone' => nil, # use the local timezone
|
||||
|
||||
"quiet" => false,
|
||||
"verbose" => false,
|
||||
"defaults" => [],
|
||||
'quiet' => false,
|
||||
'verbose' => false,
|
||||
'defaults' => [],
|
||||
|
||||
"rdiscount" => {
|
||||
"extensions" => []
|
||||
'rdiscount' => {
|
||||
'extensions' => []
|
||||
},
|
||||
|
||||
"redcarpet" => {
|
||||
"extensions" => []
|
||||
'redcarpet' => {
|
||||
'extensions' => []
|
||||
},
|
||||
|
||||
"kramdown" => {
|
||||
"auto_ids" => true,
|
||||
"toc_levels" => "1..6",
|
||||
"entity_output" => "as_char",
|
||||
"smart_quotes" => "lsquo,rsquo,ldquo,rdquo",
|
||||
"input" => "GFM",
|
||||
"hard_wrap" => false,
|
||||
"footnote_nr" => 1
|
||||
'kramdown' => {
|
||||
'auto_ids' => true,
|
||||
'toc_levels' => '1..6',
|
||||
'entity_output' => 'as_char',
|
||||
'smart_quotes' => 'lsquo,rsquo,ldquo,rdquo',
|
||||
'input' => "GFM",
|
||||
'hard_wrap' => false,
|
||||
'footnote_nr' => 1
|
||||
}
|
||||
}.map { |k, v| [k, v.freeze] }].freeze
|
||||
|
||||
class << self
|
||||
# Static: Produce a Configuration ready for use in a Site.
|
||||
# It takes the input, fills in the defaults where values do not
|
||||
# exist, and patches common issues including migrating options for
|
||||
# backwards compatiblity. Except where a key or value is being fixed,
|
||||
# the user configuration will override the defaults.
|
||||
#
|
||||
# user_config - a Hash or Configuration of overrides.
|
||||
#
|
||||
# Returns a Configuration filled with defaults and fixed for common
|
||||
# problems and backwards-compatibility.
|
||||
def from(user_config)
|
||||
Utils.deep_merge_hashes(DEFAULTS, Configuration[user_config].stringify_keys)
|
||||
.fix_common_issues.add_default_collections
|
||||
end
|
||||
end
|
||||
}]
|
||||
|
||||
# Public: Turn all keys into string
|
||||
#
|
||||
@@ -108,29 +91,28 @@ module Jekyll
|
||||
#
|
||||
# Returns the path to the Jekyll source directory
|
||||
def source(override)
|
||||
get_config_value_with_override("source", override)
|
||||
get_config_value_with_override('source', override)
|
||||
end
|
||||
|
||||
def quiet(override = {})
|
||||
get_config_value_with_override("quiet", override)
|
||||
get_config_value_with_override('quiet', override)
|
||||
end
|
||||
alias_method :quiet?, :quiet
|
||||
|
||||
def verbose(override = {})
|
||||
get_config_value_with_override("verbose", override)
|
||||
get_config_value_with_override('verbose', override)
|
||||
end
|
||||
alias_method :verbose?, :verbose
|
||||
|
||||
def safe_load_file(filename)
|
||||
case File.extname(filename)
|
||||
when %r!\.toml!i
|
||||
Jekyll::External.require_with_graceful_fail("toml") unless defined?(TOML)
|
||||
when /\.toml/i
|
||||
Jekyll::External.require_with_graceful_fail('toml') unless defined?(TOML)
|
||||
TOML.load_file(filename)
|
||||
when %r!\.ya?ml!i
|
||||
when /\.ya?ml/i
|
||||
SafeYAML.load_file(filename) || {}
|
||||
else
|
||||
raise ArgumentError, "No parser for '#{filename}' is available.
|
||||
Use a .toml or .y(a)ml file instead."
|
||||
raise ArgumentError, "No parser for '#{filename}' is available. Use a .toml or .y(a)ml file instead."
|
||||
end
|
||||
end
|
||||
|
||||
@@ -141,15 +123,12 @@ module Jekyll
|
||||
# Returns an Array of config files
|
||||
def config_files(override)
|
||||
# Adjust verbosity quickly
|
||||
Jekyll.logger.adjust_verbosity(
|
||||
:quiet => quiet?(override),
|
||||
:verbose => verbose?(override)
|
||||
)
|
||||
Jekyll.logger.adjust_verbosity(:quiet => quiet?(override), :verbose => verbose?(override))
|
||||
|
||||
# Get configuration from <source>/_config.yml or <source>/<config_file>
|
||||
config_files = override.delete("config")
|
||||
config_files = override.delete('config')
|
||||
if config_files.to_s.empty?
|
||||
default = %w(yml yaml).find(-> { "yml" }) do |ext|
|
||||
default = %w(yml yaml).find(-> { 'yml' }) do |ext|
|
||||
File.exist?(Jekyll.sanitized_path(source(override), "_config.#{ext}"))
|
||||
end
|
||||
config_files = Jekyll.sanitized_path(source(override), "_config.#{default}")
|
||||
@@ -174,8 +153,7 @@ module Jekyll
|
||||
Jekyll.logger.warn "Configuration file:", "none"
|
||||
{}
|
||||
else
|
||||
Jekyll.logger.error "Fatal:", "The configuration file '#{file}'
|
||||
could not be found."
|
||||
Jekyll.logger.error "Fatal:", "The configuration file '#{file}' could not be found."
|
||||
raise LoadError, "The Configuration file '#{file}' could not be found."
|
||||
end
|
||||
end
|
||||
@@ -191,14 +169,13 @@ module Jekyll
|
||||
|
||||
begin
|
||||
files.each do |config_file|
|
||||
next if config_file.nil? || config_file.empty?
|
||||
new_config = read_config_file(config_file)
|
||||
configuration = Utils.deep_merge_hashes(configuration, new_config)
|
||||
end
|
||||
rescue ArgumentError => err
|
||||
Jekyll.logger.warn "WARNING:", "Error reading configuration. " \
|
||||
"Using defaults (and options)."
|
||||
$stderr.puts err
|
||||
$stderr.puts "#{err}"
|
||||
end
|
||||
|
||||
configuration.fix_common_issues.backwards_compatibilize.add_default_collections
|
||||
@@ -220,18 +197,61 @@ module Jekyll
|
||||
def backwards_compatibilize
|
||||
config = clone
|
||||
# Provide backwards-compatibility
|
||||
check_auto(config)
|
||||
check_server(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
|
||||
|
||||
renamed_key "server_port", "port", config
|
||||
renamed_key "plugins", "plugins_dir", config
|
||||
renamed_key "layouts", "layouts_dir", config
|
||||
renamed_key "data_source", "data_dir", config
|
||||
if config.key? 'server'
|
||||
Jekyll::Deprecator.deprecation_message "The 'server' configuration option" \
|
||||
" is no longer accepted. Use the 'jekyll serve'" \
|
||||
" subcommand to serve your site with WEBrick."
|
||||
config.delete('server')
|
||||
end
|
||||
|
||||
check_pygments(config)
|
||||
check_include_exclude(config)
|
||||
check_coderay(config)
|
||||
check_maruku(config)
|
||||
renamed_key 'server_port', 'port', config
|
||||
renamed_key 'plugins', 'plugins_dir', config
|
||||
renamed_key 'layouts', 'layouts_dir', config
|
||||
renamed_key 'data_source', 'data_dir', config
|
||||
|
||||
if config.key? 'pygments'
|
||||
Jekyll::Deprecator.deprecation_message "The 'pygments' configuration option" \
|
||||
" has been renamed to 'highlighter'. Please update your" \
|
||||
" config file accordingly. The allowed values are 'rouge', " \
|
||||
"'pygments' or null."
|
||||
|
||||
config['highlighter'] = 'pygments' if config['pygments']
|
||||
config.delete('pygments')
|
||||
end
|
||||
|
||||
%w(include exclude).each do |option|
|
||||
config[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)
|
||||
end
|
||||
|
||||
if (config['kramdown'] || {}).key?('use_coderay')
|
||||
Jekyll::Deprecator.deprecation_message "Please change 'use_coderay'" \
|
||||
" to 'enable_coderay' in your configuration file."
|
||||
config['kramdown']['use_coderay'] = config['kramdown'].delete('enable_coderay')
|
||||
end
|
||||
|
||||
if config.fetch('markdown', 'kramdown').to_s.downcase.eql?("maruku")
|
||||
Jekyll.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
|
||||
end
|
||||
@@ -239,12 +259,10 @@ module Jekyll
|
||||
def fix_common_issues
|
||||
config = clone
|
||||
|
||||
if config.key?("paginate") && (!config["paginate"].is_a?(Integer) ||
|
||||
config["paginate"] < 1)
|
||||
|
||||
Jekyll.logger.warn "Config Warning:", "The `paginate` key must be a positive" \
|
||||
" integer or nil. It's currently set to '#{config["paginate"].inspect}'."
|
||||
config["paginate"] = nil
|
||||
if config.key?('paginate') && (!config['paginate'].is_a?(Integer) || config['paginate'] < 1)
|
||||
Jekyll.logger.warn "Config Warning:", "The `paginate` key must be a" \
|
||||
" positive integer or nil. It's currently set to '#{config['paginate'].inspect}'."
|
||||
config['paginate'] = nil
|
||||
end
|
||||
|
||||
config
|
||||
@@ -253,22 +271,14 @@ module Jekyll
|
||||
def add_default_collections
|
||||
config = clone
|
||||
|
||||
# It defaults to `{}`, so this is only if someone sets it to null manually.
|
||||
return config if config["collections"].nil?
|
||||
return config if config['collections'].nil?
|
||||
|
||||
# Ensure we have a hash.
|
||||
if config["collections"].is_a?(Array)
|
||||
config["collections"] = Hash[config["collections"].map { |c| [c, {}] }]
|
||||
end
|
||||
|
||||
config["collections"] = Utils.deep_merge_hashes(
|
||||
{ "posts" => {} }, config["collections"]
|
||||
).tap do |collections|
|
||||
collections["posts"]["output"] = true
|
||||
if config["permalink"]
|
||||
collections["posts"]["permalink"] ||= style_to_permalink(config["permalink"])
|
||||
end
|
||||
if config['collections'].is_a?(Array)
|
||||
config['collections'] = Hash[config['collections'].map { |c| [c, {}] }]
|
||||
end
|
||||
config['collections']['posts'] ||= {}
|
||||
config['collections']['posts']['output'] = true
|
||||
config['collections']['posts']['permalink'] = style_to_permalink(config['permalink'])
|
||||
|
||||
config
|
||||
end
|
||||
@@ -276,13 +286,14 @@ module Jekyll
|
||||
def renamed_key(old, new, config, _ = nil)
|
||||
if config.key?(old)
|
||||
Jekyll::Deprecator.deprecation_message "The '#{old}' configuration" \
|
||||
" option has been renamed to '#{new}'. Please update your config" \
|
||||
" file accordingly."
|
||||
"option has been renamed to '#{new}'. Please update your config " \
|
||||
"file accordingly."
|
||||
config[new] = config.delete(old)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def style_to_permalink(permalink_style)
|
||||
case permalink_style.to_sym
|
||||
when :pretty
|
||||
@@ -304,78 +315,9 @@ module Jekyll
|
||||
# file - the file from which the config was extracted
|
||||
#
|
||||
# Raises an ArgumentError if given config is not a hash
|
||||
private
|
||||
def check_config_is_hash!(extracted_config, file)
|
||||
unless extracted_config.is_a?(Hash)
|
||||
raise ArgumentError, "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."
|
||||
raise ArgumentError.new("Configuration file: (INVALID) #{file}".yellow)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -9,33 +9,23 @@ module Jekyll
|
||||
return if @setup ||= false
|
||||
unless (@parser = get_processor)
|
||||
Jekyll.logger.error "Invalid Markdown processor given:", @config["markdown"]
|
||||
if @config["safe"]
|
||||
Jekyll.logger.info "", "Custom processors are not loaded in safe mode"
|
||||
end
|
||||
Jekyll.logger.error(
|
||||
"",
|
||||
"Available processors are: #{valid_processors.join(", ")}"
|
||||
)
|
||||
Jekyll.logger.info "", "Custom processors are not loaded in safe mode" if @config["safe"]
|
||||
Jekyll.logger.error "", "Available processors are: #{valid_processors.join(", ")}"
|
||||
raise Errors::FatalException, "Bailing out; invalid Markdown processor."
|
||||
end
|
||||
|
||||
@setup = true
|
||||
end
|
||||
|
||||
# Rubocop does not allow reader methods to have names starting with `get_`
|
||||
# To ensure compatibility, this check has been disabled on this method
|
||||
#
|
||||
# rubocop:disable Style/AccessorMethodName
|
||||
def get_processor
|
||||
case @config["markdown"].downcase
|
||||
when "redcarpet" then return RedcarpetParser.new(@config)
|
||||
when "kramdown" then return KramdownParser.new(@config)
|
||||
when "rdiscount" then return RDiscountParser.new(@config)
|
||||
else
|
||||
custom_processor
|
||||
get_custom_processor
|
||||
end
|
||||
end
|
||||
# rubocop:enable Style/AccessorMethodName
|
||||
|
||||
# Public: Provides you with a list of processors, the ones we
|
||||
# support internally and the ones that you have provided to us (if you
|
||||
@@ -51,13 +41,13 @@ module Jekyll
|
||||
|
||||
def third_party_processors
|
||||
self.class.constants - \
|
||||
%w(KramdownParser RDiscountParser RedcarpetParser PRIORITIES).map(
|
||||
&:to_sym
|
||||
)
|
||||
%w(KramdownParser RDiscountParser RedcarpetParser PRIORITIES).map(
|
||||
&:to_sym
|
||||
)
|
||||
end
|
||||
|
||||
def extname_list
|
||||
@extname_list ||= @config["markdown_ext"].split(",").map do |e|
|
||||
@extname_list ||= @config['markdown_ext'].split(',').map do |e|
|
||||
".#{e.downcase}"
|
||||
end
|
||||
end
|
||||
@@ -76,7 +66,7 @@ module Jekyll
|
||||
end
|
||||
|
||||
private
|
||||
def custom_processor
|
||||
def get_custom_processor
|
||||
converter_name = @config["markdown"]
|
||||
if custom_class_allowed?(converter_name)
|
||||
self.class.const_get(converter_name).new(@config)
|
||||
@@ -93,7 +83,7 @@ module Jekyll
|
||||
|
||||
private
|
||||
def custom_class_allowed?(parser_name)
|
||||
parser_name !~ %r![^A-Za-z0-9_]! && self.class.constants.include?(
|
||||
parser_name !~ /[^A-Za-z0-9_]/ && self.class.constants.include?(
|
||||
parser_name.to_sym
|
||||
)
|
||||
end
|
||||
|
||||
@@ -24,8 +24,7 @@ module Jekyll
|
||||
|
||||
# Setup and normalize the configuration:
|
||||
# * Create Kramdown if it doesn't exist.
|
||||
# * Set syntax_highlighter, detecting enable_coderay and merging
|
||||
# highlighter if none.
|
||||
# * Set syntax_highlighter, detecting enable_coderay and merging highlighter if none.
|
||||
# * Merge kramdown[coderay] into syntax_highlighter_opts stripping coderay_.
|
||||
# * Make sure `syntax_highlighter_opts` exists.
|
||||
|
||||
@@ -53,9 +52,7 @@ module Jekyll
|
||||
end
|
||||
end
|
||||
|
||||
# config[kramdown][syntax_higlighter] >
|
||||
# config[kramdown][enable_coderay] >
|
||||
# config[highlighter]
|
||||
# config[kramdown][syntax_higlighter] > config[kramdown][enable_coderay] > config[highlighter]
|
||||
# Where `enable_coderay` is now deprecated because Kramdown
|
||||
# supports Rouge now too.
|
||||
|
||||
@@ -71,10 +68,8 @@ module Jekyll
|
||||
|
||||
@highlighter = begin
|
||||
if @config.key?("enable_coderay") && @config["enable_coderay"]
|
||||
Jekyll::Deprecator.deprecation_message(
|
||||
"You are using 'enable_coderay', " \
|
||||
Jekyll::Deprecator.deprecation_message "You are using 'enable_coderay', " \
|
||||
"use syntax_highlighter: coderay in your configuration file."
|
||||
)
|
||||
|
||||
"coderay"
|
||||
else
|
||||
@@ -86,7 +81,7 @@ module Jekyll
|
||||
private
|
||||
def strip_coderay_prefix(hash)
|
||||
hash.each_with_object({}) do |(key, val), hsh|
|
||||
cleaned_key = key.gsub(%r!\Acoderay_!, "")
|
||||
cleaned_key = key.gsub(/\Acoderay_/, "")
|
||||
|
||||
if key != cleaned_key
|
||||
Jekyll::Deprecator.deprecation_message(
|
||||
@@ -105,10 +100,8 @@ module Jekyll
|
||||
private
|
||||
def modernize_coderay_config
|
||||
if highlighter == "coderay"
|
||||
Jekyll::Deprecator.deprecation_message(
|
||||
"You are using 'kramdown.coderay' in your configuration, " \
|
||||
Jekyll::Deprecator.deprecation_message "You are using 'kramdown.coderay' in your configuration, " \
|
||||
"please use 'syntax_highlighter_opts' instead."
|
||||
)
|
||||
|
||||
@config["syntax_highlighter_opts"] = begin
|
||||
strip_coderay_prefix(
|
||||
|
||||
@@ -5,14 +5,14 @@ module Jekyll
|
||||
def initialize(config)
|
||||
Jekyll::External.require_with_graceful_fail "rdiscount"
|
||||
@config = config
|
||||
@rdiscount_extensions = @config["rdiscount"]["extensions"].map(&:to_sym)
|
||||
@rdiscount_extensions = @config['rdiscount']['extensions'].map(&:to_sym)
|
||||
end
|
||||
|
||||
def convert(content)
|
||||
rd = RDiscount.new(content, *@rdiscount_extensions)
|
||||
html = rd.to_html
|
||||
if @config["rdiscount"]["toc_token"]
|
||||
html = replace_generated_toc(rd, html, @config["rdiscount"]["toc_token"])
|
||||
if @config['rdiscount']['toc_token']
|
||||
html = replace_generated_toc(rd, html, @config['rdiscount']['toc_token'])
|
||||
end
|
||||
html
|
||||
end
|
||||
@@ -21,7 +21,7 @@ module Jekyll
|
||||
def replace_generated_toc(rd, html, toc_token)
|
||||
if rd.generate_toc && html.include?(toc_token)
|
||||
utf8_toc = rd.toc_content
|
||||
utf8_toc.force_encoding("utf-8") if utf8_toc.respond_to?(:force_encoding)
|
||||
utf8_toc.force_encoding('utf-8') if utf8_toc.respond_to?(:force_encoding)
|
||||
html.gsub(toc_token, utf8_toc)
|
||||
else
|
||||
html
|
||||
|
||||
@@ -1,108 +1,102 @@
|
||||
class Jekyll::Converters::Markdown::RedcarpetParser
|
||||
module CommonMethods
|
||||
def add_code_tags(code, lang)
|
||||
code = code.to_s
|
||||
code = code.sub(
|
||||
%r!<pre>!,
|
||||
"<pre><code class=\"language-#{lang}\" data-lang=\"#{lang}\">"
|
||||
)
|
||||
code = code.sub(%r!</pre>!, "</code></pre>")
|
||||
code
|
||||
end
|
||||
end
|
||||
|
||||
module WithPygments
|
||||
include CommonMethods
|
||||
def block_code(code, lang)
|
||||
Jekyll::External.require_with_graceful_fail("pygments")
|
||||
lang = lang && lang.split.first || "text"
|
||||
add_code_tags(
|
||||
Pygments.highlight(
|
||||
code,
|
||||
{
|
||||
:lexer => lang,
|
||||
:options => { :encoding => "utf-8" }
|
||||
}
|
||||
),
|
||||
lang
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
module WithoutHighlighting
|
||||
require "cgi"
|
||||
|
||||
include CommonMethods
|
||||
|
||||
def code_wrap(code)
|
||||
"<figure class=\"highlight\"><pre>#{CGI.escapeHTML(code)}</pre></figure>"
|
||||
end
|
||||
|
||||
def block_code(code, lang)
|
||||
lang = lang && lang.split.first || "text"
|
||||
add_code_tags(code_wrap(code), lang)
|
||||
end
|
||||
end
|
||||
|
||||
module WithRouge
|
||||
def block_code(code, lang)
|
||||
code = "<pre>#{super}</pre>"
|
||||
|
||||
output = "<div class=\"highlight\">"
|
||||
output << add_code_tags(code, lang)
|
||||
output << "</div>"
|
||||
end
|
||||
|
||||
protected
|
||||
def rouge_formatter(_lexer)
|
||||
Rouge::Formatters::HTML.new(:wrap => false)
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(config)
|
||||
Jekyll::External.require_with_graceful_fail("redcarpet")
|
||||
@config = config
|
||||
@redcarpet_extensions = {}
|
||||
@config["redcarpet"]["extensions"].each do |e|
|
||||
@redcarpet_extensions[e.to_sym] = true
|
||||
end
|
||||
|
||||
@renderer ||= class_with_proper_highlighter(@config["highlighter"])
|
||||
end
|
||||
|
||||
def class_with_proper_highlighter(highlighter)
|
||||
Class.new(Redcarpet::Render::HTML) do
|
||||
case highlighter
|
||||
when "pygments"
|
||||
include WithPygments
|
||||
when "rouge"
|
||||
Jekyll::External.require_with_graceful_fail(%w(
|
||||
rouge rouge/plugins/redcarpet
|
||||
))
|
||||
|
||||
unless Gem::Version.new(Rouge.version) > Gem::Version.new("1.3.0")
|
||||
abort "Please install Rouge 1.3.0 or greater and try running Jekyll again."
|
||||
module Jekyll
|
||||
module Converters
|
||||
class Markdown
|
||||
class RedcarpetParser
|
||||
module CommonMethods
|
||||
def add_code_tags(code, lang)
|
||||
code = code.to_s
|
||||
code = code.sub(/<pre>/, "<pre><code class=\"language-#{lang}\" data-lang=\"#{lang}\">")
|
||||
code = code.sub(/<\/pre>/, "</code></pre>")
|
||||
code
|
||||
end
|
||||
end
|
||||
|
||||
include Rouge::Plugins::Redcarpet
|
||||
include CommonMethods
|
||||
include WithRouge
|
||||
else
|
||||
include WithoutHighlighting
|
||||
module WithPygments
|
||||
include CommonMethods
|
||||
def block_code(code, lang)
|
||||
Jekyll::External.require_with_graceful_fail("pygments")
|
||||
lang = lang && lang.split.first || "text"
|
||||
add_code_tags(
|
||||
Pygments.highlight(code, :lexer => lang, :options => { :encoding => 'utf-8' }),
|
||||
lang
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
module WithoutHighlighting
|
||||
require 'cgi'
|
||||
|
||||
include CommonMethods
|
||||
|
||||
def code_wrap(code)
|
||||
"<figure class=\"highlight\"><pre>#{CGI::escapeHTML(code)}</pre></figure>"
|
||||
end
|
||||
|
||||
def block_code(code, lang)
|
||||
lang = lang && lang.split.first || "text"
|
||||
add_code_tags(code_wrap(code), lang)
|
||||
end
|
||||
end
|
||||
|
||||
module WithRouge
|
||||
def block_code(code, lang)
|
||||
code = "<pre>#{super}</pre>"
|
||||
|
||||
output = "<div class=\"highlight\">"
|
||||
output << add_code_tags(code, lang)
|
||||
output << "</div>"
|
||||
end
|
||||
|
||||
protected
|
||||
def rouge_formatter(_lexer)
|
||||
Rouge::Formatters::HTML.new(:wrap => false)
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(config)
|
||||
External.require_with_graceful_fail("redcarpet")
|
||||
@config = config
|
||||
@redcarpet_extensions = {}
|
||||
@config['redcarpet']['extensions'].each { |e| @redcarpet_extensions[e.to_sym] = true }
|
||||
|
||||
@renderer ||= class_with_proper_highlighter(@config['highlighter'])
|
||||
end
|
||||
|
||||
def class_with_proper_highlighter(highlighter)
|
||||
case highlighter
|
||||
when "pygments"
|
||||
Class.new(Redcarpet::Render::HTML) do
|
||||
include WithPygments
|
||||
end
|
||||
when "rouge"
|
||||
Class.new(Redcarpet::Render::HTML) do
|
||||
Jekyll::External.require_with_graceful_fail(%w(
|
||||
rouge
|
||||
rouge/plugins/redcarpet
|
||||
))
|
||||
|
||||
unless Gem::Version.new(Rouge.version) > Gem::Version.new("1.3.0")
|
||||
abort "Please install Rouge 1.3.0 or greater and try running Jekyll again."
|
||||
end
|
||||
|
||||
include Rouge::Plugins::Redcarpet
|
||||
include CommonMethods
|
||||
include WithRouge
|
||||
end
|
||||
else
|
||||
Class.new(Redcarpet::Render::HTML) do
|
||||
include WithoutHighlighting
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def convert(content)
|
||||
@redcarpet_extensions[:fenced_code_blocks] = !@redcarpet_extensions[:no_fenced_code_blocks]
|
||||
@renderer.send :include, Redcarpet::Render::SmartyPants if @redcarpet_extensions[:smart]
|
||||
markdown = Redcarpet::Markdown.new(@renderer.new(@redcarpet_extensions), @redcarpet_extensions)
|
||||
markdown.render(content)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def convert(content)
|
||||
@redcarpet_extensions[:fenced_code_blocks] = \
|
||||
!@redcarpet_extensions[:no_fenced_code_blocks]
|
||||
if @redcarpet_extensions[:smart]
|
||||
@renderer.send :include, Redcarpet::Render::SmartyPants
|
||||
end
|
||||
markdown = Redcarpet::Markdown.new(
|
||||
@renderer.new(@redcarpet_extensions),
|
||||
@redcarpet_extensions
|
||||
)
|
||||
markdown.render(content)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
require "set"
|
||||
require 'set'
|
||||
|
||||
# Convertible provides methods for converting a pagelike item
|
||||
# from a certain type of markup into actual content
|
||||
@@ -20,12 +20,12 @@ module Jekyll
|
||||
module Convertible
|
||||
# Returns the contents as a String.
|
||||
def to_s
|
||||
content || ""
|
||||
content || ''
|
||||
end
|
||||
|
||||
# Whether the file is published or not, as indicated in YAML front-matter
|
||||
def published?
|
||||
!(data.key?("published") && data["published"] == false)
|
||||
!(data.key?('published') && data['published'] == false)
|
||||
end
|
||||
|
||||
# Read the YAML frontmatter.
|
||||
@@ -39,15 +39,15 @@ module Jekyll
|
||||
filename = File.join(base, name)
|
||||
|
||||
begin
|
||||
self.content = File.read(@path || site.in_source_dir(base, name),
|
||||
self.content = File.read(site.in_source_dir(base, name),
|
||||
Utils.merged_file_read_opts(site, opts))
|
||||
if content =~ Document::YAML_FRONT_MATTER_REGEXP
|
||||
if content =~ /\A(---\s*\n.*?\n?)^((---|\.\.\.)\s*$\n?)/m
|
||||
self.content = $POSTMATCH
|
||||
self.data = SafeYAML.load(Regexp.last_match(1))
|
||||
end
|
||||
rescue SyntaxError => e
|
||||
Jekyll.logger.warn "YAML Exception reading #{filename}: #{e.message}"
|
||||
rescue => e
|
||||
rescue Exception => e
|
||||
Jekyll.logger.warn "Error reading file #{filename}: #{e.message}"
|
||||
end
|
||||
|
||||
@@ -61,13 +61,12 @@ module Jekyll
|
||||
|
||||
def validate_data!(filename)
|
||||
unless self.data.is_a?(Hash)
|
||||
raise Errors::InvalidYAMLFrontMatterError,
|
||||
"Invalid YAML front matter in #{filename}"
|
||||
raise Errors::InvalidYAMLFrontMatterError, "Invalid YAML front matter in #{filename}"
|
||||
end
|
||||
end
|
||||
|
||||
def validate_permalink!(filename)
|
||||
if self.data["permalink"] && self.data["permalink"].empty?
|
||||
if self.data['permalink'] && self.data['permalink'].size == 0
|
||||
raise Errors::InvalidPermalinkError, "Invalid permalink in #{filename}"
|
||||
end
|
||||
end
|
||||
@@ -80,10 +79,7 @@ module Jekyll
|
||||
begin
|
||||
converter.convert output
|
||||
rescue => e
|
||||
Jekyll.logger.error(
|
||||
"Conversion error:",
|
||||
"#{converter.class} encountered an error while converting '#{path}':"
|
||||
)
|
||||
Jekyll.logger.error "Conversion error:", "#{converter.class} encountered an error while converting '#{path}':"
|
||||
Jekyll.logger.error("", e.to_s)
|
||||
raise e
|
||||
end
|
||||
@@ -116,17 +112,12 @@ module Jekyll
|
||||
def render_liquid(content, payload, info, path)
|
||||
site.liquid_renderer.file(path).parse(content).render!(payload, info)
|
||||
rescue Tags::IncludeTagError => e
|
||||
Jekyll.logger.error(
|
||||
"Liquid Exception:",
|
||||
"#{e.message} in #{e.path}, included in #{path || self.path}"
|
||||
)
|
||||
Jekyll.logger.error "Liquid Exception:", "#{e.message} in #{e.path}, included in #{path || self.path}"
|
||||
raise e
|
||||
# rubocop: disable RescueException
|
||||
rescue Exception => e
|
||||
Jekyll.logger.error "Liquid Exception:", "#{e.message} in #{path || self.path}"
|
||||
raise e
|
||||
end
|
||||
# rubocop: enable RescueException
|
||||
|
||||
# Convert this Convertible's data to a Hash suitable for use by Liquid.
|
||||
#
|
||||
@@ -177,7 +168,7 @@ module Jekyll
|
||||
#
|
||||
# Returns true if extname == .coffee, false otherwise.
|
||||
def coffeescript_file?
|
||||
".coffee" == ext
|
||||
'.coffee'.eql?(ext)
|
||||
end
|
||||
|
||||
# Determine whether the file should be rendered with Liquid.
|
||||
@@ -214,25 +205,19 @@ module Jekyll
|
||||
# recursively render layouts
|
||||
layout = layouts[data["layout"]]
|
||||
|
||||
Jekyll.logger.warn(
|
||||
"Build Warning:",
|
||||
"Layout '#{data["layout"]}' requested in #{path} does not exist."
|
||||
) if invalid_layout? layout
|
||||
Jekyll.logger.warn("Build Warning:", "Layout '#{data["layout"]}' requested in #{path} does not exist.") if invalid_layout? layout
|
||||
|
||||
used = Set.new([layout])
|
||||
|
||||
# Reset the payload layout data to ensure it starts fresh for each page.
|
||||
payload["layout"] = nil
|
||||
|
||||
while layout
|
||||
Jekyll.logger.debug "Rendering Layout:", path
|
||||
payload["content"] = output
|
||||
payload["layout"] = Utils.deep_merge_hashes(layout.data, payload["layout"] || {})
|
||||
payload["layout"] = Utils.deep_merge_hashes(payload["layout"] || {}, layout.data)
|
||||
|
||||
self.output = render_liquid(layout.content,
|
||||
payload,
|
||||
info,
|
||||
layout.relative_path)
|
||||
payload,
|
||||
info,
|
||||
File.join(site.config['layouts_dir'], layout.name))
|
||||
|
||||
# Add layout to dependency tree
|
||||
site.regenerator.add_dependency(
|
||||
@@ -240,9 +225,12 @@ module Jekyll
|
||||
site.in_source_dir(layout.path)
|
||||
)
|
||||
|
||||
if (layout = layouts[layout.data["layout"]])
|
||||
break if used.include?(layout)
|
||||
used << layout
|
||||
if layout = layouts[layout.data["layout"]]
|
||||
if used.include?(layout)
|
||||
layout = nil # avoid recursive chain
|
||||
else
|
||||
used << layout
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -258,10 +246,7 @@ module Jekyll
|
||||
|
||||
Jekyll.logger.debug "Pre-Render Hooks:", self.relative_path
|
||||
Jekyll::Hooks.trigger hook_owner, :pre_render, self, payload
|
||||
info = {
|
||||
:filters => [Jekyll::Filters],
|
||||
:registers => { :site => site, :page => payload["page"] }
|
||||
}
|
||||
info = { :filters => [Jekyll::Filters], :registers => { :site => site, :page => payload["page"] } }
|
||||
|
||||
# render and transform content (this becomes the final content of the object)
|
||||
payload["highlighter_prefix"] = converters.first.highlighter_prefix
|
||||
@@ -290,7 +275,9 @@ module Jekyll
|
||||
def write(dest)
|
||||
path = destination(dest)
|
||||
FileUtils.mkdir_p(File.dirname(path))
|
||||
File.write(path, output, :mode => "wb")
|
||||
File.open(path, 'wb') do |f|
|
||||
f.write(output)
|
||||
end
|
||||
Jekyll::Hooks.trigger hook_owner, :post_write, self
|
||||
end
|
||||
|
||||
|
||||
@@ -9,24 +9,20 @@ module Jekyll
|
||||
'serve' subcommand."
|
||||
arg_is_present? args, "--no-server", "To build Jekyll without launching a server, \
|
||||
use the 'build' subcommand."
|
||||
arg_is_present? args, "--auto", "The switch '--auto' has been replaced with \
|
||||
'--watch'."
|
||||
arg_is_present? args, "--auto", "The switch '--auto' has been replaced with '--watch'."
|
||||
arg_is_present? args, "--no-auto", "To disable auto-replication, simply leave off \
|
||||
the '--watch' switch."
|
||||
arg_is_present? args, "--pygments", "The 'pygments'settings has been removed in \
|
||||
favour of 'highlighter'."
|
||||
arg_is_present? args, "--paginate", "The 'paginate' setting can only be set in \
|
||||
your config files."
|
||||
arg_is_present? args, "--url", "The 'url' setting can only be set in your \
|
||||
arg_is_present? args, "--paginate", "The 'paginate' setting can only be set in your \
|
||||
config files."
|
||||
arg_is_present? args, "--url", "The 'url' setting can only be set in your config files."
|
||||
no_subcommand(args)
|
||||
end
|
||||
|
||||
def no_subcommand(args)
|
||||
unless args.empty? ||
|
||||
args.first !~ %r(!/^--/!) || %w(--help --version).include?(args.first)
|
||||
deprecation_message "Jekyll now uses subcommands instead of just switches. \
|
||||
Run `jekyll help` to find out more."
|
||||
if args.size > 0 && args.first =~ /^--/ && !%w(--help --version).include?(args.first)
|
||||
deprecation_message "Jekyll now uses subcommands instead of just switches. Run `jekyll help` to find out more."
|
||||
abort
|
||||
end
|
||||
end
|
||||
@@ -43,8 +39,7 @@ module Jekyll
|
||||
|
||||
def defaults_deprecate_type(old, current)
|
||||
Jekyll.logger.warn "Defaults:", "The '#{old}' type has become '#{current}'."
|
||||
Jekyll.logger.warn "Defaults:", "Please update your front-matter defaults to use \
|
||||
'type: #{current}'."
|
||||
Jekyll.logger.warn "Defaults:", "Please update your front-matter defaults to use 'type: #{current}'."
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -7,9 +7,9 @@ module Jekyll
|
||||
attr_reader :path, :site, :extname, :collection
|
||||
attr_accessor :content, :output
|
||||
|
||||
YAML_FRONT_MATTER_REGEXP = %r!\A(---\s*\n.*?\n?)^((---|\.\.\.)\s*$\n?)!m
|
||||
DATELESS_FILENAME_MATCHER = %r!^(?:.+/)*(.*)(\.[^.]+)$!
|
||||
DATE_FILENAME_MATCHER = %r!^(?:.+/)*(\d+-\d+-\d+)-(.*)(\.[^.]+)$!
|
||||
YAML_FRONT_MATTER_REGEXP = /\A(---\s*\n.*?\n?)^((---|\.\.\.)\s*$\n?)/m
|
||||
DATELESS_FILENAME_MATCHER = /^(.+\/)*(.*)(\.[^.]+)$/
|
||||
DATE_FILENAME_MATCHER = /^(.+\/)*(\d+-\d+-\d+)-(.*)(\.[^.]+)$/
|
||||
|
||||
# Create a new Document.
|
||||
#
|
||||
@@ -51,16 +51,16 @@ module Jekyll
|
||||
#
|
||||
# Returns the merged data.
|
||||
def merge_data!(other, source: "YAML front matter")
|
||||
if other.key?("categories") && !other["categories"].nil?
|
||||
if other["categories"].is_a?(String)
|
||||
other["categories"] = other["categories"].split(" ").map(&:strip)
|
||||
if other.key?('categories') && !other['categories'].nil?
|
||||
if other['categories'].is_a?(String)
|
||||
other['categories'] = other['categories'].split(" ").map(&:strip)
|
||||
end
|
||||
other["categories"] = (data["categories"] || []) | other["categories"]
|
||||
other['categories'] = (data['categories'] || []) | other['categories']
|
||||
end
|
||||
Utils.deep_merge_hashes!(data, other)
|
||||
if data.key?("date") && !data["date"].is_a?(Time)
|
||||
data["date"] = Utils.parse_date(
|
||||
data["date"].to_s,
|
||||
if data.key?('date') && !data['date'].is_a?(Time)
|
||||
data['date'] = Utils.parse_date(
|
||||
data['date'].to_s,
|
||||
"Document '#{relative_path}' does not have a valid date in the #{source}."
|
||||
)
|
||||
end
|
||||
@@ -68,7 +68,7 @@ module Jekyll
|
||||
end
|
||||
|
||||
def date
|
||||
data["date"] ||= (draft? ? source_file_mtime : site.time)
|
||||
data['date'] ||= (draft? ? source_file_mtime : site.time)
|
||||
end
|
||||
|
||||
def source_file_mtime
|
||||
@@ -81,8 +81,7 @@ module Jekyll
|
||||
#
|
||||
# Returns whether the document is a draft.
|
||||
def draft?
|
||||
data["draft"] ||= relative_path.index(collection.relative_directory).nil? &&
|
||||
collection.label == "posts"
|
||||
data['draft'] ||= relative_path.index(collection.relative_directory).nil? && collection.label == "posts"
|
||||
end
|
||||
|
||||
# The path to the document, relative to the site source.
|
||||
@@ -90,8 +89,7 @@ module Jekyll
|
||||
# Returns a String path which represents the relative path
|
||||
# from the site source to this document
|
||||
def relative_path
|
||||
@relative_path ||= Pathname.new(path)
|
||||
.relative_path_from(Pathname.new(site.source)).to_s
|
||||
@relative_path ||= Pathname.new(path).relative_path_from(Pathname.new(site.source)).to_s
|
||||
end
|
||||
|
||||
# The output extension of the document.
|
||||
@@ -105,7 +103,7 @@ module Jekyll
|
||||
#
|
||||
# Returns the basename without the file extname.
|
||||
def basename_without_ext
|
||||
@basename_without_ext ||= File.basename(path, ".*")
|
||||
@basename_without_ext ||= File.basename(path, '.*')
|
||||
end
|
||||
|
||||
# The base filename of the document.
|
||||
@@ -158,7 +156,7 @@ module Jekyll
|
||||
#
|
||||
# Returns true if extname == .coffee, false otherwise.
|
||||
def coffeescript_file?
|
||||
".coffee" == extname
|
||||
'.coffee'.eql?(extname)
|
||||
end
|
||||
|
||||
# Determine whether the file should be rendered with Liquid.
|
||||
@@ -197,7 +195,7 @@ module Jekyll
|
||||
#
|
||||
# Returns the permalink or nil if no permalink was set in the data.
|
||||
def permalink
|
||||
data && data.is_a?(Hash) && data["permalink"]
|
||||
data && data.is_a?(Hash) && data['permalink']
|
||||
end
|
||||
|
||||
# The computed URL for the document. See `Jekyll::URL#to_s` for more details.
|
||||
@@ -205,9 +203,9 @@ module Jekyll
|
||||
# Returns the computed URL for the document.
|
||||
def url
|
||||
@url = URL.new({
|
||||
:template => url_template,
|
||||
:template => url_template,
|
||||
:placeholders => url_placeholders,
|
||||
:permalink => permalink
|
||||
:permalink => permalink
|
||||
}).to_s
|
||||
end
|
||||
|
||||
@@ -239,17 +237,18 @@ module Jekyll
|
||||
def write(dest)
|
||||
path = destination(dest)
|
||||
FileUtils.mkdir_p(File.dirname(path))
|
||||
File.write(path, output, :mode => "wb")
|
||||
File.open(path, 'wb') do |f|
|
||||
f.write(output)
|
||||
end
|
||||
|
||||
trigger_hooks(:post_write)
|
||||
end
|
||||
|
||||
# Whether the file is published or not, as indicated in YAML front-matter
|
||||
#
|
||||
# Returns 'false' if the 'published' key is specified in the
|
||||
# YAML front-matter and is 'false'. Otherwise returns 'true'.
|
||||
# Returns true if the 'published' key is specified in the YAML front-matter and not `false`.
|
||||
def published?
|
||||
!(data.key?("published") && data["published"] == false)
|
||||
!(data.key?('published') && data['published'] == false)
|
||||
end
|
||||
|
||||
# Read in the file and assign the content and data based on the file contents.
|
||||
@@ -264,24 +263,23 @@ module Jekyll
|
||||
@data = SafeYAML.load_file(path)
|
||||
else
|
||||
begin
|
||||
defaults = @site.frontmatter_defaults.all(
|
||||
relative_path,
|
||||
collection.label.to_sym
|
||||
)
|
||||
merge_data!(defaults, :source => "front matter defaults") unless defaults.empty?
|
||||
defaults = @site.frontmatter_defaults.all(url, collection.label.to_sym)
|
||||
merge_data!(defaults, source: "front matter defaults") unless defaults.empty?
|
||||
|
||||
self.content = File.read(path, Utils.merged_file_read_opts(site, opts))
|
||||
if content =~ YAML_FRONT_MATTER_REGEXP
|
||||
self.content = $POSTMATCH
|
||||
data_file = SafeYAML.load(Regexp.last_match(1))
|
||||
merge_data!(data_file, :source => "YAML front matter") if data_file
|
||||
merge_data!(data_file, source: "YAML front matter") if data_file
|
||||
end
|
||||
|
||||
post_read
|
||||
rescue SyntaxError => e
|
||||
Jekyll.logger.error "Error:", "YAML Exception reading #{path}: #{e.message}"
|
||||
rescue => e
|
||||
raise e if e.is_a? Jekyll::Errors::FatalException
|
||||
rescue Exception => e
|
||||
if e.is_a? Jekyll::Errors::FatalException
|
||||
raise e
|
||||
end
|
||||
Jekyll.logger.error "Error:", "could not read file #{path}: #{e.message}"
|
||||
end
|
||||
end
|
||||
@@ -289,19 +287,19 @@ module Jekyll
|
||||
|
||||
def post_read
|
||||
if relative_path =~ DATE_FILENAME_MATCHER
|
||||
date, slug, ext = Regexp.last_match.captures
|
||||
if !data["date"] || data["date"].to_i == site.time.to_i
|
||||
merge_data!({ "date" => date }, :source => "filename")
|
||||
date, slug, ext = $2, $3, $4
|
||||
if !data['date'] || data['date'].to_i == site.time.to_i
|
||||
merge_data!({"date" => date}, source: "filename")
|
||||
end
|
||||
elsif relative_path =~ DATELESS_FILENAME_MATCHER
|
||||
slug, ext = Regexp.last_match.captures
|
||||
slug, ext = $2, $3
|
||||
end
|
||||
|
||||
# Try to ensure the user gets a title.
|
||||
data["title"] ||= Utils.titleize_slug(slug)
|
||||
# Only overwrite slug & ext if they aren't specified.
|
||||
data["slug"] ||= slug
|
||||
data["ext"] ||= ext
|
||||
data['slug'] ||= slug
|
||||
data['ext'] ||= ext
|
||||
|
||||
populate_categories
|
||||
populate_tags
|
||||
@@ -314,19 +312,16 @@ module Jekyll
|
||||
#
|
||||
# Returns nothing.
|
||||
def categories_from_path(special_dir)
|
||||
superdirs = relative_path.sub(%r!#{special_dir}(.*)!, "")
|
||||
.split(File::SEPARATOR)
|
||||
.reject do |c|
|
||||
superdirs = relative_path.sub(/#{special_dir}(.*)/, '').split(File::SEPARATOR).reject do |c|
|
||||
c.empty? || c.eql?(special_dir) || c.eql?(basename)
|
||||
end
|
||||
merge_data!({ "categories" => superdirs }, :source => "file path")
|
||||
merge_data!({ 'categories' => superdirs }, source: "file path")
|
||||
end
|
||||
|
||||
def populate_categories
|
||||
merge_data!({
|
||||
"categories" => (
|
||||
Array(data["categories"]) +
|
||||
Utils.pluralized_array_from_hash(data, "category", "categories")
|
||||
'categories' => (
|
||||
Array(data['categories']) + Utils.pluralized_array_from_hash(data, 'category', 'categories')
|
||||
).map(&:to_s).flatten.uniq
|
||||
})
|
||||
end
|
||||
@@ -356,7 +351,7 @@ module Jekyll
|
||||
#
|
||||
# Returns the content of the document
|
||||
def to_s
|
||||
output || content || "NO CONTENT"
|
||||
output || content || 'NO CONTENT'
|
||||
end
|
||||
|
||||
# Compare this document against another document.
|
||||
@@ -366,7 +361,7 @@ module Jekyll
|
||||
# equal or greater than the other doc's path. See String#<=> for more details.
|
||||
def <=>(other)
|
||||
return nil unless other.respond_to?(:data)
|
||||
cmp = data["date"] <=> other.data["date"]
|
||||
cmp = data['date'] <=> other.data['date']
|
||||
cmp = path <=> other.path if cmp.nil? || cmp == 0
|
||||
cmp
|
||||
end
|
||||
@@ -385,7 +380,7 @@ module Jekyll
|
||||
#
|
||||
# Returns the document excerpt_separator
|
||||
def excerpt_separator
|
||||
(data["excerpt_separator"] || site.config["excerpt_separator"]).to_s
|
||||
(data['excerpt_separator'] || site.config['excerpt_separator']).to_s
|
||||
end
|
||||
|
||||
# Whether to generate an excerpt
|
||||
@@ -399,6 +394,8 @@ module Jekyll
|
||||
pos = collection.docs.index { |post| post.equal?(self) }
|
||||
if pos && pos < collection.docs.length - 1
|
||||
collection.docs[pos + 1]
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
@@ -406,6 +403,8 @@ module Jekyll
|
||||
pos = collection.docs.index { |post| post.equal?(self) }
|
||||
if pos && pos > 0
|
||||
collection.docs[pos - 1]
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
@@ -415,7 +414,7 @@ module Jekyll
|
||||
end
|
||||
|
||||
def id
|
||||
@id ||= File.join(File.dirname(url), (data["slug"] || basename_without_ext).to_s)
|
||||
@id ||= File.join(File.dirname(url), (data['slug'] || basename_without_ext).to_s)
|
||||
end
|
||||
|
||||
# Calculate related posts.
|
||||
@@ -434,9 +433,8 @@ module Jekyll
|
||||
# Override of method_missing to check in @data for the key.
|
||||
def method_missing(method, *args, &blck)
|
||||
if data.key?(method.to_s)
|
||||
Jekyll::Deprecator.deprecation_message "Document##{method} is now a key "\
|
||||
"in the #data hash."
|
||||
Jekyll::Deprecator.deprecation_message "Called by #{caller.first}."
|
||||
Jekyll.logger.warn "Deprecation:", "Document##{method} is now a key in the #data hash."
|
||||
Jekyll.logger.warn "", "Called by #{caller.first}."
|
||||
data[method.to_s]
|
||||
else
|
||||
super
|
||||
|
||||
@@ -5,12 +5,10 @@ module Jekyll
|
||||
class DocumentDrop < Drop
|
||||
extend Forwardable
|
||||
|
||||
NESTED_OBJECT_FIELD_BLACKLIST = %w(
|
||||
content output excerpt next previous
|
||||
).freeze
|
||||
|
||||
mutable false
|
||||
|
||||
def_delegator :@obj, :next_doc, :next
|
||||
def_delegator :@obj, :previous_doc, :previous
|
||||
def_delegator :@obj, :relative_path, :path
|
||||
def_delegators :@obj, :id, :output, :content, :to_s, :relative_path, :url
|
||||
|
||||
@@ -19,49 +17,16 @@ module Jekyll
|
||||
end
|
||||
|
||||
def excerpt
|
||||
fallback_data["excerpt"].to_s
|
||||
fallback_data['excerpt'].to_s
|
||||
end
|
||||
|
||||
def <=>(other)
|
||||
return nil unless other.is_a? DocumentDrop
|
||||
cmp = self["date"] <=> other["date"]
|
||||
cmp = self["path"] <=> other["path"] if cmp.nil? || cmp == 0
|
||||
cmp = self['date'] <=> other['date']
|
||||
cmp = self['path'] <=> other['path'] if cmp.nil? || cmp == 0
|
||||
cmp
|
||||
end
|
||||
|
||||
def previous
|
||||
@obj.previous_doc.to_liquid
|
||||
end
|
||||
|
||||
def next
|
||||
@obj.next_doc.to_liquid
|
||||
end
|
||||
|
||||
# Generate a Hash for use in generating JSON.
|
||||
# This is useful if fields need to be cleared before the JSON can generate.
|
||||
#
|
||||
# state - the JSON::State object which determines the state of current processing.
|
||||
#
|
||||
# Returns a Hash ready for JSON generation.
|
||||
def hash_for_json(state = nil)
|
||||
to_h.tap do |hash|
|
||||
if state && state.depth >= 2
|
||||
hash["previous"] = collapse_document(hash["previous"]) if hash["previous"]
|
||||
hash["next"] = collapse_document(hash["next"]) if hash["next"]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Generate a Hash which breaks the recursive chain.
|
||||
# Certain fields which are normally available are omitted.
|
||||
#
|
||||
# Returns a Hash with only non-recursive fields present.
|
||||
def collapse_document(doc)
|
||||
doc.keys.each_with_object({}) do |(key, _), result|
|
||||
result[key] = doc[key] unless NESTED_OBJECT_FIELD_BLACKLIST.include?(key)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def_delegator :@obj, :data, :fallback_data
|
||||
end
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
module Jekyll
|
||||
module Drops
|
||||
class Drop < Liquid::Drop
|
||||
include Enumerable
|
||||
|
||||
NON_CONTENT_METHODS = [:fallback_data, :collapse_document].freeze
|
||||
NON_CONTENT_METHODS = [:[], :[]=, :inspect, :to_h, :fallback_data].freeze
|
||||
|
||||
# Get or set whether the drop class is mutable.
|
||||
# Mutability determines whether or not pre-defined fields may be
|
||||
@@ -15,11 +13,11 @@ module Jekyll
|
||||
#
|
||||
# Returns the mutability of the class
|
||||
def self.mutable(is_mutable = nil)
|
||||
@is_mutable = if is_mutable
|
||||
is_mutable
|
||||
else
|
||||
false
|
||||
end
|
||||
if is_mutable
|
||||
@is_mutable = is_mutable
|
||||
else
|
||||
@is_mutable = false
|
||||
end
|
||||
end
|
||||
|
||||
def self.mutable?
|
||||
@@ -88,9 +86,7 @@ module Jekyll
|
||||
# Returns an Array of strings which represent method-specific keys.
|
||||
def content_methods
|
||||
@content_methods ||= (
|
||||
self.class.instance_methods \
|
||||
- Jekyll::Drops::Drop.instance_methods \
|
||||
- NON_CONTENT_METHODS
|
||||
self.class.instance_methods(false) - NON_CONTENT_METHODS
|
||||
).map(&:to_s).reject do |method|
|
||||
method.end_with?("=")
|
||||
end
|
||||
@@ -138,28 +134,10 @@ module Jekyll
|
||||
#
|
||||
# Returns a pretty generation of the hash representation of the Drop.
|
||||
def inspect
|
||||
require "json"
|
||||
require 'json'
|
||||
JSON.pretty_generate to_h
|
||||
end
|
||||
|
||||
# Generate a Hash for use in generating JSON.
|
||||
# This is useful if fields need to be cleared before the JSON can generate.
|
||||
#
|
||||
# Returns a Hash ready for JSON generation.
|
||||
def hash_for_json(*)
|
||||
to_h
|
||||
end
|
||||
|
||||
# Generate a JSON representation of the Drop.
|
||||
#
|
||||
# state - the JSON::State object which determines the state of current processing.
|
||||
#
|
||||
# Returns a JSON representation of the Drop in a String.
|
||||
def to_json(state = nil)
|
||||
require "json"
|
||||
JSON.generate(hash_for_json(state), state)
|
||||
end
|
||||
|
||||
# Collects all the keys and passes each to the block in turn.
|
||||
#
|
||||
# block - a block which accepts one argument, the key
|
||||
@@ -169,12 +147,6 @@ module Jekyll
|
||||
keys.each(&block)
|
||||
end
|
||||
|
||||
def each
|
||||
each_key.each do |key|
|
||||
yield key, self[key]
|
||||
end
|
||||
end
|
||||
|
||||
def merge(other, &block)
|
||||
self.dup.tap do |me|
|
||||
if block.nil?
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
# encoding: UTF-8
|
||||
|
||||
module Jekyll
|
||||
module Drops
|
||||
class ExcerptDrop < DocumentDrop
|
||||
def layout
|
||||
@obj.doc.data["layout"]
|
||||
end
|
||||
|
||||
def excerpt
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -16,18 +16,6 @@ module Jekyll
|
||||
def environment
|
||||
Jekyll.env
|
||||
end
|
||||
|
||||
def to_h
|
||||
@to_h ||= {
|
||||
"version" => version,
|
||||
"environment" => environment
|
||||
}
|
||||
end
|
||||
|
||||
def to_json(state = nil)
|
||||
require "json"
|
||||
JSON.generate(to_h, state)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -24,13 +24,11 @@ module Jekyll
|
||||
end
|
||||
|
||||
def html_pages
|
||||
@site_html_pages ||= @obj.pages.select do |page|
|
||||
page.html? || page.url.end_with?("/")
|
||||
end
|
||||
@site_html_pages ||= @obj.pages.select { |page| page.html? || page.url.end_with?("/") }
|
||||
end
|
||||
|
||||
def collections
|
||||
@site_collections ||= @obj.collections.values.sort_by(&:label).map(&:to_liquid)
|
||||
@site_collections ||= @obj.collections.values.map(&:to_liquid)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -19,20 +19,20 @@ module Jekyll
|
||||
end
|
||||
|
||||
def title
|
||||
Utils.slugify(@obj.data["slug"], :mode => "pretty", :cased => true) ||
|
||||
Utils.slugify(@obj.data['slug'], :mode => "pretty", :cased => true) ||
|
||||
Utils.slugify(@obj.basename_without_ext, :mode => "pretty", :cased => true)
|
||||
end
|
||||
|
||||
def slug
|
||||
Utils.slugify(@obj.data["slug"]) || Utils.slugify(@obj.basename_without_ext)
|
||||
Utils.slugify(@obj.data['slug']) || Utils.slugify(@obj.basename_without_ext)
|
||||
end
|
||||
|
||||
def categories
|
||||
category_set = Set.new
|
||||
Array(@obj.data["categories"]).each do |category|
|
||||
Array(@obj.data['categories']).each do |category|
|
||||
category_set << category.to_s.downcase
|
||||
end
|
||||
category_set.to_a.join("/")
|
||||
category_set.to_a.join('/')
|
||||
end
|
||||
|
||||
def year
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
module Jekyll
|
||||
class EntryFilter
|
||||
SPECIAL_LEADING_CHARACTERS = ['.', '_', '#', '~'].freeze
|
||||
|
||||
attr_reader :site
|
||||
SPECIAL_LEADING_CHARACTERS = [
|
||||
".", "_", "#", "~"
|
||||
].freeze
|
||||
|
||||
def initialize(site, base_directory = nil)
|
||||
@site = site
|
||||
@base_directory = derive_base_directory(
|
||||
@site, base_directory.to_s.dup
|
||||
)
|
||||
@base_directory = derive_base_directory(@site, base_directory.to_s.dup)
|
||||
end
|
||||
|
||||
def base_directory
|
||||
@@ -17,14 +14,14 @@ module Jekyll
|
||||
end
|
||||
|
||||
def derive_base_directory(site, base_dir)
|
||||
base_dir[site.source] = "" if base_dir.start_with?(site.source)
|
||||
if base_dir.start_with?(site.source)
|
||||
base_dir[site.source] = ""
|
||||
end
|
||||
base_dir
|
||||
end
|
||||
|
||||
def relative_to_source(entry)
|
||||
File.join(
|
||||
base_directory, entry
|
||||
)
|
||||
File.join(base_directory, entry)
|
||||
end
|
||||
|
||||
def filter(entries)
|
||||
@@ -36,8 +33,7 @@ module Jekyll
|
||||
end
|
||||
|
||||
def included?(entry)
|
||||
glob_include?(site.include,
|
||||
entry)
|
||||
glob_include?(site.include, entry)
|
||||
end
|
||||
|
||||
def special?(entry)
|
||||
@@ -46,75 +42,30 @@ module Jekyll
|
||||
end
|
||||
|
||||
def backup?(entry)
|
||||
entry[-1..-1] == "~"
|
||||
entry[-1..-1] == '~'
|
||||
end
|
||||
|
||||
def excluded?(entry)
|
||||
excluded = glob_include?(site.exclude, relative_to_source(entry))
|
||||
if excluded
|
||||
Jekyll.logger.debug(
|
||||
"EntryFilter:",
|
||||
"excluded #{relative_to_source(entry)}"
|
||||
)
|
||||
end
|
||||
Jekyll.logger.debug "EntryFilter:", "excluded #{relative_to_source(entry)}" if excluded
|
||||
excluded
|
||||
end
|
||||
|
||||
# --
|
||||
# Check if a file is a symlink.
|
||||
# NOTE: This can be converted to allowing even in safe,
|
||||
# since we use Pathutil#in_path? now.
|
||||
# --
|
||||
def symlink?(entry)
|
||||
site.safe && File.symlink?(entry) && symlink_outside_site_source?(entry)
|
||||
File.symlink?(entry) && site.safe
|
||||
end
|
||||
|
||||
# --
|
||||
# NOTE: Pathutil#in_path? gets the realpath.
|
||||
# @param [<Anything>] entry the entry you want to validate.
|
||||
# Check if a path is outside of our given root.
|
||||
# --
|
||||
def symlink_outside_site_source?(entry)
|
||||
!Pathutil.new(entry).in_path?(
|
||||
site.in_source_dir
|
||||
)
|
||||
def ensure_leading_slash(path)
|
||||
path[0..0] == "/" ? path : "/#{path}"
|
||||
end
|
||||
|
||||
# --
|
||||
# Check if an entry matches a specific pattern and return true,false.
|
||||
# Returns true if path matches against any glob pattern.
|
||||
# --
|
||||
# Look for more detail about glob pattern in method File::fnmatch.
|
||||
def glob_include?(enum, e)
|
||||
entry = Pathutil.new(site.in_source_dir).join(e)
|
||||
entry = ensure_leading_slash(e)
|
||||
enum.any? do |exp|
|
||||
# Users who send a Regexp knows what they want to
|
||||
# exclude, so let them send a Regexp to exclude files,
|
||||
# we will not bother caring if it works or not, it's
|
||||
# on them at this point.
|
||||
|
||||
if exp.is_a?(Regexp)
|
||||
entry =~ exp
|
||||
|
||||
else
|
||||
item = Pathutil.new(site.in_source_dir).join(exp)
|
||||
|
||||
# If it's a directory they want to exclude, AKA
|
||||
# ends with a "/" then we will go on to check and
|
||||
# see if the entry falls within that path and
|
||||
# exclude it if that's the case.
|
||||
|
||||
if e.end_with?("/")
|
||||
entry.in_path?(
|
||||
item
|
||||
)
|
||||
|
||||
else
|
||||
File.fnmatch?(item, entry) ||
|
||||
entry.to_path.start_with?(
|
||||
item
|
||||
)
|
||||
end
|
||||
end
|
||||
item = ensure_leading_slash(exp)
|
||||
File.fnmatch?(item, entry) || entry.start_with?(item)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,8 +2,6 @@ module Jekyll
|
||||
module Errors
|
||||
FatalException = Class.new(::RuntimeError)
|
||||
|
||||
InvalidThemeName = Class.new(FatalException)
|
||||
|
||||
DropMutationException = Class.new(FatalException)
|
||||
InvalidPermalinkError = Class.new(FatalException)
|
||||
InvalidYAMLFrontMatterError = Class.new(FatalException)
|
||||
|
||||
@@ -7,7 +7,7 @@ module Jekyll
|
||||
attr_writer :output
|
||||
|
||||
def_delegators :@doc, :site, :name, :ext, :relative_path, :extname,
|
||||
:render_with_liquid?, :collection, :related_posts, :url
|
||||
:render_with_liquid?, :collection, :related_posts
|
||||
|
||||
# Initialize this Excerpt instance.
|
||||
#
|
||||
@@ -59,7 +59,10 @@ module Jekyll
|
||||
end
|
||||
|
||||
def to_liquid
|
||||
Jekyll::Drops::ExcerptDrop.new(self)
|
||||
doc.data['excerpt'] = nil
|
||||
@to_liquid ||= doc.to_liquid
|
||||
doc.data['excerpt'] = self
|
||||
@to_liquid
|
||||
end
|
||||
|
||||
# Returns the shorthand String identifier of this doc.
|
||||
@@ -117,7 +120,7 @@ module Jekyll
|
||||
if tail.empty?
|
||||
head
|
||||
else
|
||||
"" << head << "\n\n" << tail.scan(%r!^\[[^\]]+\]:.+$!).join("\n")
|
||||
"" << head << "\n\n" << tail.scan(/^\[[^\]]+\]:.+$/).join("\n")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -17,13 +17,13 @@ module Jekyll
|
||||
#
|
||||
# names - a string gem name or array of gem names
|
||||
#
|
||||
def require_if_present(names)
|
||||
def require_if_present(names, &block)
|
||||
Array(names).each do |name|
|
||||
begin
|
||||
require name
|
||||
rescue LoadError
|
||||
Jekyll.logger.debug "Couldn't load #{name}. Skipping."
|
||||
yield(name) if block_given?
|
||||
block.call(name) if block
|
||||
false
|
||||
end
|
||||
end
|
||||
@@ -39,7 +39,7 @@ module Jekyll
|
||||
def require_with_graceful_fail(names)
|
||||
Array(names).each do |name|
|
||||
begin
|
||||
Jekyll.logger.debug "Requiring:", name.to_s
|
||||
Jekyll.logger.debug "Requiring:", "#{name}"
|
||||
require name
|
||||
rescue LoadError => e
|
||||
Jekyll.logger.error "Dependency Error:", <<-MSG
|
||||
@@ -50,7 +50,7 @@ The full error message from Ruby is: '#{e.message}'
|
||||
|
||||
If you run into trouble, you can find helpful resources at http://jekyllrb.com/help/!
|
||||
MSG
|
||||
raise Jekyll::Errors::MissingDependencyException, name
|
||||
raise Jekyll::Errors::MissingDependencyException.new(name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
require "uri"
|
||||
require "json"
|
||||
require "date"
|
||||
require "liquid"
|
||||
require 'uri'
|
||||
require 'json'
|
||||
require 'date'
|
||||
|
||||
module Jekyll
|
||||
module Filters
|
||||
@@ -13,7 +12,7 @@ module Jekyll
|
||||
def markdownify(input)
|
||||
site = @context.registers[:site]
|
||||
converter = site.find_converter_instance(Jekyll::Converters::Markdown)
|
||||
converter.convert(input.to_s)
|
||||
converter.convert(input)
|
||||
end
|
||||
|
||||
# Convert quotes into smart quotes.
|
||||
@@ -24,7 +23,7 @@ module Jekyll
|
||||
def smartify(input)
|
||||
site = @context.registers[:site]
|
||||
converter = site.find_converter_instance(Jekyll::Converters::SmartyPants)
|
||||
converter.convert(input.to_s)
|
||||
converter.convert(input)
|
||||
end
|
||||
|
||||
# Convert a Sass string into CSS output.
|
||||
@@ -56,7 +55,7 @@ module Jekyll
|
||||
#
|
||||
# Returns the given filename or title as a lowercase URL String.
|
||||
# See Utils.slugify for more detail.
|
||||
def slugify(input, mode = nil)
|
||||
def slugify(input, mode=nil)
|
||||
Utils.slugify(input, :mode => mode)
|
||||
end
|
||||
|
||||
@@ -118,7 +117,7 @@ module Jekyll
|
||||
#
|
||||
# Returns the escaped String.
|
||||
def xml_escape(input)
|
||||
input.to_s.encode(:xml => :attr).gsub(%r!\A"|"\Z!, "")
|
||||
input.to_s.encode(:xml => :attr).gsub(/\A"|"\Z/, "")
|
||||
end
|
||||
|
||||
# CGI escape a string for use in a URL. Replaces any special characters
|
||||
@@ -133,7 +132,7 @@ module Jekyll
|
||||
#
|
||||
# Returns the escaped String.
|
||||
def cgi_escape(input)
|
||||
CGI.escape(input)
|
||||
CGI::escape(input)
|
||||
end
|
||||
|
||||
# URI escape a string.
|
||||
@@ -150,15 +149,6 @@ module Jekyll
|
||||
URI.escape(input)
|
||||
end
|
||||
|
||||
# Replace any whitespace in the input string with a single space
|
||||
#
|
||||
# input - The String on which to operate.
|
||||
#
|
||||
# Returns the formatted String
|
||||
def normalize_whitespace(input)
|
||||
input.to_s.gsub(%r!\s+!, " ").strip
|
||||
end
|
||||
|
||||
# Count the number of words in the input string.
|
||||
#
|
||||
# input - The String on which to operate.
|
||||
@@ -189,7 +179,7 @@ module Jekyll
|
||||
when 2
|
||||
"#{array[0]} #{connector} #{array[1]}"
|
||||
else
|
||||
"#{array[0...-1].join(", ")}, #{connector} #{array[-1]}"
|
||||
"#{array[0...-1].join(', ')}, #{connector} #{array[-1]}"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -212,14 +202,11 @@ module Jekyll
|
||||
# "items" => [...] } # all the items where `property` == "larry"
|
||||
def group_by(input, property)
|
||||
if groupable?(input)
|
||||
input.group_by { |item| item_property(item, property).to_s }
|
||||
.each_with_object([]) do |item, array|
|
||||
array << {
|
||||
"name" => item.first,
|
||||
"items" => item.last,
|
||||
"size" => item.last.size
|
||||
}
|
||||
end
|
||||
input.group_by do |item|
|
||||
item_property(item, property).to_s
|
||||
end.inject([]) do |memo, i|
|
||||
memo << { "name" => i.first, "items" => i.last, "size" => i.last.size }
|
||||
end
|
||||
else
|
||||
input
|
||||
end
|
||||
@@ -235,29 +222,7 @@ module Jekyll
|
||||
def where(input, property, value)
|
||||
return input unless input.is_a?(Enumerable)
|
||||
input = input.values if input.is_a?(Hash)
|
||||
input.select do |object|
|
||||
Array(item_property(object, property)).map(&:to_s).include?(value.to_s)
|
||||
end
|
||||
end
|
||||
|
||||
# Filters an array of objects against an expression
|
||||
#
|
||||
# input - the object array
|
||||
# variable - the variable to assign each item to in the expression
|
||||
# expression - a Liquid comparison expression passed in as a string
|
||||
#
|
||||
# Returns the filtered array of objects
|
||||
def where_exp(input, variable, expression)
|
||||
return input unless input.is_a?(Enumerable)
|
||||
input = input.values if input.is_a?(Hash) # FIXME
|
||||
|
||||
condition = parse_condition(expression)
|
||||
@context.stack do
|
||||
input.select do |object|
|
||||
@context[variable] = object
|
||||
condition.evaluate(@context)
|
||||
end
|
||||
end
|
||||
input.select { |object| Array(item_property(object, property)).map(&:to_s).include?(value.to_s) }
|
||||
end
|
||||
|
||||
# Sort an array of objects
|
||||
@@ -269,21 +234,33 @@ module Jekyll
|
||||
# Returns the filtered array of objects
|
||||
def sort(input, property = nil, nils = "first")
|
||||
if input.nil?
|
||||
raise ArgumentError, "Cannot sort a null object."
|
||||
raise ArgumentError.new("Cannot sort a null object.")
|
||||
end
|
||||
if property.nil?
|
||||
input.sort
|
||||
else
|
||||
if nils == "first"
|
||||
case
|
||||
when nils == "first"
|
||||
order = - 1
|
||||
elsif nils == "last"
|
||||
when nils == "last"
|
||||
order = + 1
|
||||
else
|
||||
raise ArgumentError, "Invalid nils order: " \
|
||||
"'#{nils}' is not a valid nils order. It must be 'first' or 'last'."
|
||||
raise ArgumentError.new("Invalid nils order: " \
|
||||
"'#{nils}' is not a valid nils order. It must be 'first' or 'last'.")
|
||||
end
|
||||
|
||||
sort_input(input, property, order)
|
||||
input.sort do |apple, orange|
|
||||
apple_property = item_property(apple, property)
|
||||
orange_property = item_property(orange, property)
|
||||
|
||||
if !apple_property.nil? && orange_property.nil?
|
||||
- order
|
||||
elsif apple_property.nil? && !orange_property.nil?
|
||||
+ order
|
||||
else
|
||||
apple_property <=> orange_property
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -334,22 +311,6 @@ module Jekyll
|
||||
xml_escape(input.inspect)
|
||||
end
|
||||
|
||||
private
|
||||
def sort_input(input, property, order)
|
||||
input.sort do |apple, orange|
|
||||
apple_property = item_property(apple, property)
|
||||
orange_property = item_property(orange, property)
|
||||
|
||||
if !apple_property.nil? && orange_property.nil?
|
||||
- order
|
||||
elsif apple_property.nil? && !orange_property.nil?
|
||||
+ order
|
||||
else
|
||||
apple_property <=> orange_property
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def time(input)
|
||||
case input
|
||||
@@ -367,12 +328,10 @@ module Jekyll
|
||||
end.localtime
|
||||
end
|
||||
|
||||
private
|
||||
def groupable?(element)
|
||||
element.respond_to?(:group_by)
|
||||
end
|
||||
|
||||
private
|
||||
def item_property(item, property)
|
||||
if item.respond_to?(:to_liquid)
|
||||
item.to_liquid[property.to_s]
|
||||
@@ -383,7 +342,6 @@ module Jekyll
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def as_liquid(item)
|
||||
case item
|
||||
when Hash
|
||||
@@ -405,26 +363,5 @@ module Jekyll
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Parse a string to a Liquid Condition
|
||||
private
|
||||
def parse_condition(exp)
|
||||
parser = Liquid::Parser.new(exp)
|
||||
left_expr = parser.expression
|
||||
operator = parser.consume?(:comparison)
|
||||
condition =
|
||||
if operator
|
||||
Liquid::Condition.new(left_expr, operator, parser.expression)
|
||||
else
|
||||
Liquid::Condition.new(left_expr)
|
||||
end
|
||||
parser.consume(:end_of_string)
|
||||
|
||||
condition
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Liquid::Template.register_filter(
|
||||
Jekyll::Filters
|
||||
)
|
||||
|
||||
@@ -11,42 +11,37 @@ module Jekyll
|
||||
end
|
||||
|
||||
def update_deprecated_types(set)
|
||||
return set unless set.key?("scope") && set["scope"].key?("type")
|
||||
return set unless set.key?('scope') && set['scope'].key?('type')
|
||||
|
||||
set["scope"]["type"] =
|
||||
case set["scope"]["type"]
|
||||
when "page"
|
||||
Deprecator.defaults_deprecate_type("page", "pages")
|
||||
"pages"
|
||||
when "post"
|
||||
Deprecator.defaults_deprecate_type("post", "posts")
|
||||
"posts"
|
||||
when "draft"
|
||||
Deprecator.defaults_deprecate_type("draft", "drafts")
|
||||
"drafts"
|
||||
set['scope']['type'] =
|
||||
case set['scope']['type']
|
||||
when 'page'
|
||||
Deprecator.defaults_deprecate_type('page', 'pages')
|
||||
'pages'
|
||||
when 'post'
|
||||
Deprecator.defaults_deprecate_type('post', 'posts')
|
||||
'posts'
|
||||
when 'draft'
|
||||
Deprecator.defaults_deprecate_type('draft', 'drafts')
|
||||
'drafts'
|
||||
else
|
||||
set["scope"]["type"]
|
||||
set['scope']['type']
|
||||
end
|
||||
|
||||
set
|
||||
end
|
||||
|
||||
def ensure_time!(set)
|
||||
return set unless set.key?("values") && set["values"].key?("date")
|
||||
return set if set["values"]["date"].is_a?(Time)
|
||||
set["values"]["date"] = Utils.parse_date(
|
||||
set["values"]["date"],
|
||||
"An invalid date format was found in a front-matter default set: #{set}"
|
||||
)
|
||||
return set unless set.key?('values') && set['values'].key?('date')
|
||||
return set if set['values']['date'].is_a?(Time)
|
||||
set['values']['date'] = Utils.parse_date(set['values']['date'], "An invalid date format was found in a front-matter default set: #{set}")
|
||||
set
|
||||
end
|
||||
|
||||
# Finds a default value for a given setting, filtered by path and type
|
||||
#
|
||||
# path - the path (relative to the source) of the page,
|
||||
# post or :draft the default is used in
|
||||
# type - a symbol indicating whether a :page,
|
||||
# a :post or a :draft calls this method
|
||||
# path - the path (relative to the source) of the page, post or :draft the default is used in
|
||||
# type - a symbol indicating whether a :page, a :post or a :draft calls this method
|
||||
#
|
||||
# Returns the default value or nil if none was found
|
||||
def find(path, type, setting)
|
||||
@@ -54,9 +49,9 @@ module Jekyll
|
||||
old_scope = nil
|
||||
|
||||
matching_sets(path, type).each do |set|
|
||||
if set["values"].key?(setting) && has_precedence?(old_scope, set["scope"])
|
||||
value = set["values"][setting]
|
||||
old_scope = set["scope"]
|
||||
if set['values'].key?(setting) && has_precedence?(old_scope, set['scope'])
|
||||
value = set['values'][setting]
|
||||
old_scope = set['scope']
|
||||
end
|
||||
end
|
||||
value
|
||||
@@ -72,11 +67,11 @@ module Jekyll
|
||||
defaults = {}
|
||||
old_scope = nil
|
||||
matching_sets(path, type).each do |set|
|
||||
if has_precedence?(old_scope, set["scope"])
|
||||
defaults = Utils.deep_merge_hashes(defaults, set["values"])
|
||||
old_scope = set["scope"]
|
||||
if has_precedence?(old_scope, set['scope'])
|
||||
defaults = Utils.deep_merge_hashes(defaults, set['values'])
|
||||
old_scope = set['scope']
|
||||
else
|
||||
defaults = Utils.deep_merge_hashes(set["values"], defaults)
|
||||
defaults = Utils.deep_merge_hashes(set['values'], defaults)
|
||||
end
|
||||
end
|
||||
defaults
|
||||
@@ -96,9 +91,9 @@ module Jekyll
|
||||
end
|
||||
|
||||
def applies_path?(scope, path)
|
||||
return true if !scope.key?("path") || scope["path"].empty?
|
||||
return true if !scope.key?('path') || scope['path'].empty?
|
||||
|
||||
scope_path = Pathname.new(scope["path"])
|
||||
scope_path = Pathname.new(scope['path'])
|
||||
Pathname.new(sanitize_path(path)).ascend do |ascended_path|
|
||||
if ascended_path.to_s == scope_path.to_s
|
||||
return true
|
||||
@@ -118,7 +113,7 @@ module Jekyll
|
||||
# Returns true if either of the above conditions are satisfied,
|
||||
# otherwise returns false
|
||||
def applies_type?(scope, type)
|
||||
!scope.key?("type") || scope["type"].eql?(type.to_s)
|
||||
!scope.key?('type') || scope['type'].eql?(type.to_s)
|
||||
end
|
||||
|
||||
# Checks if a given set of default values is valid
|
||||
@@ -127,7 +122,7 @@ module Jekyll
|
||||
#
|
||||
# Returns true if the set is valid and can be used in this class
|
||||
def valid?(set)
|
||||
set.is_a?(Hash) && set["values"].is_a?(Hash)
|
||||
set.is_a?(Hash) && set['values'].is_a?(Hash)
|
||||
end
|
||||
|
||||
# Determines if a new scope has precedence over an old one
|
||||
@@ -136,29 +131,27 @@ module Jekyll
|
||||
# new_scope - the new scope hash
|
||||
#
|
||||
# Returns true if the new scope has precedence over the older
|
||||
# rubocop: disable PredicateName
|
||||
def has_precedence?(old_scope, new_scope)
|
||||
return true if old_scope.nil?
|
||||
|
||||
new_path = sanitize_path(new_scope["path"])
|
||||
old_path = sanitize_path(old_scope["path"])
|
||||
new_path = sanitize_path(new_scope['path'])
|
||||
old_path = sanitize_path(old_scope['path'])
|
||||
|
||||
if new_path.length != old_path.length
|
||||
new_path.length >= old_path.length
|
||||
elsif new_scope.key?("type")
|
||||
elsif new_scope.key? 'type'
|
||||
true
|
||||
else
|
||||
!old_scope.key? "type"
|
||||
!old_scope.key? 'type'
|
||||
end
|
||||
end
|
||||
# rubocop: enable PredicateName
|
||||
|
||||
# Collects a list of sets that match the given path and type
|
||||
#
|
||||
# Returns an array of hashes
|
||||
def matching_sets(path, type)
|
||||
valid_sets.select do |set|
|
||||
!set.key?("scope") || applies?(set["scope"], path, type)
|
||||
!set.key?('scope') || applies?(set['scope'], path, type)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -169,7 +162,7 @@ module Jekyll
|
||||
#
|
||||
# Returns an array of hashes
|
||||
def valid_sets
|
||||
sets = @site.config["defaults"]
|
||||
sets = @site.config['defaults']
|
||||
return [] unless sets.is_a?(Array)
|
||||
|
||||
sets.map do |set|
|
||||
@@ -177,7 +170,7 @@ module Jekyll
|
||||
ensure_time!(update_deprecated_types(set))
|
||||
else
|
||||
Jekyll.logger.warn "Defaults:", "An invalid front-matter default set was found:"
|
||||
Jekyll.logger.warn set.to_s
|
||||
Jekyll.logger.warn "#{set}"
|
||||
nil
|
||||
end
|
||||
end.compact
|
||||
@@ -188,7 +181,7 @@ module Jekyll
|
||||
if path.nil? || path.empty?
|
||||
""
|
||||
else
|
||||
path.gsub(%r!\A/!, "").gsub(%r!([^/])\z!, '\1')
|
||||
path.gsub(/\A\//, '').gsub(/([^\/])\z/, '\1')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,38 +4,38 @@ module Jekyll
|
||||
|
||||
# compatibility layer for octopress-hooks users
|
||||
PRIORITY_MAP = {
|
||||
:low => 10,
|
||||
:low => 10,
|
||||
:normal => 20,
|
||||
:high => 30
|
||||
:high => 30
|
||||
}.freeze
|
||||
|
||||
# initial empty hooks
|
||||
@registry = {
|
||||
:site => {
|
||||
:after_init => [],
|
||||
:site => {
|
||||
:after_init => [],
|
||||
:after_reset => [],
|
||||
:post_read => [],
|
||||
:pre_render => [],
|
||||
:post_read => [],
|
||||
:pre_render => [],
|
||||
:post_render => [],
|
||||
:post_write => []
|
||||
:post_write => []
|
||||
},
|
||||
:pages => {
|
||||
:post_init => [],
|
||||
:pre_render => [],
|
||||
:pages => {
|
||||
:post_init => [],
|
||||
:pre_render => [],
|
||||
:post_render => [],
|
||||
:post_write => []
|
||||
:post_write => []
|
||||
},
|
||||
:posts => {
|
||||
:post_init => [],
|
||||
:pre_render => [],
|
||||
:posts => {
|
||||
:post_init => [],
|
||||
:pre_render => [],
|
||||
:post_render => [],
|
||||
:post_write => []
|
||||
:post_write => []
|
||||
},
|
||||
:documents => {
|
||||
:post_init => [],
|
||||
:pre_render => [],
|
||||
:post_init => [],
|
||||
:pre_render => [],
|
||||
:post_render => [],
|
||||
:post_write => []
|
||||
:post_write => []
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,10 +61,10 @@ module Jekyll
|
||||
# register a single hook to be called later, internal API
|
||||
def self.register_one(owner, event, priority, &block)
|
||||
@registry[owner] ||={
|
||||
:post_init => [],
|
||||
:pre_render => [],
|
||||
:post_init => [],
|
||||
:pre_render => [],
|
||||
:post_render => [],
|
||||
:post_write => []
|
||||
:post_write => []
|
||||
}
|
||||
|
||||
unless @registry[owner][event]
|
||||
|
||||
@@ -29,14 +29,7 @@ module Jekyll
|
||||
@site = site
|
||||
@base = base
|
||||
@name = name
|
||||
|
||||
if site.theme && site.theme.layouts_path.eql?(base)
|
||||
@base_dir = site.theme.root
|
||||
@path = site.in_theme_dir(base, name)
|
||||
else
|
||||
@base_dir = site.source
|
||||
@path = site.in_source_dir(base, name)
|
||||
end
|
||||
@path = site.in_source_dir(base, name)
|
||||
|
||||
self.data = {}
|
||||
|
||||
@@ -52,15 +45,5 @@ module Jekyll
|
||||
def process(name)
|
||||
self.ext = File.extname(name)
|
||||
end
|
||||
|
||||
# The path to the layout, relative to the site source.
|
||||
#
|
||||
# Returns a String path which represents the relative path
|
||||
# from the site source to this layout
|
||||
def relative_path
|
||||
@relative_path ||= Pathname.new(path).relative_path_from(
|
||||
Pathname.new(@base_dir)
|
||||
).to_s
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
require "jekyll/liquid_renderer/file"
|
||||
require "jekyll/liquid_renderer/table"
|
||||
require 'jekyll/liquid_renderer/file'
|
||||
require 'jekyll/liquid_renderer/table'
|
||||
|
||||
module Jekyll
|
||||
class LiquidRenderer
|
||||
@@ -13,10 +13,7 @@ module Jekyll
|
||||
end
|
||||
|
||||
def file(filename)
|
||||
filename = @site.in_source_dir(filename).sub(
|
||||
%r!\A#{Regexp.escape(@site.source)}/!,
|
||||
""
|
||||
)
|
||||
filename = @site.in_source_dir(filename).sub(/\A#{Regexp.escape(@site.source)}\//, '')
|
||||
|
||||
LiquidRenderer::File.new(self, filename).tap do
|
||||
@stats[filename] ||= {}
|
||||
|
||||
@@ -8,7 +8,7 @@ module Jekyll
|
||||
|
||||
def parse(content)
|
||||
measure_time do
|
||||
@template = Liquid::Template.parse(content, :line_numbers => true)
|
||||
@template = Liquid::Template.parse(content, line_numbers: true)
|
||||
end
|
||||
|
||||
self
|
||||
|
||||
@@ -31,8 +31,8 @@ module Jekyll
|
||||
str = ""
|
||||
|
||||
row_data.each_index do |cell_index|
|
||||
str << "-" * widths[cell_index]
|
||||
str << "-+-" unless cell_index == row_data.length-1
|
||||
str << '-' * widths[cell_index]
|
||||
str << '-+-' unless cell_index == row_data.length-1
|
||||
end
|
||||
|
||||
str << "\n"
|
||||
@@ -40,16 +40,16 @@ module Jekyll
|
||||
end
|
||||
|
||||
def generate_row(row_data, widths)
|
||||
str = ""
|
||||
str = ''
|
||||
|
||||
row_data.each_with_index do |cell_data, cell_index|
|
||||
str << if cell_index == 0
|
||||
cell_data.ljust(widths[cell_index], " ")
|
||||
else
|
||||
cell_data.rjust(widths[cell_index], " ")
|
||||
end
|
||||
if cell_index == 0
|
||||
str << cell_data.ljust(widths[cell_index], ' ')
|
||||
else
|
||||
str << cell_data.rjust(widths[cell_index], ' ')
|
||||
end
|
||||
|
||||
str << " | " unless cell_index == row_data.length-1
|
||||
str << ' | ' unless cell_index == row_data.length-1
|
||||
end
|
||||
|
||||
str << "\n"
|
||||
@@ -79,7 +79,7 @@ module Jekyll
|
||||
row << filename
|
||||
row << file_stats[:count].to_s
|
||||
row << format_bytes(file_stats[:bytes])
|
||||
row << format("%.3f", file_stats[:time])
|
||||
row << "%.3f" % file_stats[:time]
|
||||
table << row
|
||||
end
|
||||
|
||||
@@ -88,7 +88,7 @@ module Jekyll
|
||||
|
||||
def format_bytes(bytes)
|
||||
bytes /= 1024.0
|
||||
format("%.2fK", bytes)
|
||||
"%.2fK" % bytes
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -7,7 +7,7 @@ module Jekyll
|
||||
:info => ::Logger::INFO,
|
||||
:warn => ::Logger::WARN,
|
||||
:error => ::Logger::ERROR
|
||||
}.freeze
|
||||
}
|
||||
|
||||
# Public: Create a new instance of a log writer
|
||||
#
|
||||
@@ -98,7 +98,7 @@ module Jekyll
|
||||
#
|
||||
# Returns the formatted message
|
||||
def message(topic, message)
|
||||
msg = formatted_topic(topic) + message.to_s.gsub(%r!\s+!, " ")
|
||||
msg = formatted_topic(topic) + message.to_s.gsub(/\s+/, ' ')
|
||||
messages << msg
|
||||
msg
|
||||
end
|
||||
|
||||
@@ -9,7 +9,7 @@ module Jekyll
|
||||
|
||||
alias_method :extname, :ext
|
||||
|
||||
FORWARD_SLASH = "/".freeze
|
||||
FORWARD_SLASH = '/'.freeze
|
||||
|
||||
# Attributes for Liquid templates
|
||||
ATTRIBUTES_FOR_LIQUID = %w(
|
||||
@@ -18,16 +18,16 @@ module Jekyll
|
||||
name
|
||||
path
|
||||
url
|
||||
).freeze
|
||||
)
|
||||
|
||||
# A set of extensions that are considered HTML or HTML-like so we
|
||||
# should not alter them, this includes .xhtml through XHTM5.
|
||||
|
||||
HTML_EXTENSIONS = %w(
|
||||
HTML_EXTENSIONS = %W(
|
||||
.html
|
||||
.xhtml
|
||||
.htm
|
||||
).freeze
|
||||
)
|
||||
|
||||
# Initialize a new Page.
|
||||
#
|
||||
@@ -40,7 +40,6 @@ module Jekyll
|
||||
@base = base
|
||||
@dir = dir
|
||||
@name = name
|
||||
@path = site.in_source_dir(base, dir, name)
|
||||
|
||||
process(name)
|
||||
read_yaml(File.join(base, dir), name)
|
||||
@@ -71,7 +70,7 @@ module Jekyll
|
||||
#
|
||||
# Returns the String permalink or nil if none has been set.
|
||||
def permalink
|
||||
data.nil? ? nil : data["permalink"]
|
||||
data.nil? ? nil : data['permalink']
|
||||
end
|
||||
|
||||
# The template of the permalink.
|
||||
@@ -92,9 +91,9 @@ module Jekyll
|
||||
# Returns the String url.
|
||||
def url
|
||||
@url ||= URL.new({
|
||||
:template => template,
|
||||
:template => template,
|
||||
:placeholders => url_placeholders,
|
||||
:permalink => permalink
|
||||
:permalink => permalink
|
||||
}).to_s
|
||||
end
|
||||
|
||||
@@ -135,12 +134,12 @@ module Jekyll
|
||||
#
|
||||
# Returns the path to the source file
|
||||
def path
|
||||
data.fetch("path") { relative_path }
|
||||
data.fetch('path') { relative_path.sub(/\A\//, '') }
|
||||
end
|
||||
|
||||
# The path to the page source file, relative to the site source
|
||||
def relative_path
|
||||
File.join(*[@dir, @name].map(&:to_s).reject(&:empty?)).sub(%r!\A\/!, "")
|
||||
File.join(*[@dir, @name].map(&:to_s).reject(&:empty?))
|
||||
end
|
||||
|
||||
# Obtain destination path.
|
||||
@@ -167,7 +166,7 @@ module Jekyll
|
||||
|
||||
# Returns the Boolean of whether this Page is an index file or not.
|
||||
def index?
|
||||
basename == "index"
|
||||
basename == 'index'
|
||||
end
|
||||
|
||||
def trigger_hooks(hook_name, *args)
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
module Jekyll
|
||||
class Plugin
|
||||
PRIORITIES = {
|
||||
:low => -10,
|
||||
:low => -10,
|
||||
:highest => 100,
|
||||
:lowest => -100,
|
||||
:normal => 0,
|
||||
:high => 10
|
||||
}.freeze
|
||||
:lowest => -100,
|
||||
:normal => 0,
|
||||
:high => 10
|
||||
}
|
||||
|
||||
#
|
||||
|
||||
|
||||
@@ -24,25 +24,22 @@ module Jekyll
|
||||
#
|
||||
# Returns nothing.
|
||||
def require_gems
|
||||
Jekyll::External.require_with_graceful_fail(
|
||||
site.gems.select { |gem| plugin_allowed?(gem) }
|
||||
)
|
||||
Jekyll::External.require_with_graceful_fail(site.gems.select { |gem| plugin_allowed?(gem) })
|
||||
end
|
||||
|
||||
def self.require_from_bundler
|
||||
if !ENV["JEKYLL_NO_BUNDLER_REQUIRE"] && File.file?("Gemfile")
|
||||
require "bundler"
|
||||
|
||||
Bundler.setup
|
||||
required_gems = Bundler.require(:jekyll_plugins)
|
||||
message = "Required #{required_gems.map(&:name).join(", ")}"
|
||||
Jekyll.logger.debug("PluginManager:", message)
|
||||
Bundler.setup # puts all groups on the load path
|
||||
required_gems = Bundler.require(:jekyll_plugins) # requires the gems in this group only
|
||||
Jekyll.logger.debug("PluginManager:", "Required #{required_gems.map(&:name).join(', ')}")
|
||||
ENV["JEKYLL_NO_BUNDLER_REQUIRE"] = "true"
|
||||
|
||||
true
|
||||
else
|
||||
false
|
||||
end
|
||||
rescue LoadError, Bundler::GemfileNotFound
|
||||
false
|
||||
end
|
||||
|
||||
# Check whether a gem plugin is allowed to be used during this build.
|
||||
@@ -60,7 +57,7 @@ module Jekyll
|
||||
# Returns an array of strings, each string being the name of a gem name
|
||||
# that is allowed to be used.
|
||||
def whitelist
|
||||
@whitelist ||= Array[site.config["whitelist"]].flatten
|
||||
@whitelist ||= Array[site.config['whitelist']].flatten
|
||||
end
|
||||
|
||||
# Require all .rb files if safe mode is off
|
||||
@@ -79,17 +76,16 @@ module Jekyll
|
||||
#
|
||||
# Returns an Array of plugin search paths
|
||||
def plugins_path
|
||||
if site.config["plugins_dir"].eql? Jekyll::Configuration::DEFAULTS["plugins_dir"]
|
||||
[site.in_source_dir(site.config["plugins_dir"])]
|
||||
if site.config['plugins_dir'] == Jekyll::Configuration::DEFAULTS['plugins_dir']
|
||||
[site.in_source_dir(site.config['plugins_dir'])]
|
||||
else
|
||||
Array(site.config["plugins_dir"]).map { |d| File.expand_path(d) }
|
||||
Array(site.config['plugins_dir']).map { |d| File.expand_path(d) }
|
||||
end
|
||||
end
|
||||
|
||||
def deprecation_checks
|
||||
pagination_included = (site.config["gems"] || []).include?("jekyll-paginate") ||
|
||||
defined?(Jekyll::Paginate)
|
||||
if site.config["paginate"] && !pagination_included
|
||||
pagination_included = (site.config['gems'] || []).include?('jekyll-paginate') || defined?(Jekyll::Paginate)
|
||||
if site.config['paginate'] && !pagination_included
|
||||
Jekyll::Deprecator.deprecation_message "You appear to have pagination " \
|
||||
"turned on, but you haven't included the `jekyll-paginate` gem. " \
|
||||
"Ensure you have `gems: [jekyll-paginate]` in your configuration file."
|
||||
|
||||
@@ -15,7 +15,7 @@ module Jekyll
|
||||
private
|
||||
|
||||
def can_be_published?(thing)
|
||||
thing.data.fetch("published", true) || @site.unpublished
|
||||
thing.data.fetch('published', true) || @site.unpublished
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# encoding: UTF-8
|
||||
require "csv"
|
||||
require 'csv'
|
||||
|
||||
module Jekyll
|
||||
class Reader
|
||||
@@ -16,7 +16,7 @@ module Jekyll
|
||||
@site.layouts = LayoutReader.new(site).read
|
||||
read_directories
|
||||
sort_files!
|
||||
@site.data = DataReader.new(site).read(site.config["data_dir"])
|
||||
@site.data = DataReader.new(site).read(site.config['data_dir'])
|
||||
CollectionReader.new(site).read
|
||||
end
|
||||
|
||||
@@ -34,15 +34,13 @@ module Jekyll
|
||||
# dir - The String relative path of the directory to read. Default: ''.
|
||||
#
|
||||
# Returns nothing.
|
||||
def read_directories(dir = "")
|
||||
def read_directories(dir = '')
|
||||
base = site.in_source_dir(dir)
|
||||
|
||||
dot = Dir.chdir(base) { filter_entries(Dir.entries("."), base) }
|
||||
dot = Dir.chdir(base) { filter_entries(Dir.entries('.'), base) }
|
||||
dot_dirs = dot.select { |file| File.directory?(@site.in_source_dir(base, file)) }
|
||||
dot_files = (dot - dot_dirs)
|
||||
dot_pages = dot_files.select do |file|
|
||||
Utils.has_yaml_header?(@site.in_source_dir(base, file))
|
||||
end
|
||||
dot_pages = dot_files.select { |file| Utils.has_yaml_header?(@site.in_source_dir(base, file)) }
|
||||
dot_static_files = dot_files - dot_pages
|
||||
|
||||
retrieve_posts(dir)
|
||||
@@ -73,9 +71,7 @@ module Jekyll
|
||||
dot_dirs.map do |file|
|
||||
dir_path = site.in_source_dir(dir, file)
|
||||
rel_path = File.join(dir, file)
|
||||
unless @site.dest.sub(%r!/$!, "") == dir_path
|
||||
@site.reader.read_directories(rel_path)
|
||||
end
|
||||
@site.reader.read_directories(rel_path) unless @site.dest.sub(/\/$/, '') == dir_path
|
||||
end
|
||||
end
|
||||
|
||||
@@ -123,7 +119,7 @@ module Jekyll
|
||||
def get_entries(dir, subfolder)
|
||||
base = site.in_source_dir(dir, subfolder)
|
||||
return [] unless File.exist?(base)
|
||||
entries = Dir.chdir(base) { filter_entries(Dir["**/*"], base) }
|
||||
entries = Dir.chdir(base) { filter_entries(Dir['**/*'], base) }
|
||||
entries.delete_if { |e| File.directory?(site.in_source_dir(base, e)) }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,7 +4,6 @@ module Jekyll
|
||||
def initialize(site)
|
||||
@site = site
|
||||
@content = {}
|
||||
@entry_filter = EntryFilter.new(site)
|
||||
end
|
||||
|
||||
# Read all the files in <source>/<dir>/_drafts and create a new Draft
|
||||
@@ -27,17 +26,17 @@ module Jekyll
|
||||
#
|
||||
# Returns nothing
|
||||
def read_data_to(dir, data)
|
||||
return unless File.directory?(dir) && !@entry_filter.symlink?(dir)
|
||||
return unless File.directory?(dir) && (!site.safe || !File.symlink?(dir))
|
||||
|
||||
entries = Dir.chdir(dir) do
|
||||
Dir["*.{yaml,yml,json,csv}"] + Dir["*"].select { |fn| File.directory?(fn) }
|
||||
Dir['*.{yaml,yml,json,csv}'] + Dir['*'].select { |fn| File.directory?(fn) }
|
||||
end
|
||||
|
||||
entries.each do |entry|
|
||||
path = @site.in_source_dir(dir, entry)
|
||||
next if @entry_filter.symlink?(path)
|
||||
next if File.symlink?(path) && site.safe
|
||||
|
||||
key = sanitize_filename(File.basename(entry, ".*"))
|
||||
key = sanitize_filename(File.basename(entry, '.*'))
|
||||
if File.directory?(path)
|
||||
read_data_to(path, data[key] = {})
|
||||
else
|
||||
@@ -51,20 +50,20 @@ module Jekyll
|
||||
# Returns the contents of the data file.
|
||||
def read_data_file(path)
|
||||
case File.extname(path).downcase
|
||||
when ".csv"
|
||||
when '.csv'
|
||||
CSV.read(path, {
|
||||
:headers => true,
|
||||
:encoding => site.config["encoding"]
|
||||
}).map(&:to_hash)
|
||||
:headers => true,
|
||||
:encoding => site.config['encoding']
|
||||
}).map(&:to_hash)
|
||||
else
|
||||
SafeYAML.load_file(path)
|
||||
end
|
||||
end
|
||||
|
||||
def sanitize_filename(name)
|
||||
name.gsub!(%r![^\w\s-]+!, "")
|
||||
name.gsub!(%r!(^|\b\s)\s+($|\s?\b)!, '\\1\\2')
|
||||
name.gsub(%r!\s+!, "_")
|
||||
name.gsub!(/[^\w\s-]+/, '')
|
||||
name.gsub!(/(^|\b\s)\s+($|\s?\b)/, '\\1\\2')
|
||||
name.gsub(/\s+/, '_')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -7,14 +7,8 @@ module Jekyll
|
||||
end
|
||||
|
||||
def read
|
||||
layout_entries.each do |layout_file|
|
||||
@layouts[layout_name(layout_file)] = \
|
||||
Layout.new(site, layout_directory, layout_file)
|
||||
end
|
||||
|
||||
theme_layout_entries.each do |layout_file|
|
||||
@layouts[layout_name(layout_file)] ||= \
|
||||
Layout.new(site, theme_layout_directory, layout_file)
|
||||
layout_entries.each do |f|
|
||||
@layouts[layout_name(f)] = Layout.new(site, layout_directory, f)
|
||||
end
|
||||
|
||||
@layouts
|
||||
@@ -24,24 +18,12 @@ module Jekyll
|
||||
@layout_directory ||= (layout_directory_in_cwd || layout_directory_inside_source)
|
||||
end
|
||||
|
||||
def theme_layout_directory
|
||||
@theme_layout_directory ||= site.theme.layouts_path if site.theme
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def layout_entries
|
||||
entries_in layout_directory
|
||||
end
|
||||
|
||||
def theme_layout_entries
|
||||
theme_layout_directory ? entries_in(theme_layout_directory) : []
|
||||
end
|
||||
|
||||
def entries_in(dir)
|
||||
entries = []
|
||||
within(dir) do
|
||||
entries = EntryFilter.new(site).filter(Dir["**/*.*"])
|
||||
within(layout_directory) do
|
||||
entries = EntryFilter.new(site).filter(Dir['**/*.*'])
|
||||
end
|
||||
entries
|
||||
end
|
||||
@@ -56,13 +38,15 @@ module Jekyll
|
||||
end
|
||||
|
||||
def layout_directory_inside_source
|
||||
site.in_source_dir(site.config["layouts_dir"])
|
||||
site.in_source_dir(site.config['layouts_dir'])
|
||||
end
|
||||
|
||||
def layout_directory_in_cwd
|
||||
dir = Jekyll.sanitized_path(Dir.pwd, site.config["layouts_dir"])
|
||||
dir = Jekyll.sanitized_path(Dir.pwd, site.config['layouts_dir'])
|
||||
if File.directory?(dir) && !site.safe
|
||||
dir
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -14,9 +14,7 @@ module Jekyll
|
||||
#
|
||||
# Returns an array of static pages.
|
||||
def read(files)
|
||||
files.map do |page|
|
||||
@unfiltered_content << Page.new(@site, @site.source, @dir, page)
|
||||
end
|
||||
files.map { |page| @unfiltered_content << Page.new(@site, @site.source, @dir, page) }
|
||||
@unfiltered_content.select { |page| site.publisher.publish?(page) }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -12,7 +12,7 @@ module Jekyll
|
||||
#
|
||||
# Returns nothing.
|
||||
def read_drafts(dir)
|
||||
read_publishable(dir, "_drafts", Document::DATELESS_FILENAME_MATCHER)
|
||||
read_publishable(dir, '_drafts', Document::DATELESS_FILENAME_MATCHER)
|
||||
end
|
||||
|
||||
# Read all the files in <source>/<dir>/_posts and create a new Document
|
||||
@@ -22,7 +22,7 @@ module Jekyll
|
||||
#
|
||||
# Returns nothing.
|
||||
def read_posts(dir)
|
||||
read_publishable(dir, "_posts", Document::DATE_FILENAME_MATCHER)
|
||||
read_publishable(dir, '_posts', Document::DATE_FILENAME_MATCHER)
|
||||
end
|
||||
|
||||
# Read all the files in <source>/<dir>/<magic_dir> and create a new
|
||||
@@ -32,14 +32,15 @@ module Jekyll
|
||||
#
|
||||
# Returns nothing.
|
||||
def read_publishable(dir, magic_dir, matcher)
|
||||
read_content(dir, magic_dir, matcher).tap { |docs| docs.each(&:read) }
|
||||
.select do |doc|
|
||||
site.publisher.publish?(doc).tap do |will_publish|
|
||||
if !will_publish && site.publisher.hidden_in_the_future?(doc)
|
||||
Jekyll.logger.debug "Skipping:", "#{doc.relative_path} has a future date"
|
||||
end
|
||||
read_content(dir, magic_dir, matcher).tap do |docs|
|
||||
docs.each(&:read)
|
||||
end.select do |doc|
|
||||
site.publisher.publish?(doc).tap do |will_publish|
|
||||
if !will_publish && site.publisher.hidden_in_the_future?(doc)
|
||||
Jekyll.logger.debug "Skipping:", "#{doc.relative_path} has a future date"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Read all the content files from <source>/<dir>/magic_dir
|
||||
@@ -56,7 +57,7 @@ module Jekyll
|
||||
next unless entry =~ matcher
|
||||
path = @site.in_source_dir(File.join(dir, magic_dir, entry))
|
||||
Document.new(path, {
|
||||
:site => @site,
|
||||
:site => @site,
|
||||
:collection => @site.posts
|
||||
})
|
||||
end.reject(&:nil?)
|
||||
|
||||
@@ -14,9 +14,7 @@ module Jekyll
|
||||
#
|
||||
# Returns an array of static files.
|
||||
def read(files)
|
||||
files.map do |file|
|
||||
@unfiltered_content << StaticFile.new(@site, @site.source, @dir, file)
|
||||
end
|
||||
files.map { |file| @unfiltered_content << StaticFile.new(@site, @site.source, @dir, file) }
|
||||
@unfiltered_content
|
||||
end
|
||||
end
|
||||
|
||||
@@ -20,14 +20,18 @@ module Jekyll
|
||||
def regenerate?(document)
|
||||
case document
|
||||
when Page
|
||||
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)
|
||||
)
|
||||
when Document
|
||||
regenerate_document?(document)
|
||||
!document.write? || document.data['regenerate'] ||
|
||||
source_modified_or_dest_missing?(
|
||||
document.path, document.destination(@site.dest)
|
||||
)
|
||||
else
|
||||
source_path = document.respond_to?(:path) ? document.path : nil
|
||||
dest_path = if document.respond_to?(:destination)
|
||||
document.destination(@site.dest)
|
||||
end
|
||||
source_path = document.respond_to?(:path) ? document.path : nil
|
||||
dest_path = document.respond_to?(:destination) ? document.destination(@site.dest) : nil
|
||||
source_modified_or_dest_missing?(source_path, dest_path)
|
||||
end
|
||||
end
|
||||
@@ -40,7 +44,7 @@ module Jekyll
|
||||
|
||||
metadata[path] = {
|
||||
"mtime" => File.mtime(path),
|
||||
"deps" => []
|
||||
"deps" => []
|
||||
}
|
||||
cache[path] = true
|
||||
end
|
||||
@@ -90,14 +94,23 @@ module Jekyll
|
||||
return cache[path]
|
||||
end
|
||||
|
||||
if metadata[path]
|
||||
# If we have seen this file before,
|
||||
# check if it or one of its dependencies has been modified
|
||||
existing_file_modified?(path)
|
||||
else
|
||||
# If we have not seen this file before, add it to the metadata and regenerate it
|
||||
add(path)
|
||||
# Check path that exists in metadata
|
||||
data = metadata[path]
|
||||
if data
|
||||
data["deps"].each do |dependency|
|
||||
if modified?(dependency)
|
||||
return cache[dependency] = cache[path] = true
|
||||
end
|
||||
end
|
||||
if File.exist?(path) && data["mtime"].eql?(File.mtime(path))
|
||||
return cache[path] = false
|
||||
else
|
||||
return add(path)
|
||||
end
|
||||
end
|
||||
|
||||
# Path does not exist in metadata, add it
|
||||
return add(path)
|
||||
end
|
||||
|
||||
# Add a dependency of a path
|
||||
@@ -126,7 +139,7 @@ module Jekyll
|
||||
#
|
||||
# Returns the String path of the file.
|
||||
def metadata_file
|
||||
site.in_source_dir(".jekyll-metadata")
|
||||
site.in_source_dir('.jekyll-metadata')
|
||||
end
|
||||
|
||||
# Check if metadata has been disabled
|
||||
@@ -160,40 +173,5 @@ module Jekyll
|
||||
{}
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def regenerate_page?(document)
|
||||
document.asset_file? || document.data["regenerate"] ||
|
||||
source_modified_or_dest_missing?(
|
||||
site.in_source_dir(document.relative_path), document.destination(@site.dest)
|
||||
)
|
||||
end
|
||||
|
||||
private
|
||||
def regenerate_document?(document)
|
||||
!document.write? || document.data["regenerate"] ||
|
||||
source_modified_or_dest_missing?(
|
||||
document.path, document.destination(@site.dest)
|
||||
)
|
||||
end
|
||||
|
||||
private
|
||||
def existing_file_modified?(path)
|
||||
# If one of this file dependencies have been modified,
|
||||
# set the regeneration bit for both the dependency and the file to true
|
||||
metadata[path]["deps"].each do |dependency|
|
||||
if modified?(dependency)
|
||||
return cache[dependency] = cache[path] = true
|
||||
end
|
||||
end
|
||||
|
||||
if File.exist?(path) && metadata[path]["mtime"].eql?(File.mtime(path))
|
||||
# If this file has not been modified, set the regeneration bit to false
|
||||
cache[path] = false
|
||||
else
|
||||
# If it has been modified, set it to true
|
||||
add(path)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -9,7 +9,7 @@ module Jekyll
|
||||
def initialize(post)
|
||||
@post = post
|
||||
@site = post.site
|
||||
Jekyll::External.require_with_graceful_fail("classifier-reborn") if site.lsi
|
||||
Jekyll::External.require_with_graceful_fail('classifier-reborn') if site.lsi
|
||||
end
|
||||
|
||||
def build
|
||||
|
||||
@@ -38,21 +38,22 @@ module Jekyll
|
||||
payload["paginator"] = document.pager.to_liquid
|
||||
end
|
||||
|
||||
if document.is_a?(Document) && document.collection.label == "posts"
|
||||
payload["site"]["related_posts"] = document.related_posts
|
||||
if document.is_a?(Document) && document.collection.label == 'posts'
|
||||
payload['site']['related_posts'] = document.related_posts
|
||||
else
|
||||
payload["site"]["related_posts"] = nil
|
||||
payload['site']['related_posts'] = nil
|
||||
end
|
||||
|
||||
# render and transform content (this becomes the final content of the object)
|
||||
payload["highlighter_prefix"] = converters.first.highlighter_prefix
|
||||
payload["highlighter_suffix"] = converters.first.highlighter_suffix
|
||||
payload['highlighter_prefix'] = converters.first.highlighter_prefix
|
||||
payload['highlighter_suffix'] = converters.first.highlighter_suffix
|
||||
|
||||
Jekyll.logger.debug "Pre-Render Hooks:", document.relative_path
|
||||
document.trigger_hooks(:pre_render, payload)
|
||||
|
||||
info = {
|
||||
:registers => { :site => site, :page => payload["page"] }
|
||||
:filters => [Jekyll::Filters],
|
||||
:registers => { :site => site, :page => payload['page'] }
|
||||
}
|
||||
|
||||
output = document.content
|
||||
@@ -88,9 +89,7 @@ module Jekyll
|
||||
begin
|
||||
converter.convert output
|
||||
rescue => e
|
||||
Jekyll.logger.error "Conversion error:",
|
||||
"#{converter.class} encountered an error while "\
|
||||
"converting '#{document.relative_path}':"
|
||||
Jekyll.logger.error "Conversion error:", "#{converter.class} encountered an error while converting '#{document.relative_path}':"
|
||||
Jekyll.logger.error("", e.to_s)
|
||||
raise e
|
||||
end
|
||||
@@ -108,16 +107,12 @@ module Jekyll
|
||||
def render_liquid(content, payload, info, path = nil)
|
||||
site.liquid_renderer.file(path).parse(content).render!(payload, info)
|
||||
rescue Tags::IncludeTagError => e
|
||||
Jekyll.logger.error "Liquid Exception:",
|
||||
"#{e.message} in #{e.path}, included in #{path || document.relative_path}"
|
||||
Jekyll.logger.error "Liquid Exception:", "#{e.message} in #{e.path}, included in #{path || document.relative_path}"
|
||||
raise e
|
||||
# rubocop: disable RescueException
|
||||
rescue Exception => e
|
||||
Jekyll.logger.error "Liquid Exception:",
|
||||
"#{e.message} in #{path || document.relative_path}"
|
||||
Jekyll.logger.error "Liquid Exception:", "#{e.message} in #{path || document.relative_path}"
|
||||
raise e
|
||||
end
|
||||
# rubocop: enable RescueException
|
||||
|
||||
# Checks if the layout specified in the document actually exists
|
||||
#
|
||||
@@ -138,26 +133,20 @@ module Jekyll
|
||||
output = content.dup
|
||||
layout = site.layouts[document.data["layout"]]
|
||||
|
||||
Jekyll.logger.warn(
|
||||
"Build Warning:",
|
||||
"Layout '#{document.data["layout"]}' requested in "\
|
||||
"#{document.relative_path} does not exist."
|
||||
) if invalid_layout? layout
|
||||
Jekyll.logger.warn("Build Warning:", "Layout '#{document.data["layout"]}' requested in #{document.relative_path} does not exist.") if invalid_layout? layout
|
||||
|
||||
used = Set.new([layout])
|
||||
|
||||
# Reset the payload layout data to ensure it starts fresh for each page.
|
||||
payload["layout"] = nil
|
||||
used = Set.new([layout])
|
||||
|
||||
while layout
|
||||
payload["content"] = output
|
||||
payload["layout"] = Utils.deep_merge_hashes(layout.data, payload["layout"] || {})
|
||||
payload['content'] = output
|
||||
payload['page'] = document.to_liquid
|
||||
payload['layout'] = Utils.deep_merge_hashes(payload['layout'] || {}, layout.data)
|
||||
|
||||
output = render_liquid(
|
||||
layout.content,
|
||||
payload,
|
||||
info,
|
||||
layout.relative_path
|
||||
File.join(site.config['layouts_dir'], layout.name)
|
||||
)
|
||||
|
||||
# Add layout to dependency tree
|
||||
@@ -166,9 +155,12 @@ module Jekyll
|
||||
site.in_source_dir(layout.path)
|
||||
) if document.write?
|
||||
|
||||
if (layout = site.layouts[layout.data["layout"]])
|
||||
break if used.include?(layout)
|
||||
used << layout
|
||||
if layout = site.layouts[layout.data["layout"]]
|
||||
if used.include?(layout)
|
||||
layout = nil # avoid recursive chain
|
||||
else
|
||||
used << layout
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# encoding: UTF-8
|
||||
require "csv"
|
||||
require 'csv'
|
||||
|
||||
module Jekyll
|
||||
class Site
|
||||
@@ -8,18 +8,18 @@ module Jekyll
|
||||
:exclude, :include, :lsi, :highlighter, :permalink_style,
|
||||
:time, :future, :unpublished, :safe, :plugins, :limit_posts,
|
||||
:show_drafts, :keep_files, :baseurl, :data, :file_read_opts,
|
||||
:gems, :plugin_manager, :theme
|
||||
:gems, :plugin_manager
|
||||
|
||||
attr_accessor :converters, :generators, :reader
|
||||
attr_reader :regenerator, :liquid_renderer, :includes_load_paths
|
||||
attr_reader :regenerator, :liquid_renderer
|
||||
|
||||
# Public: Initialize a new Site.
|
||||
#
|
||||
# config - A Hash containing site configuration details.
|
||||
def initialize(config)
|
||||
# Source and destination may not be changed after the site has been created.
|
||||
@source = File.expand_path(config["source"]).freeze
|
||||
@dest = File.expand_path(config["destination"]).freeze
|
||||
@source = File.expand_path(config['source']).freeze
|
||||
@dest = File.expand_path(config['destination']).freeze
|
||||
|
||||
self.config = config
|
||||
|
||||
@@ -49,12 +49,13 @@ module Jekyll
|
||||
self.send("#{opt}=", config[opt])
|
||||
end
|
||||
|
||||
configure_plugins
|
||||
configure_theme
|
||||
configure_include_paths
|
||||
configure_file_read_opts
|
||||
self.plugin_manager = Jekyll::PluginManager.new(self)
|
||||
self.plugins = plugin_manager.plugins_path
|
||||
|
||||
self.permalink_style = config["permalink"].to_sym
|
||||
self.file_read_opts = {}
|
||||
self.file_read_opts[:encoding] = config['encoding'] if config['encoding']
|
||||
|
||||
self.permalink_style = config['permalink'].to_sym
|
||||
|
||||
@config
|
||||
end
|
||||
@@ -73,7 +74,7 @@ module Jekyll
|
||||
end
|
||||
|
||||
def print_stats
|
||||
if @config["profile"]
|
||||
if @config['profile']
|
||||
puts @liquid_renderer.stats_table
|
||||
end
|
||||
end
|
||||
@@ -82,11 +83,7 @@ module Jekyll
|
||||
#
|
||||
# Returns nothing
|
||||
def reset
|
||||
if config["time"]
|
||||
self.time = Utils.parse_date(config["time"].to_s, "Invalid time in _config.yml.")
|
||||
else
|
||||
self.time = Time.now
|
||||
end
|
||||
self.time = (config['time'] ? Utils.parse_date(config['time'].to_s, "Invalid time in _config.yml.") : Time.now)
|
||||
self.layouts = {}
|
||||
self.pages = []
|
||||
self.static_files = []
|
||||
@@ -120,23 +117,18 @@ module Jekyll
|
||||
dest_pathname = Pathname.new(dest)
|
||||
Pathname.new(source).ascend do |path|
|
||||
if path == dest_pathname
|
||||
raise(
|
||||
Errors::FatalException,
|
||||
"Destination directory cannot be or contain the Source directory."
|
||||
)
|
||||
raise Errors::FatalException.new "Destination directory cannot be or contain the Source directory."
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# The list of collections and their corresponding Jekyll::Collection instances.
|
||||
# If config['collections'] is set, a new instance is created
|
||||
# for each item in the collection, a new hash is returned otherwise.
|
||||
# If config['collections'] is set, a new instance is created for each item in the collection.
|
||||
# If config['collections'] is not set, a new hash is returned.
|
||||
#
|
||||
# Returns a Hash containing collection name-to-instance pairs.
|
||||
def collections
|
||||
@collections ||= Hash[collection_names.map do |coll|
|
||||
[coll, Jekyll::Collection.new(self, coll)]
|
||||
end]
|
||||
@collections ||= Hash[collection_names.map { |coll| [coll, Jekyll::Collection.new(self, coll)] } ]
|
||||
end
|
||||
|
||||
# The list of collection names.
|
||||
@@ -144,11 +136,11 @@ module Jekyll
|
||||
# Returns an array of collection names from the configuration,
|
||||
# or an empty array if the `collections` key is not set.
|
||||
def collection_names
|
||||
case config["collections"]
|
||||
case config['collections']
|
||||
when Hash
|
||||
config["collections"].keys
|
||||
config['collections'].keys
|
||||
when Array
|
||||
config["collections"]
|
||||
config['collections']
|
||||
when nil
|
||||
[]
|
||||
else
|
||||
@@ -184,15 +176,26 @@ module Jekyll
|
||||
|
||||
Jekyll::Hooks.trigger :site, :pre_render, self, payload
|
||||
|
||||
render_docs(payload)
|
||||
render_pages(payload)
|
||||
collections.each do |_, collection|
|
||||
collection.docs.each do |document|
|
||||
if regenerator.regenerate?(document)
|
||||
document.output = Jekyll::Renderer.new(self, document, payload).run
|
||||
document.trigger_hooks(:post_render)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
pages.flatten.each do |page|
|
||||
if regenerator.regenerate?(page)
|
||||
page.output = Jekyll::Renderer.new(self, page, payload).run
|
||||
page.trigger_hooks(:post_render)
|
||||
end
|
||||
end
|
||||
|
||||
Jekyll::Hooks.trigger :site, :post_render, self, payload
|
||||
# rubocop: disable HandleExceptions
|
||||
rescue Errno::ENOENT
|
||||
# ignore missing layout dir
|
||||
end
|
||||
# rubocop: enable HandleExceptions
|
||||
|
||||
# Remove orphaned files and empty directories in destination.
|
||||
#
|
||||
@@ -213,7 +216,7 @@ module Jekyll
|
||||
end
|
||||
|
||||
def posts
|
||||
collections["posts"] ||= Collection.new(self, "posts")
|
||||
collections['posts'] ||= Collection.new(self, 'posts')
|
||||
end
|
||||
|
||||
# Construct a Hash of Posts indexed by the specified Post attribute.
|
||||
@@ -233,19 +236,17 @@ module Jekyll
|
||||
# Build a hash map based on the specified post attribute ( post attr =>
|
||||
# array of posts ) then sort each array in reverse order.
|
||||
hash = Hash.new { |h, key| h[key] = [] }
|
||||
posts.docs.each do |p|
|
||||
p.data[post_attr].each { |t| hash[t] << p } if p.data[post_attr]
|
||||
end
|
||||
posts.docs.each { |p| p.data[post_attr].each { |t| hash[t] << p } if p.data[post_attr] }
|
||||
hash.values.each { |posts| posts.sort!.reverse! }
|
||||
hash
|
||||
end
|
||||
|
||||
def tags
|
||||
post_attr_hash("tags")
|
||||
post_attr_hash('tags')
|
||||
end
|
||||
|
||||
def categories
|
||||
post_attr_hash("categories")
|
||||
post_attr_hash('categories')
|
||||
end
|
||||
|
||||
# Prepare site data for site payload. The method maintains backward compatibility
|
||||
@@ -253,7 +254,7 @@ module Jekyll
|
||||
#
|
||||
# Returns the Hash to be hooked to site.data.
|
||||
def site_data
|
||||
config["data"] || data
|
||||
config['data'] || data
|
||||
end
|
||||
|
||||
# The Hash payload containing site-wide data.
|
||||
@@ -272,7 +273,6 @@ module Jekyll
|
||||
def site_payload
|
||||
Drops::UnifiedPayloadDrop.new self
|
||||
end
|
||||
alias_method :to_liquid, :site_payload
|
||||
|
||||
# Get the implementation class for the given Converter.
|
||||
# Returns the Converter instance implementing the given Converter.
|
||||
@@ -299,7 +299,7 @@ module Jekyll
|
||||
#
|
||||
# Returns
|
||||
def relative_permalinks_are_deprecated
|
||||
if config["relative_permalinks"]
|
||||
if config['relative_permalinks']
|
||||
Jekyll.logger.abort_with "Since v3.0, permalinks for pages" \
|
||||
" in subfolders must be relative to the" \
|
||||
" site source directory, not the parent" \
|
||||
@@ -344,7 +344,7 @@ module Jekyll
|
||||
#
|
||||
# Returns a Boolean: true for a full rebuild, false for normal build
|
||||
def incremental?(override = {})
|
||||
override["incremental"] || config["incremental"]
|
||||
override['incremental'] || config['incremental']
|
||||
end
|
||||
|
||||
# Returns the publisher or creates a new publisher if it doesn't
|
||||
@@ -367,19 +367,6 @@ module Jekyll
|
||||
end
|
||||
end
|
||||
|
||||
# Public: Prefix a given path with the theme directory.
|
||||
#
|
||||
# paths - (optional) path elements to a file or directory within the
|
||||
# theme directory
|
||||
#
|
||||
# Returns a path which is prefixed with the theme root directory.
|
||||
def in_theme_dir(*paths)
|
||||
return nil unless theme
|
||||
paths.reduce(theme.root) do |base, path|
|
||||
Jekyll.sanitized_path(base, path)
|
||||
end
|
||||
end
|
||||
|
||||
# Public: Prefix a given path with the destination directory.
|
||||
#
|
||||
# paths - (optional) path elements to a file or directory within the
|
||||
@@ -392,10 +379,11 @@ module Jekyll
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Limits the current posts; removes the posts which exceed the limit_posts
|
||||
#
|
||||
# Returns nothing
|
||||
private
|
||||
def limit_posts!
|
||||
if limit_posts > 0
|
||||
limit = posts.docs.length < limit_posts ? posts.docs.length : limit_posts
|
||||
@@ -407,55 +395,8 @@ module Jekyll
|
||||
# already exist.
|
||||
#
|
||||
# Returns The Cleaner
|
||||
private
|
||||
def site_cleaner
|
||||
@site_cleaner ||= Cleaner.new(self)
|
||||
end
|
||||
|
||||
private
|
||||
def configure_plugins
|
||||
self.plugin_manager = Jekyll::PluginManager.new(self)
|
||||
self.plugins = plugin_manager.plugins_path
|
||||
end
|
||||
|
||||
private
|
||||
def configure_theme
|
||||
self.theme = nil
|
||||
self.theme = Jekyll::Theme.new(config["theme"]) if config["theme"]
|
||||
end
|
||||
|
||||
private
|
||||
def configure_include_paths
|
||||
@includes_load_paths = Array(in_source_dir(config["includes_dir"].to_s))
|
||||
@includes_load_paths << theme.includes_path if self.theme
|
||||
end
|
||||
|
||||
private
|
||||
def configure_file_read_opts
|
||||
self.file_read_opts = {}
|
||||
self.file_read_opts[:encoding] = config["encoding"] if config["encoding"]
|
||||
end
|
||||
|
||||
private
|
||||
def render_docs(payload)
|
||||
collections.each do |_, collection|
|
||||
collection.docs.each do |document|
|
||||
if regenerator.regenerate?(document)
|
||||
document.output = Jekyll::Renderer.new(self, document, payload).run
|
||||
document.trigger_hooks(:post_render)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def render_pages(payload)
|
||||
pages.flatten.each do |page|
|
||||
if regenerator.regenerate?(page)
|
||||
page.output = Jekyll::Renderer.new(self, page, payload).run
|
||||
page.trigger_hooks(:post_render)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,25 +1,16 @@
|
||||
module Jekyll
|
||||
class StaticFile
|
||||
# The cache of last modification times [path] -> mtime.
|
||||
@@mtimes = {}
|
||||
|
||||
attr_reader :relative_path, :extname
|
||||
|
||||
class << self
|
||||
# The cache of last modification times [path] -> mtime.
|
||||
def mtimes
|
||||
@mtimes ||= {}
|
||||
end
|
||||
|
||||
def reset_cache
|
||||
@mtimes = nil
|
||||
end
|
||||
end
|
||||
|
||||
# Initialize a new StaticFile.
|
||||
#
|
||||
# site - The Site.
|
||||
# base - The String path to the <source>.
|
||||
# dir - The String path between <source> and the file.
|
||||
# name - The String filename of the file.
|
||||
# rubocop: disable ParameterLists
|
||||
def initialize(site, base, dir, name, collection = nil)
|
||||
@site = site
|
||||
@base = base
|
||||
@@ -29,7 +20,6 @@ module Jekyll
|
||||
@relative_path = File.join(*[@dir, @name].compact)
|
||||
@extname = File.extname(@name)
|
||||
end
|
||||
# rubocop: enable ParameterLists
|
||||
|
||||
# Returns source file path.
|
||||
def path
|
||||
@@ -66,7 +56,7 @@ module Jekyll
|
||||
#
|
||||
# Returns true if modified since last write.
|
||||
def modified?
|
||||
self.class.mtimes[path] != mtime
|
||||
@@mtimes[path] != mtime
|
||||
end
|
||||
|
||||
# Whether to write the file to the filesystem
|
||||
@@ -74,7 +64,7 @@ module Jekyll
|
||||
# Returns true unless the defaults for the destination path from
|
||||
# _config.yml contain `published: false`.
|
||||
def write?
|
||||
defaults.fetch("published", true)
|
||||
defaults.fetch('published', true)
|
||||
end
|
||||
|
||||
# Write the static file to the destination directory (if modified).
|
||||
@@ -86,15 +76,28 @@ module Jekyll
|
||||
dest_path = destination(dest)
|
||||
|
||||
return false if File.exist?(dest_path) && !modified?
|
||||
self.class.mtimes[path] = mtime
|
||||
@@mtimes[path] = mtime
|
||||
|
||||
FileUtils.mkdir_p(File.dirname(dest_path))
|
||||
FileUtils.rm(dest_path) if File.exist?(dest_path)
|
||||
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(@@mtimes[path], @@mtimes[path], dest_path)
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
# Reset the mtimes cache (for testing purposes).
|
||||
#
|
||||
# Returns nothing.
|
||||
def self.reset_cache
|
||||
@@mtimes = {}
|
||||
nil
|
||||
end
|
||||
|
||||
def to_liquid
|
||||
{
|
||||
"extname" => extname,
|
||||
@@ -106,11 +109,11 @@ module Jekyll
|
||||
def placeholders
|
||||
{
|
||||
:collection => @collection.label,
|
||||
:path => relative_path[
|
||||
:path => relative_path[
|
||||
@collection.relative_directory.size..relative_path.size],
|
||||
:output_ext => "",
|
||||
:name => "",
|
||||
:title => ""
|
||||
:output_ext => '',
|
||||
:name => '',
|
||||
:title => ''
|
||||
}
|
||||
end
|
||||
|
||||
@@ -122,10 +125,10 @@ module Jekyll
|
||||
relative_path
|
||||
else
|
||||
::Jekyll::URL.new({
|
||||
:template => @collection.url_template,
|
||||
:template => @collection.url_template,
|
||||
:placeholders => placeholders
|
||||
})
|
||||
end.to_s.gsub(%r!/$!, "")
|
||||
end.to_s.gsub(/\/$/, '')
|
||||
end
|
||||
|
||||
# Returns the type of the collection if present, nil otherwise.
|
||||
@@ -138,15 +141,5 @@ module Jekyll
|
||||
def defaults
|
||||
@defaults ||= @site.frontmatter_defaults.all url, type
|
||||
end
|
||||
|
||||
private
|
||||
def copy_file(dest_path)
|
||||
if @site.safe || Jekyll.env == "production"
|
||||
FileUtils.cp(path, dest_path)
|
||||
else
|
||||
FileUtils.copy_entry(path, dest_path)
|
||||
end
|
||||
File.utime(self.class.mtimes[path], self.class.mtimes[path], dest_path)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -6,13 +6,13 @@ module Jekyll
|
||||
@default_formatter = Formatter.new
|
||||
@logdev = $stdout
|
||||
@formatter = proc do |_, _, _, msg|
|
||||
msg.to_s
|
||||
"#{msg}"
|
||||
end
|
||||
end
|
||||
|
||||
def add(severity, message = nil, progname = nil)
|
||||
def add(severity, message = nil, progname = nil, &block)
|
||||
severity ||= UNKNOWN
|
||||
@logdev = logdevice(severity)
|
||||
@logdev = set_logdevice(severity)
|
||||
|
||||
if @logdev.nil? || severity < @level
|
||||
return true
|
||||
@@ -27,8 +27,7 @@ module Jekyll
|
||||
end
|
||||
end
|
||||
@logdev.puts(
|
||||
format_message(format_severity(severity), Time.now, progname, message)
|
||||
)
|
||||
format_message(format_severity(severity), Time.now, progname, message))
|
||||
true
|
||||
end
|
||||
|
||||
@@ -48,7 +47,7 @@ module Jekyll
|
||||
|
||||
private
|
||||
|
||||
def logdevice(severity)
|
||||
def set_logdevice(severity)
|
||||
if severity > INFO
|
||||
$stderr
|
||||
else
|
||||
|
||||
@@ -8,15 +8,28 @@ module Jekyll
|
||||
# forms: name, name=value, or name="<quoted list>"
|
||||
#
|
||||
# <quoted list> is a space-separated list of numbers
|
||||
SYNTAX = %r!^([a-zA-Z0-9.+#-]+)((\s+\w+(=(\w+|"([0-9]+\s)*[0-9]+"))?)*)$!
|
||||
SYNTAX = /^([a-zA-Z0-9.+#-]+)((\s+\w+(=(\w+|"([0-9]+\s)*[0-9]+"))?)*)$/
|
||||
|
||||
def initialize(tag_name, markup, tokens)
|
||||
super
|
||||
if markup.strip =~ SYNTAX
|
||||
@lang = Regexp.last_match(1).downcase
|
||||
@highlight_options = parse_options(Regexp.last_match(2))
|
||||
@highlight_options = {}
|
||||
if defined?(Regexp.last_match(2)) && Regexp.last_match(2) != ''
|
||||
# Split along 3 possible forms -- key="<quoted list>", key=value, or key
|
||||
Regexp.last_match(2).scan(/(?:\w="[^"]*"|\w=\w|\w)+/) do |opt|
|
||||
key, value = opt.split('=')
|
||||
# If a quoted list, convert to array
|
||||
if value && value.include?("\"")
|
||||
value.delete!('"')
|
||||
value = value.split
|
||||
end
|
||||
@highlight_options[key.to_sym] = value || true
|
||||
end
|
||||
end
|
||||
@highlight_options[:linenos] = "inline" if @highlight_options.key?(:linenos) && @highlight_options[:linenos] == true
|
||||
else
|
||||
raise SyntaxError, <<-eos
|
||||
raise SyntaxError.new <<-eos
|
||||
Syntax Error in tag 'highlight' while parsing the following markup:
|
||||
|
||||
#{markup}
|
||||
@@ -29,15 +42,15 @@ eos
|
||||
def render(context)
|
||||
prefix = context["highlighter_prefix"] || ""
|
||||
suffix = context["highlighter_suffix"] || ""
|
||||
code = super.to_s.gsub(%r!\A(\n|\r)+|(\n|\r)+\z!, "")
|
||||
code = super.to_s.gsub(/\A(\n|\r)+|(\n|\r)+\z/, '')
|
||||
|
||||
is_safe = !!context.registers[:site].safe
|
||||
|
||||
output =
|
||||
case context.registers[:site].highlighter
|
||||
when "pygments"
|
||||
when 'pygments'
|
||||
render_pygments(code, is_safe)
|
||||
when "rouge"
|
||||
when 'rouge'
|
||||
render_rouge(code)
|
||||
else
|
||||
render_codehighlighter(code)
|
||||
@@ -53,7 +66,7 @@ eos
|
||||
[:startinline, opts.fetch(:startinline, nil)],
|
||||
[:hl_lines, opts.fetch(:hl_lines, nil)],
|
||||
[:linenos, opts.fetch(:linenos, nil)],
|
||||
[:encoding, opts.fetch(:encoding, "utf-8")],
|
||||
[:encoding, opts.fetch(:encoding, 'utf-8')],
|
||||
[:cssclass, opts.fetch(:cssclass, nil)]
|
||||
].reject { |f| f.last.nil? }]
|
||||
else
|
||||
@@ -61,30 +74,8 @@ eos
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def parse_options(input)
|
||||
options = {}
|
||||
unless input.empty?
|
||||
# Split along 3 possible forms -- key="<quoted list>", key=value, or key
|
||||
input.scan(%r!(?:\w="[^"]*"|\w=\w|\w)+!) do |opt|
|
||||
key, value = opt.split("=")
|
||||
# If a quoted list, convert to array
|
||||
if value && value.include?("\"")
|
||||
value.delete!('"')
|
||||
value = value.split
|
||||
end
|
||||
options[key.to_sym] = value || true
|
||||
end
|
||||
end
|
||||
if options.key?(:linenos) && options[:linenos] == true
|
||||
options[:linenos] = "inline"
|
||||
end
|
||||
options
|
||||
end
|
||||
|
||||
def render_pygments(code, is_safe)
|
||||
Jekyll::External.require_with_graceful_fail("pygments")
|
||||
Jekyll::External.require_with_graceful_fail('pygments')
|
||||
|
||||
highlighted_code = Pygments.highlight(
|
||||
code,
|
||||
@@ -93,27 +84,22 @@ eos
|
||||
)
|
||||
|
||||
if highlighted_code.nil?
|
||||
Jekyll.logger.error <<eos
|
||||
There was an error highlighting your code:
|
||||
|
||||
#{code}
|
||||
|
||||
While attempting to convert the above code, Pygments.rb returned an unacceptable value.
|
||||
This is usually a timeout problem solved by running `jekyll build` again.
|
||||
eos
|
||||
raise ArgumentError, "Pygments.rb returned an unacceptable value "\
|
||||
"when attempting to highlight some code."
|
||||
Jekyll.logger.error "There was an error highlighting your code:"
|
||||
puts
|
||||
Jekyll.logger.error code
|
||||
puts
|
||||
Jekyll.logger.error "While attempting to convert the above code, Pygments.rb" \
|
||||
" returned an unacceptable value."
|
||||
Jekyll.logger.error "This is usually a timeout problem solved by running `jekyll build` again."
|
||||
raise ArgumentError.new("Pygments.rb returned an unacceptable value when attempting to highlight some code.")
|
||||
end
|
||||
|
||||
highlighted_code.sub('<div class="highlight"><pre>', "").sub("</pre></div>", "")
|
||||
highlighted_code.sub('<div class="highlight"><pre>', '').sub('</pre></div>', '')
|
||||
end
|
||||
|
||||
def render_rouge(code)
|
||||
Jekyll::External.require_with_graceful_fail("rouge")
|
||||
formatter = Rouge::Formatters::HTML.new(
|
||||
:line_numbers => @highlight_options[:linenos],
|
||||
:wrap => false
|
||||
)
|
||||
Jekyll::External.require_with_graceful_fail('rouge')
|
||||
formatter = Rouge::Formatters::HTML.new(:line_numbers => @highlight_options[:linenos], :wrap => false)
|
||||
lexer = Rouge::Lexer.find_fancy(@lang, code) || Rouge::Lexers::PlainText
|
||||
formatter.format(lexer.lex(code))
|
||||
end
|
||||
@@ -124,14 +110,13 @@ eos
|
||||
|
||||
def add_code_tag(code)
|
||||
code_attributes = [
|
||||
"class=\"language-#{@lang.to_s.tr("+", "-")}\"",
|
||||
"class=\"language-#{@lang.to_s.tr('+', '-')}\"",
|
||||
"data-lang=\"#{@lang}\""
|
||||
].join(" ")
|
||||
"<figure class=\"highlight\"><pre><code #{code_attributes}>"\
|
||||
"#{code.chomp}</code></pre></figure>"
|
||||
"<figure class=\"highlight\"><pre><code #{code_attributes}>#{code.chomp}</code></pre></figure>"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Liquid::Template.register_tag("highlight", Jekyll::Tags::HighlightBlock)
|
||||
Liquid::Template.register_tag('highlight', Jekyll::Tags::HighlightBlock)
|
||||
|
||||
@@ -12,23 +12,19 @@ module Jekyll
|
||||
end
|
||||
|
||||
class IncludeTag < Liquid::Tag
|
||||
VALID_SYNTAX = %r!
|
||||
([\w-]+)\s*=\s*
|
||||
(?:"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)'|([\w\.-]+))
|
||||
!x
|
||||
VARIABLE_SYNTAX = %r!
|
||||
(?<variable>[^{]*(\{\{\s*[\w\-\.]+\s*(\|.*)?\}\}[^\s{}]*)+)
|
||||
(?<params>.*)
|
||||
!x
|
||||
attr_reader :includes_dir
|
||||
|
||||
VALID_SYNTAX = /([\w-]+)\s*=\s*(?:"([^"\\]*(?:\\.[^"\\]*)*)"|'([^'\\]*(?:\\.[^'\\]*)*)'|([\w\.-]+))/
|
||||
VARIABLE_SYNTAX = /(?<variable>[^{]*(\{\{\s*[\w\-\.]+\s*(\|.*)?\}\}[^\s{}]*)+)(?<params>.*)/
|
||||
|
||||
def initialize(tag_name, markup, tokens)
|
||||
super
|
||||
matched = markup.strip.match(VARIABLE_SYNTAX)
|
||||
if matched
|
||||
@file = matched["variable"].strip
|
||||
@params = matched["params"].strip
|
||||
@file = matched['variable'].strip
|
||||
@params = matched['params'].strip
|
||||
else
|
||||
@file, @params = markup.strip.split(%r!\s+!, 2)
|
||||
@file, @params = markup.strip.split(' ', 2)
|
||||
end
|
||||
validate_params if @params
|
||||
@tag_name = tag_name
|
||||
@@ -42,13 +38,13 @@ module Jekyll
|
||||
params = {}
|
||||
markup = @params
|
||||
|
||||
while (match = VALID_SYNTAX.match(markup))
|
||||
while match = VALID_SYNTAX.match(markup) do
|
||||
markup = markup[match.end(0)..-1]
|
||||
|
||||
value = if match[2]
|
||||
match[2].gsub(%r!\\"!, '"')
|
||||
match[2].gsub(/\\"/, '"')
|
||||
elsif match[3]
|
||||
match[3].gsub(%r!\\'!, "'")
|
||||
match[3].gsub(/\\'/, "'")
|
||||
elsif match[4]
|
||||
context[match[4]]
|
||||
end
|
||||
@@ -59,8 +55,8 @@ module Jekyll
|
||||
end
|
||||
|
||||
def validate_file_name(file)
|
||||
if file !~ %r!^[a-zA-Z0-9_/\.-]+$! || file =~ %r!\./! || file =~ %r!/\.!
|
||||
raise ArgumentError, <<-eos
|
||||
if file !~ /^[a-zA-Z0-9_\/\.-]+$/ || file =~ /\.\// || file =~ /\/\./
|
||||
raise ArgumentError.new <<-eos
|
||||
Invalid syntax for include tag. File contains invalid characters or sequences:
|
||||
|
||||
#{file}
|
||||
@@ -74,9 +70,9 @@ eos
|
||||
end
|
||||
|
||||
def validate_params
|
||||
full_valid_syntax = %r!\A\s*(?:#{VALID_SYNTAX}(?=\s|\z)\s*)*\z!
|
||||
full_valid_syntax = Regexp.compile('\A\s*(?:' + VALID_SYNTAX.to_s + '(?=\s|\z)\s*)*\z')
|
||||
unless @params =~ full_valid_syntax
|
||||
raise ArgumentError, <<-eos
|
||||
raise ArgumentError.new <<-eos
|
||||
Invalid syntax for include tag:
|
||||
|
||||
#{@params}
|
||||
@@ -97,55 +93,44 @@ eos
|
||||
# Render the variable if required
|
||||
def render_variable(context)
|
||||
if @file.match(VARIABLE_SYNTAX)
|
||||
partial = context.registers[:site]
|
||||
.liquid_renderer
|
||||
.file("(variable)")
|
||||
.parse(@file)
|
||||
partial = context.registers[:site].liquid_renderer.file("(variable)").parse(@file)
|
||||
partial.render!(context)
|
||||
end
|
||||
end
|
||||
|
||||
def tag_includes_dirs(context)
|
||||
context.registers[:site].includes_load_paths.freeze
|
||||
end
|
||||
|
||||
def locate_include_file(context, file, safe)
|
||||
includes_dirs = tag_includes_dirs(context)
|
||||
includes_dirs.each do |dir|
|
||||
path = File.join(dir, file)
|
||||
return path if valid_include_file?(path, dir, safe)
|
||||
end
|
||||
raise IOError, "Could not locate the included file '#{file}' in any of "\
|
||||
"#{includes_dirs}. Ensure it exists in one of those directories and, "\
|
||||
"if it is a symlink, does not point outside your site source."
|
||||
def tag_includes_dir(context)
|
||||
context.registers[:site].config['includes_dir'].freeze
|
||||
end
|
||||
|
||||
def render(context)
|
||||
site = context.registers[:site]
|
||||
@includes_dir = tag_includes_dir(context)
|
||||
dir = resolved_includes_dir(context)
|
||||
|
||||
file = render_variable(context) || @file
|
||||
validate_file_name(file)
|
||||
|
||||
path = locate_include_file(context, file, site.safe)
|
||||
return unless path
|
||||
path = File.join(dir, file)
|
||||
validate_path(path, dir, site.safe)
|
||||
|
||||
add_include_to_dependency(site, path, context)
|
||||
|
||||
partial = load_cached_partial(path, context)
|
||||
|
||||
context.stack do
|
||||
context["include"] = parse_params(context) if @params
|
||||
partial.render!(context)
|
||||
end
|
||||
end
|
||||
|
||||
def add_include_to_dependency(site, path, context)
|
||||
# Add include to dependency tree
|
||||
if context.registers[:page] && context.registers[:page].key?("path")
|
||||
site.regenerator.add_dependency(
|
||||
site.in_source_dir(context.registers[:page]["path"]),
|
||||
path
|
||||
)
|
||||
end
|
||||
|
||||
begin
|
||||
partial = load_cached_partial(path, context)
|
||||
|
||||
context.stack do
|
||||
context['include'] = parse_params(context) if @params
|
||||
partial.render!(context)
|
||||
end
|
||||
rescue => e
|
||||
raise IncludeTagError.new e.message, File.join(@includes_dir, @file)
|
||||
end
|
||||
end
|
||||
|
||||
def load_cached_partial(path, context)
|
||||
@@ -155,25 +140,28 @@ eos
|
||||
if cached_partial.key?(path)
|
||||
cached_partial[path]
|
||||
else
|
||||
cached_partial[path] = context.registers[:site]
|
||||
.liquid_renderer
|
||||
.file(path)
|
||||
.parse(read_file(path, context))
|
||||
cached_partial[path] = context.registers[:site].liquid_renderer.file(path).parse(read_file(path, context))
|
||||
end
|
||||
end
|
||||
|
||||
def valid_include_file?(path, dir, safe)
|
||||
!(outside_site_source?(path, dir, safe) || !File.exist?(path))
|
||||
def resolved_includes_dir(context)
|
||||
context.registers[:site].in_source_dir(@includes_dir)
|
||||
end
|
||||
|
||||
def outside_site_source?(path, dir, safe)
|
||||
safe && !realpath_prefixed_with?(path, dir)
|
||||
def validate_path(path, dir, safe)
|
||||
if safe && !realpath_prefixed_with?(path, dir)
|
||||
raise IOError.new "The included file '#{path}' should exist and should not be a symlink"
|
||||
elsif !File.exist?(path)
|
||||
raise IOError.new "Included file '#{path_relative_to_source(dir, path)}' not found"
|
||||
end
|
||||
end
|
||||
|
||||
def path_relative_to_source(dir, path)
|
||||
File.join(@includes_dir, path.sub(Regexp.new("^#{dir}"), ""))
|
||||
end
|
||||
|
||||
def realpath_prefixed_with?(path, dir)
|
||||
File.exist?(path) && File.realpath(path).start_with?(dir)
|
||||
rescue
|
||||
false
|
||||
end
|
||||
|
||||
# This method allows to modify the file content by inheriting from the class.
|
||||
@@ -183,21 +171,20 @@ eos
|
||||
end
|
||||
|
||||
class IncludeRelativeTag < IncludeTag
|
||||
def tag_includes_dirs(context)
|
||||
Array(page_path(context)).freeze
|
||||
def tag_includes_dir(context)
|
||||
'.'.freeze
|
||||
end
|
||||
|
||||
def page_path(context)
|
||||
if context.registers[:page].nil?
|
||||
context.registers[:site].source
|
||||
else
|
||||
current_doc_dir = File.dirname(context.registers[:page]["path"])
|
||||
context.registers[:site].in_source_dir current_doc_dir
|
||||
end
|
||||
context.registers[:page].nil? ? includes_dir : File.dirname(context.registers[:page]["path"])
|
||||
end
|
||||
|
||||
def resolved_includes_dir(context)
|
||||
context.registers[:site].in_source_dir(page_path(context))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Liquid::Template.register_tag("include", Jekyll::Tags::IncludeTag)
|
||||
Liquid::Template.register_tag("include_relative", Jekyll::Tags::IncludeRelativeTag)
|
||||
Liquid::Template.register_tag('include', Jekyll::Tags::IncludeTag)
|
||||
Liquid::Template.register_tag('include_relative', Jekyll::Tags::IncludeRelativeTag)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
module Jekyll
|
||||
module Tags
|
||||
class Link < Liquid::Tag
|
||||
TAG_NAME = "link".freeze
|
||||
TagName = 'link'
|
||||
|
||||
def initialize(tag_name, relative_path, tokens)
|
||||
super
|
||||
@@ -16,14 +16,11 @@ module Jekyll
|
||||
return document.url if document.relative_path == @relative_path
|
||||
end
|
||||
|
||||
raise ArgumentError, <<eos
|
||||
Could not find document '#{@relative_path}' in tag '#{TAG_NAME}'.
|
||||
|
||||
Make sure the document exists and the path is correct.
|
||||
eos
|
||||
raise ArgumentError, "Could not find document '#{@relative_path}' in tag '#{TagName}'.\n\n" \
|
||||
"Make sure the document exists and the path is correct."
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Liquid::Template.register_tag(Jekyll::Tags::Link::TAG_NAME, Jekyll::Tags::Link)
|
||||
Liquid::Template.register_tag(Jekyll::Tags::Link::TagName, Jekyll::Tags::Link)
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
module Jekyll
|
||||
module Tags
|
||||
class PostComparer
|
||||
MATCHER = %r!^(.+/)*(\d+-\d+-\d+)-(.*)$!
|
||||
MATCHER = /^(.+\/)*(\d+-\d+-\d+)-(.*)$/
|
||||
|
||||
attr_reader :path, :date, :slug, :name
|
||||
|
||||
def initialize(name)
|
||||
@name = name
|
||||
|
||||
all, @path, @date, @slug = *name.sub(%r!^/!, "").match(MATCHER)
|
||||
all, @path, @date, @slug = *name.sub(/^\//, "").match(MATCHER)
|
||||
unless all
|
||||
raise Jekyll::Errors::InvalidPostNameError,
|
||||
"'#{name}' does not contain valid date and/or title."
|
||||
end
|
||||
|
||||
@name_regex = %r!^#{path}#{date}-#{slug}\.[^.]+!
|
||||
@name_regex = /^#{path}#{date}-#{slug}\.[^.]+/
|
||||
end
|
||||
|
||||
def post_date
|
||||
@@ -42,9 +42,9 @@ module Jekyll
|
||||
def post_slug(other)
|
||||
path = other.basename.split("/")[0...-1].join("/")
|
||||
if path.nil? || path == ""
|
||||
other.data["slug"]
|
||||
other.data['slug']
|
||||
else
|
||||
path + "/" + other.data["slug"]
|
||||
path + '/' + other.data['slug']
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -78,8 +78,7 @@ eos
|
||||
|
||||
site.posts.docs.each do |p|
|
||||
next unless @post.deprecated_equality p
|
||||
Jekyll::Deprecator.deprecation_message "A call to "\
|
||||
"'{{ post_url #{@post.name} }}' did not match " \
|
||||
Jekyll::Deprecator.deprecation_message "A call to '{{ post_url #{@post.name} }}' did not match " \
|
||||
"a post using the new matching method of checking name " \
|
||||
"(path-date-slug) equality. Please make sure that you " \
|
||||
"change this tag to match the post's name exactly."
|
||||
@@ -96,4 +95,4 @@ eos
|
||||
end
|
||||
end
|
||||
|
||||
Liquid::Template.register_tag("post_url", Jekyll::Tags::PostUrl)
|
||||
Liquid::Template.register_tag('post_url', Jekyll::Tags::PostUrl)
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
module Jekyll
|
||||
class Theme
|
||||
extend Forwardable
|
||||
attr_reader :name
|
||||
def_delegator :gemspec, :version, :version
|
||||
|
||||
def initialize(name)
|
||||
@name = name.downcase.strip
|
||||
configure_sass
|
||||
end
|
||||
|
||||
def root
|
||||
@root ||= gemspec.full_gem_path
|
||||
end
|
||||
|
||||
def includes_path
|
||||
path_for :includes
|
||||
end
|
||||
|
||||
def layouts_path
|
||||
path_for :layouts
|
||||
end
|
||||
|
||||
def sass_path
|
||||
path_for :sass
|
||||
end
|
||||
|
||||
def configure_sass
|
||||
return unless sass_path
|
||||
require "sass"
|
||||
Sass.load_paths << sass_path
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def path_for(folder)
|
||||
resolved_dir = realpath_for(folder)
|
||||
return unless resolved_dir
|
||||
|
||||
path = Jekyll.sanitized_path(root, resolved_dir)
|
||||
path if File.directory?(path)
|
||||
end
|
||||
|
||||
def realpath_for(folder)
|
||||
File.realpath(Jekyll.sanitized_path(root, "_#{folder}"))
|
||||
rescue Errno::ENOENT, Errno::EACCES, Errno::ELOOP
|
||||
nil
|
||||
end
|
||||
|
||||
def gemspec
|
||||
@gemspec ||= Gem::Specification.find_by_name(name)
|
||||
rescue Gem::LoadError
|
||||
raise Jekyll::Errors::MissingDependencyException,
|
||||
"The #{name} theme could not be found."
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,129 +0,0 @@
|
||||
class Jekyll::ThemeBuilder
|
||||
SCAFFOLD_DIRECTORIES = %w(
|
||||
_layouts _includes _sass
|
||||
).freeze
|
||||
|
||||
attr_reader :name, :path, :code_of_conduct
|
||||
|
||||
def initialize(theme_name, opts)
|
||||
@name = theme_name.to_s.tr(" ", "_").gsub(%r!_+!, "_")
|
||||
@path = Pathname.new(File.expand_path(name, Dir.pwd))
|
||||
@code_of_conduct = !!opts["code_of_conduct"]
|
||||
end
|
||||
|
||||
def create!
|
||||
create_directories
|
||||
create_starter_files
|
||||
create_gemspec
|
||||
create_accessories
|
||||
create_example_site
|
||||
initialize_git_repo
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def root
|
||||
@root ||= Pathname.new(File.expand_path("../", __dir__))
|
||||
end
|
||||
|
||||
def template_file(filename)
|
||||
[
|
||||
root.join("theme_template", "#{filename}.erb"),
|
||||
root.join("theme_template", filename.to_s)
|
||||
].find(&:exist?)
|
||||
end
|
||||
|
||||
def template(filename)
|
||||
erb.render(template_file(filename).read)
|
||||
end
|
||||
|
||||
def erb
|
||||
@erb ||= ERBRenderer.new(self)
|
||||
end
|
||||
|
||||
def mkdir_p(directories)
|
||||
Array(directories).each do |directory|
|
||||
full_path = path.join(directory)
|
||||
Jekyll.logger.info "create", full_path.to_s
|
||||
FileUtils.mkdir_p(full_path)
|
||||
end
|
||||
end
|
||||
|
||||
def write_file(filename, contents)
|
||||
full_path = path.join(filename)
|
||||
Jekyll.logger.info "create", full_path.to_s
|
||||
File.write(full_path, contents)
|
||||
end
|
||||
|
||||
def create_directories
|
||||
mkdir_p(SCAFFOLD_DIRECTORIES)
|
||||
mkdir_p(%w(example example/_posts))
|
||||
end
|
||||
|
||||
def create_starter_files
|
||||
%w(page post default).each do |layout|
|
||||
write_file("_layouts/#{layout}.html", template("_layouts/#{layout}.html"))
|
||||
end
|
||||
end
|
||||
|
||||
def create_gemspec
|
||||
write_file("Gemfile", template("Gemfile"))
|
||||
write_file("#{name}.gemspec", template("theme.gemspec"))
|
||||
end
|
||||
|
||||
def create_accessories
|
||||
accessories = %w(README.md Rakefile LICENSE.txt)
|
||||
accessories << "CODE_OF_CONDUCT.md" if code_of_conduct
|
||||
accessories.each do |filename|
|
||||
write_file(filename, template(filename))
|
||||
end
|
||||
end
|
||||
|
||||
def create_example_site
|
||||
%w(example/_config.yml example/index.html example/style.scss).each do |filename|
|
||||
write_file(filename, template(filename))
|
||||
end
|
||||
write_file(
|
||||
"example/_posts/#{Time.now.strftime("%Y-%m-%d")}-my-example-post.md",
|
||||
template("example/_post.md")
|
||||
)
|
||||
end
|
||||
|
||||
def initialize_git_repo
|
||||
Jekyll.logger.info "initialize", path.join(".git").to_s
|
||||
Dir.chdir(path.to_s) { `git init` }
|
||||
write_file(".gitignore", template("gitignore"))
|
||||
end
|
||||
|
||||
def user_name
|
||||
@user_name ||= `git config user.name`.chomp
|
||||
end
|
||||
|
||||
def user_email
|
||||
@user_email ||= `git config user.email`.chomp
|
||||
end
|
||||
|
||||
class ERBRenderer
|
||||
extend Forwardable
|
||||
|
||||
def_delegator :@theme_builder, :name, :theme_name
|
||||
def_delegator :@theme_builder, :user_name, :user_name
|
||||
def_delegator :@theme_builder, :user_email, :user_email
|
||||
|
||||
def initialize(theme_builder)
|
||||
@theme_builder = theme_builder
|
||||
end
|
||||
|
||||
def jekyll_version_with_minor
|
||||
Jekyll::VERSION.split(".").take(2).join(".")
|
||||
end
|
||||
|
||||
def theme_directories
|
||||
SCAFFOLD_DIRECTORIES
|
||||
end
|
||||
|
||||
def render(contents)
|
||||
ERB.new(contents).result binding
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,4 +1,4 @@
|
||||
require "uri"
|
||||
require 'uri'
|
||||
|
||||
# Public: Methods that generate a URL for a resource such as a Post or a Page.
|
||||
#
|
||||
@@ -67,32 +67,32 @@ module Jekyll
|
||||
|
||||
def generate_url_from_hash(template)
|
||||
@placeholders.inject(template) do |result, token|
|
||||
break result if result.index(":").nil?
|
||||
break result if result.index(':').nil?
|
||||
if token.last.nil?
|
||||
# Remove leading "/" to avoid generating urls with `//`
|
||||
result.gsub(%r!/:#{token.first}!, "")
|
||||
# Remove leading '/' to avoid generating urls with `//`
|
||||
result.gsub(/\/:#{token.first}/, '')
|
||||
else
|
||||
result.gsub(%r!:#{token.first}!, self.class.escape_path(token.last))
|
||||
result.gsub(/:#{token.first}/, self.class.escape_path(token.last))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def generate_url_from_drop(template)
|
||||
template.gsub(%r!:([a-z_]+)!) do |match|
|
||||
replacement = @placeholders.public_send(match.sub(":".freeze, "".freeze))
|
||||
template.gsub(/:([a-z_]+)/.freeze) do |match|
|
||||
replacement = @placeholders.public_send(match.sub(':'.freeze, ''.freeze))
|
||||
if replacement.nil?
|
||||
"".freeze
|
||||
''.freeze
|
||||
else
|
||||
self.class.escape_path(replacement)
|
||||
end
|
||||
end.gsub(%r!//!, "/".freeze)
|
||||
end.gsub(/\/\//.freeze, '/'.freeze)
|
||||
end
|
||||
|
||||
# Returns a sanitized String URL, stripping "../../" and multiples of "/",
|
||||
# as well as the beginning "/" so we can enforce and ensure it.
|
||||
|
||||
def sanitize_url(str)
|
||||
"/" + str.gsub(%r!/{2,}!, "/").gsub(%r!\.+/|\A/+!, "")
|
||||
"/" + str.gsub(/\/{2,}/, "/").gsub(/\.+\/|\A\/+/, "")
|
||||
end
|
||||
|
||||
# Escapes a path to be a valid URL path segment
|
||||
@@ -106,7 +106,7 @@ module Jekyll
|
||||
#
|
||||
# Returns the escaped path.
|
||||
def self.escape_path(path)
|
||||
# Because URI.escape doesn't escape "?", "[" and "]" by default,
|
||||
# Because URI.escape doesn't escape '?', '[' and ']' by default,
|
||||
# specify unsafe string (except unreserved, sub-delims, ":", "@" and "/").
|
||||
#
|
||||
# URI path segment is defined in RFC 3986 as follows:
|
||||
@@ -116,7 +116,7 @@ module Jekyll
|
||||
# pct-encoded = "%" HEXDIG HEXDIG
|
||||
# sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
|
||||
# / "*" / "+" / "," / ";" / "="
|
||||
URI.escape(path, %r{[^a-zA-Z\d\-._~!$&'()*+,;=:@\/]}).encode("utf-8")
|
||||
URI.escape(path, /[^a-zA-Z\d\-._~!$&'()*+,;=:@\/]/).encode('utf-8')
|
||||
end
|
||||
|
||||
# Unescapes a URL path segment
|
||||
@@ -130,7 +130,7 @@ module Jekyll
|
||||
#
|
||||
# Returns the unescaped path.
|
||||
def self.unescape_path(path)
|
||||
URI.unescape(path.encode("utf-8"))
|
||||
URI.unescape(path.encode('utf-8'))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,25 +2,27 @@
|
||||
module Jekyll
|
||||
module Utils
|
||||
extend self
|
||||
autoload :Platforms, "jekyll/utils/platforms"
|
||||
autoload :Platforms, 'jekyll/utils/platforms'
|
||||
autoload :Ansi, "jekyll/utils/ansi"
|
||||
|
||||
# Constants for use in #slugify
|
||||
SLUGIFY_MODES = %w(raw default pretty).freeze
|
||||
SLUGIFY_MODES = %w(raw default pretty)
|
||||
SLUGIFY_RAW_REGEXP = Regexp.new('\\s+').freeze
|
||||
SLUGIFY_DEFAULT_REGEXP = Regexp.new("[^[:alnum:]]+").freeze
|
||||
SLUGIFY_DEFAULT_REGEXP = Regexp.new('[^[:alnum:]]+').freeze
|
||||
SLUGIFY_PRETTY_REGEXP = Regexp.new("[^[:alnum:]._~!$&'()+,;=@]+").freeze
|
||||
|
||||
# Takes an indented string and removes the preceding spaces on each line
|
||||
|
||||
def strip_heredoc(str)
|
||||
str.gsub(%r!^[ \t]{#{(str.scan(%r!^[ \t]*(?=\S)!).min || "").size}}!, "")
|
||||
str.gsub(/^[ \t]{#{(str.scan(/^[ \t]*(?=\S)/).min || "").size}}/, "")
|
||||
end
|
||||
|
||||
# Takes a slug and turns it into a simple title.
|
||||
|
||||
def titleize_slug(slug)
|
||||
slug.split("-").map!(&:capitalize).join(" ")
|
||||
slug.split("-").map! do |val|
|
||||
val.capitalize
|
||||
end.join(" ")
|
||||
end
|
||||
|
||||
# Non-destructive version of deep_merge_hashes! See that method.
|
||||
@@ -40,9 +42,17 @@ module Jekyll
|
||||
#
|
||||
# Thanks to whoever made it.
|
||||
def deep_merge_hashes!(target, overwrite)
|
||||
merge_values(target, overwrite)
|
||||
merge_default_proc(target, overwrite)
|
||||
duplicate_frozen_values(target)
|
||||
target.merge!(overwrite) do |key, old_val, new_val|
|
||||
if new_val.nil?
|
||||
old_val
|
||||
else
|
||||
mergable?(old_val) && mergable?(new_val) ? deep_merge_hashes(old_val, new_val) : new_val
|
||||
end
|
||||
end
|
||||
|
||||
if target.respond_to?(:default_proc) && overwrite.respond_to?(:default_proc) && target.default_proc.nil?
|
||||
target.default_proc = overwrite.default_proc
|
||||
end
|
||||
|
||||
target
|
||||
end
|
||||
@@ -51,15 +61,6 @@ module Jekyll
|
||||
value.is_a?(Hash) || value.is_a?(Drops::Drop)
|
||||
end
|
||||
|
||||
def duplicable?(obj)
|
||||
case obj
|
||||
when nil, false, true, Symbol, Numeric
|
||||
false
|
||||
else
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
# Read array from the supplied hash favouring the singular key
|
||||
# and then the plural key, and handling any nil entries.
|
||||
#
|
||||
@@ -70,9 +71,7 @@ module Jekyll
|
||||
# Returns an array
|
||||
def pluralized_array_from_hash(hash, singular_key, plural_key)
|
||||
[].tap do |array|
|
||||
value = value_from_singular_key(hash, singular_key)
|
||||
value ||= value_from_plural_key(hash, plural_key)
|
||||
array << value
|
||||
array << (value_from_singular_key(hash, singular_key) || value_from_plural_key(hash, plural_key))
|
||||
end.flatten.compact
|
||||
end
|
||||
|
||||
@@ -134,13 +133,11 @@ module Jekyll
|
||||
# Determines whether a given file has
|
||||
#
|
||||
# Returns true if the YAML front matter is present.
|
||||
# rubocop: disable PredicateName
|
||||
def has_yaml_header?(file)
|
||||
!!(File.open(file, "rb", &:readline) =~ %r!\A---\s*\r?\n!)
|
||||
!!(File.open(file, 'rb') { |f| f.readline } =~ /\A---\s*\r?\n/)
|
||||
rescue EOFError
|
||||
false
|
||||
end
|
||||
# rubocop: enable PredicateName
|
||||
|
||||
# Slugify a filename or title.
|
||||
#
|
||||
@@ -175,7 +172,7 @@ module Jekyll
|
||||
#
|
||||
# Returns the slugified string.
|
||||
def slugify(string, mode: nil, cased: false)
|
||||
mode ||= "default"
|
||||
mode ||= 'default'
|
||||
return nil if string.nil?
|
||||
|
||||
unless SLUGIFY_MODES.include?(mode)
|
||||
@@ -185,21 +182,21 @@ module Jekyll
|
||||
# Replace each character sequence with a hyphen
|
||||
re =
|
||||
case mode
|
||||
when "raw"
|
||||
when 'raw'
|
||||
SLUGIFY_RAW_REGEXP
|
||||
when "default"
|
||||
when 'default'
|
||||
SLUGIFY_DEFAULT_REGEXP
|
||||
when "pretty"
|
||||
when 'pretty'
|
||||
# "._~!$&'()+,;=@" is human readable (not URI-escaped) in URL
|
||||
# and is allowed in both extN and NTFS.
|
||||
SLUGIFY_PRETTY_REGEXP
|
||||
end
|
||||
|
||||
# Strip according to the mode
|
||||
slug = string.gsub(re, "-")
|
||||
slug = string.gsub(re, '-')
|
||||
|
||||
# Remove leading/trailing hyphen
|
||||
slug.gsub!(%r!^\-|\-$!i, "")
|
||||
slug.gsub!(/^\-|\-$/i, '')
|
||||
|
||||
slug.downcase! unless cased
|
||||
slug
|
||||
@@ -270,7 +267,7 @@ module Jekyll
|
||||
# Returns matched pathes
|
||||
def safe_glob(dir, patterns, flags = 0)
|
||||
return [] unless Dir.exist?(dir)
|
||||
pattern = File.join(Array(patterns))
|
||||
pattern = File.join(Array patterns)
|
||||
return [dir] if pattern.empty?
|
||||
Dir.chdir(dir) do
|
||||
Dir.glob(pattern, flags).map { |f| File.join(dir, f) }
|
||||
@@ -287,31 +284,5 @@ module Jekyll
|
||||
merged
|
||||
end
|
||||
|
||||
private
|
||||
def merge_values(target, overwrite)
|
||||
target.merge!(overwrite) do |_key, old_val, new_val|
|
||||
if new_val.nil?
|
||||
old_val
|
||||
elsif mergable?(old_val) && mergable?(new_val)
|
||||
deep_merge_hashes(old_val, new_val)
|
||||
else
|
||||
new_val
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def merge_default_proc(target, overwrite)
|
||||
if target.is_a?(Hash) && overwrite.is_a?(Hash) && target.default_proc.nil?
|
||||
target.default_proc = overwrite.default_proc
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def duplicate_frozen_values(target)
|
||||
target.each do |key, val|
|
||||
target[key] = val.dup if val.frozen? && duplicable?(val)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -8,17 +8,17 @@ module Jekyll
|
||||
extend self
|
||||
|
||||
ESCAPE = format("%c", 27)
|
||||
MATCH = %r!#{ESCAPE}\[(?:\d+)(?:;\d+)*(j|k|m|s|u|A|B|G)|\e\(B\e\[m!ix
|
||||
MATCH = /#{ESCAPE}\[(?:\d+)(?:;\d+)*(j|k|m|s|u|A|B|G)|\e\(B\e\[m/ix.freeze
|
||||
COLORS = {
|
||||
:red => 31,
|
||||
:green => 32,
|
||||
:black => 30,
|
||||
:red => 31,
|
||||
:green => 32,
|
||||
:black => 30,
|
||||
:magenta => 35,
|
||||
:yellow => 33,
|
||||
:white => 37,
|
||||
:blue => 34,
|
||||
:cyan => 36
|
||||
}.freeze
|
||||
:yellow => 33,
|
||||
:white => 37,
|
||||
:blue => 34,
|
||||
:cyan => 36
|
||||
}
|
||||
|
||||
# Strip ANSI from the current string. It also strips cursor stuff,
|
||||
# well some of it, and it also strips some other stuff that a lot of
|
||||
|
||||
@@ -17,8 +17,8 @@ module Jekyll
|
||||
# platforms. This is mostly useful for `jekyll doctor` and for testing
|
||||
# where we kick off certain tests based on the platform.
|
||||
|
||||
{ :windows? => %r!mswin|mingw|cygwin!, :linux? => %r!linux!, \
|
||||
:osx? => %r!darwin|mac os!, :unix? => %r!solaris|bsd! }.each do |k, v|
|
||||
{ :windows? => /mswin|mingw|cygwin/, :linux? => /linux/, \
|
||||
:osx? => /darwin|mac os/, :unix? => /solaris|bsd/ }.each do |k, v|
|
||||
define_method k do
|
||||
!!(
|
||||
RbConfig::CONFIG["host_os"] =~ v
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
module Jekyll
|
||||
VERSION = "3.2.0.pre.beta1".freeze
|
||||
VERSION = '3.1.2'
|
||||
end
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
# which you are expected to set up once and rarely edit after that. If you find
|
||||
# yourself editing these this file very often, consider using Jekyll's data files
|
||||
# feature for the data you need to update frequently.
|
||||
#
|
||||
# For technical reasons, this file is *NOT* reloaded automatically when you use
|
||||
# 'jekyll serve'. If you change this file, please restart the server process.
|
||||
|
||||
@@ -20,10 +19,9 @@ description: > # this means to ignore newlines until "baseurl:"
|
||||
line in _config.yml. It will appear in your document head meta (for
|
||||
Google search results) and in your feed.xml site description.
|
||||
baseurl: "" # the subpath of your site, e.g. /blog
|
||||
url: "http://example.com" # the base hostname & protocol for your site
|
||||
url: "http://yourdomain.com" # the base hostname & protocol for your site
|
||||
twitter_username: jekyllrb
|
||||
github_username: jekyll
|
||||
|
||||
# Build settings
|
||||
markdown: kramdown
|
||||
theme: minima
|
||||
|
||||
38
lib/site_template/_includes/footer.html
Normal file
38
lib/site_template/_includes/footer.html
Normal file
@@ -0,0 +1,38 @@
|
||||
<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>
|
||||
12
lib/site_template/_includes/head.html
Normal file
12
lib/site_template/_includes/head.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<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>
|
||||
27
lib/site_template/_includes/header.html
Normal file
27
lib/site_template/_includes/header.html
Normal file
@@ -0,0 +1,27 @@
|
||||
<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
lib/site_template/_includes/icon-github.html
Normal file
1
lib/site_template/_includes/icon-github.html
Normal file
@@ -0,0 +1 @@
|
||||
<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
lib/site_template/_includes/icon-github.svg
Normal file
1
lib/site_template/_includes/icon-github.svg
Normal file
@@ -0,0 +1 @@
|
||||
<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>
|
||||
|
After Width: | Height: | Size: 926 B |
1
lib/site_template/_includes/icon-twitter.html
Normal file
1
lib/site_template/_includes/icon-twitter.html
Normal file
@@ -0,0 +1 @@
|
||||
<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
lib/site_template/_includes/icon-twitter.svg
Normal file
1
lib/site_template/_includes/icon-twitter.svg
Normal file
@@ -0,0 +1 @@
|
||||
<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>
|
||||
|
After Width: | Height: | Size: 787 B |
20
lib/site_template/_layouts/default.html
Normal file
20
lib/site_template/_layouts/default.html
Normal file
@@ -0,0 +1,20 @@
|
||||
<!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>
|
||||
14
lib/site_template/_layouts/page.html
Normal file
14
lib/site_template/_layouts/page.html
Normal file
@@ -0,0 +1,14 @@
|
||||
---
|
||||
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>
|
||||
15
lib/site_template/_layouts/post.html
Normal file
15
lib/site_template/_layouts/post.html
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
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>
|
||||
200
lib/site_template/_sass/_base.scss
Normal file
200
lib/site_template/_sass/_base.scss
Normal file
@@ -0,0 +1,200 @@
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
242
lib/site_template/_sass/_layout.scss
Normal file
242
lib/site_template/_sass/_layout.scss
Normal file
@@ -0,0 +1,242 @@
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
71
lib/site_template/_sass/_syntax-highlighting.scss
Normal file
71
lib/site_template/_sass/_syntax-highlighting.scss
Normal file
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* 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,6 +3,8 @@
|
||||
---
|
||||
@charset "utf-8";
|
||||
|
||||
|
||||
|
||||
// Our variables
|
||||
$base-font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
$base-font-size: 16px;
|
||||
@@ -26,7 +28,8 @@ $content-width: 800px;
|
||||
$on-palm: 600px;
|
||||
$on-laptop: 800px;
|
||||
|
||||
// Minima also includes a mixin for defining media queries.
|
||||
|
||||
|
||||
// Use media queries like this:
|
||||
// @include media-query($on-palm) {
|
||||
// .wrapper {
|
||||
@@ -34,6 +37,17 @@ $on-laptop: 800px;
|
||||
// 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"
|
||||
;
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, gender identity and expression, level of experience,
|
||||
nationality, personal appearance, race, religion, or sexual identity and
|
||||
orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||
advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or
|
||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||
permanently any contributor for other behaviors that they deem inappropriate,
|
||||
threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. Examples of
|
||||
representing a project or community include using an official project e-mail
|
||||
address, posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event. Representation of a project may be
|
||||
further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting the project team at <%= user_email %>. All
|
||||
complaints will be reviewed and investigated and will result in a response that
|
||||
is deemed necessary and appropriate to the circumstances. The project team is
|
||||
obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||
faith may face temporary or permanent repercussions as determined by other
|
||||
members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||
available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
||||
@@ -1,2 +0,0 @@
|
||||
source "https://rubygems.org"
|
||||
gemspec
|
||||
@@ -1,21 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 <%= user_name %>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user