diff --git a/Rakefile b/Rakefile index 439a5366..b16e743f 100644 --- a/Rakefile +++ b/Rakefile @@ -146,10 +146,14 @@ namespace :site do # Generate the site in server mode. puts "Running Jekyll..." - Jekyll::Commands::Serve.process({ + options = { "source" => File.expand_path("site"), - "destination" => File.expand_path("site/_site") - }) + "destination" => File.expand_path("site/_site"), + "watch" => true, + "serving" => true + } + Jekyll::Commands::Build.process(options) + Jekyll::Commands::Serve.process(options) end desc "Generate the site" diff --git a/bin/jekyll b/bin/jekyll index 194295c8..060c9125 100755 --- a/bin/jekyll +++ b/bin/jekyll @@ -13,6 +13,8 @@ require 'mercenary' end end +Jekyll::PluginManager.require_from_bundler + Jekyll::Deprecator.process(ARGV) Mercenary.program(:jekyll) do |p| diff --git a/features/plugins.feature b/features/plugins.feature new file mode 100644 index 00000000..a36c6c82 --- /dev/null +++ b/features/plugins.feature @@ -0,0 +1,34 @@ +Feature: Configuring and using plugins + As a hacker + I want to specify my own plugins that can modify Jekyll's behaviour + + Scenario: Add a gem-based plugin + Given I have an "index.html" file that contains "Whatever" + And I have a configuration file with "gems" set to "[jekyll_test_plugin]" + When I run jekyll build + Then the _site directory should exist + And I should see "Whatever" in "_site/index.html" + And I should see "this is a test" in "_site/test.txt" + + Scenario: Add an empty whitelist to restrict all gems + Given I have an "index.html" file that contains "Whatever" + And I have a configuration file with: + | key | value | + | gems | [jekyll_test_plugin] | + | whitelist | [] | + When I run jekyll build --safe + Then the _site directory should exist + And I should see "Whatever" in "_site/index.html" + And the "_site/test.txt" file should not exist + + Scenario: Add a whitelist to restrict some gems but allow others + Given I have an "index.html" file that contains "Whatever" + And I have a configuration file with: + | key | value | + | gems | [jekyll_test_plugin, jekyll_test_plugin_malicious] | + | whitelist | [jekyll_test_plugin] | + When I run jekyll build --safe + Then the _site directory should exist + And I should see "Whatever" in "_site/index.html" + And the "_site/test.txt" file should exist + And I should see "this is a test" in "_site/test.txt" diff --git a/features/site_configuration.feature b/features/site_configuration.feature index 8aaa9e1d..1d067f0c 100644 --- a/features/site_configuration.feature +++ b/features/site_configuration.feature @@ -243,37 +243,6 @@ Feature: Site configuration And I should see "Post Layout:
content for entry1.
" in "_site/2007/12/31/entry1.html" And I should see "Post Layout:content for entry2.
" in "_site/2020/01/31/entry2.html" - Scenario: Add a gem-based plugin - Given I have an "index.html" file that contains "Whatever" - And I have a configuration file with "gems" set to "[jekyll_test_plugin]" - When I run jekyll build - Then the _site directory should exist - And I should see "Whatever" in "_site/index.html" - And I should see "this is a test" in "_site/test.txt" - - Scenario: Add an empty whitelist to restrict all gems - Given I have an "index.html" file that contains "Whatever" - And I have a configuration file with: - | key | value | - | gems | [jekyll_test_plugin] | - | whitelist | [] | - When I run jekyll build --safe - Then the _site directory should exist - And I should see "Whatever" in "_site/index.html" - And the "_site/test.txt" file should not exist - - Scenario: Add a whitelist to restrict some gems but allow others - Given I have an "index.html" file that contains "Whatever" - And I have a configuration file with: - | key | value | - | gems | [jekyll_test_plugin, jekyll_test_plugin_malicious] | - | whitelist | [jekyll_test_plugin] | - When I run jekyll build --safe - Then the _site directory should exist - And I should see "Whatever" in "_site/index.html" - And the "_site/test.txt" file should exist - And I should see "this is a test" in "_site/test.txt" - Scenario: arbitrary file reads via layouts Given I have an "index.html" page with layout "page" that contains "FOO" And I have a "_config.yml" file that contains "layouts: '../../../../../../../../../../../../../../usr/include'" diff --git a/features/step_definitions/jekyll_steps.rb b/features/step_definitions/jekyll_steps.rb index 8be4ea2f..b75379f5 100644 --- a/features/step_definitions/jekyll_steps.rb +++ b/features/step_definitions/jekyll_steps.rb @@ -146,6 +146,13 @@ When /^I run jekyll(.*)$/ do |args| end end +When /^I run bundle(.*)$/ do |args| + status = run_bundle(args) + if args.include?("--verbose") || ENV['DEBUG'] + puts jekyll_run_output + end +end + When /^I change "(.*)" to contain "(.*)"$/ do |file, text| File.open(file, 'a') do |f| f.write(text) diff --git a/features/support/env.rb b/features/support/env.rb index 996c79ba..ba4555fe 100644 --- a/features/support/env.rb +++ b/features/support/env.rb @@ -21,11 +21,19 @@ def jekyll_run_output File.read(jekyll_output_file) if File.file?(jekyll_output_file) end +def run_bundle(args) + child = run_in_shell('bundle', *args.strip.split(' ')) +end + def run_jekyll(args) - child = POSIX::Spawn::Child.new JEKYLL_PATH, *args.strip.split(' '), "--trace", :out => [JEKYLL_COMMAND_OUTPUT_FILE, "w"] + child = run_in_shell(JEKYLL_PATH, *args.strip.split(' '), "--trace") child.status.exitstatus == 0 end +def run_in_shell(*args) + POSIX::Spawn::Child.new *args, :out => [JEKYLL_COMMAND_OUTPUT_FILE, "w"] +end + def slug(title) if title title.downcase.gsub(/[^\w]/, " ").strip.gsub(/\s+/, '-') diff --git a/lib/jekyll/plugin_manager.rb b/lib/jekyll/plugin_manager.rb index c52a5205..ea964ce5 100644 --- a/lib/jekyll/plugin_manager.rb +++ b/lib/jekyll/plugin_manager.rb @@ -17,6 +17,7 @@ module Jekyll def conscientious_require require_plugin_files require_gems + self.class.require_from_bundler end # Require each of the gem plugins specified. @@ -25,11 +26,26 @@ module Jekyll def require_gems site.gems.each do |gem| if plugin_allowed?(gem) + Jekyll.logger.debug("PluginManager:", "Requiring #{gem}") require gem end end end + def self.require_from_bundler + if ENV["JEKYLL_NO_BUNDLER_REQUIRE"] + false + else + require "bundler" + required_gems = Bundler.require(:jekyll_plugins) + Jekyll.logger.debug("PluginManager:", "Required #{required_gems.map(&:name).join(', ')}") + ENV["JEKYLL_NO_BUNDLER_REQUIRE"] = "true" + true + end + rescue LoadError + false + end + # Check whether a gem plugin is allowed to be used during this build. # # gem_name - the name of the gem diff --git a/site/_docs/plugins.md b/site/_docs/plugins.md index df1de0cb..c80081fb 100644 --- a/site/_docs/plugins.md +++ b/site/_docs/plugins.md @@ -25,7 +25,7 @@ having to modify the Jekyll source itself. ## Installing a plugin -You have 2 options for installing plugins: +You have 3 options for installing plugins: 1. In your site source root, make a `_plugins` directory. Place your plugins here. Any file ending in `*.rb` inside this directory will be loaded before Jekyll @@ -35,6 +35,12 @@ You have 2 options for installing plugins: gems: [jekyll-test-plugin, jekyll-jsonify, jekyll-assets] # This will require each of these gems automatically. +3. Add the relevant plugins to a Bundler group in your `Gemfile`. An + example: + + group :jekyll_plugins do + gem "my-jekyll-plugin" + endMethod | +Description | +
---|---|
+
|
+
+ This method accepts one parameter, the
+ |
+