From 0eb937935451377232724370b6228bb08f9a8cec Mon Sep 17 00:00:00 2001 From: ashmaroli Date: Fri, 31 Mar 2017 11:16:15 +0530 Subject: [PATCH] Require `runtime_dependencies` of a Gem-based theme from its `.gemspec` file (#5914) Merge pull request 5914 --- Gemfile | 1 + docs/_docs/themes.md | 6 ++++++ features/theme.feature | 7 +++++++ lib/jekyll/plugin_manager.rb | 12 ++++++++++++ lib/jekyll/theme.rb | 4 ++++ .../test-dependency-theme.gemspec | 11 +++++++++++ test/test_plugin_manager.rb | 16 ++++++++++++++-- 7 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 test/fixtures/test-dependency-theme/test-dependency-theme.gemspec diff --git a/Gemfile b/Gemfile index 8355c1b9..7e509366 100644 --- a/Gemfile +++ b/Gemfile @@ -27,6 +27,7 @@ group :test do gem "rspec-mocks" gem "rubocop", "~> 0.47.1" gem "test-theme", :path => File.expand_path("./test/fixtures/test-theme", File.dirname(__FILE__)) + gem "test-dependency-theme", :path => File.expand_path("./test/fixtures/test-dependency-theme", File.dirname(__FILE__)) gem "jruby-openssl" if RUBY_ENGINE == "jruby" end diff --git a/docs/_docs/themes.md b/docs/_docs/themes.md index 5ad3b2da..6770a9ca 100644 --- a/docs/_docs/themes.md +++ b/docs/_docs/themes.md @@ -206,6 +206,12 @@ Your theme's styles can be included in the user's stylesheet using the `@import` {% raw %}@import "{{ site.theme }}";{% endraw %} ``` +### Theme-gem dependencies + +From `v3.5`, Jekyll will automatically require all whitelisted `runtime_dependencies` of your theme-gem even if they're not explicitly included under the `gems` array in the site's config file. (NOTE: whitelisting is only required when building or serving with the `--safe` option.) + +With this, the end-user need not keep track of the plugins required to be included in their config file for their theme-gem to work as intended. + ### Documenting your theme Your theme should include a `/README.md` file, which explains how site authors can install and use your theme. What layouts are included? What includes? Do they need to add anything special to their site's configuration file? diff --git a/features/theme.feature b/features/theme.feature index 7729a0eb..820283e8 100644 --- a/features/theme.feature +++ b/features/theme.feature @@ -46,6 +46,13 @@ Feature: Writing themes 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: Requiring dependencies of a theme + Given I have a configuration file with "theme" set to "test-dependency-theme" + When I run jekyll build + Then I should get a zero exit status + And the _site directory should exist + And the "_site/test.txt" file should exist + 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 diff --git a/lib/jekyll/plugin_manager.rb b/lib/jekyll/plugin_manager.rb index 53c08113..fa183c62 100644 --- a/lib/jekyll/plugin_manager.rb +++ b/lib/jekyll/plugin_manager.rb @@ -15,6 +15,7 @@ module Jekyll # # Returns nothing def conscientious_require + require_theme_deps if site.theme require_plugin_files require_gems deprecation_checks @@ -29,6 +30,17 @@ module Jekyll ) end + # Require each of the runtime_dependencies specified by the theme's gemspec. + # + # Returns false only if no dependencies have been specified, otherwise nothing. + def require_theme_deps + return false unless site.theme.runtime_dependencies + site.theme.runtime_dependencies.each do |dep| + next if dep.name == "jekyll" + External.require_with_graceful_fail(dep.name) if plugin_allowed?(dep.name) + end + end + def self.require_from_bundler if !ENV["JEKYLL_NO_BUNDLER_REQUIRE"] && File.file?("Gemfile") require "bundler" diff --git a/lib/jekyll/theme.rb b/lib/jekyll/theme.rb index 803004f3..045c91aa 100644 --- a/lib/jekyll/theme.rb +++ b/lib/jekyll/theme.rb @@ -39,6 +39,10 @@ module Jekyll Sass.load_paths << sass_path end + def runtime_dependencies + gemspec.runtime_dependencies + end + private def path_for(folder) diff --git a/test/fixtures/test-dependency-theme/test-dependency-theme.gemspec b/test/fixtures/test-dependency-theme/test-dependency-theme.gemspec new file mode 100644 index 00000000..f372354e --- /dev/null +++ b/test/fixtures/test-dependency-theme/test-dependency-theme.gemspec @@ -0,0 +1,11 @@ +Gem::Specification.new do |s| + s.name = 'test-dependency-theme' + s.version = '0.1.0' + s.licenses = ['MIT'] + s.summary = "This is another theme used to test Jekyll" + s.authors = ["Jekyll"] + s.files = ["lib/example.rb"] + s.homepage = 'https://github.com/jekyll/jekyll' + + s.add_runtime_dependency "jekyll_test_plugin" +end diff --git a/test/test_plugin_manager.rb b/test/test_plugin_manager.rb index 702df593..9217965b 100644 --- a/test/test_plugin_manager.rb +++ b/test/test_plugin_manager.rb @@ -142,12 +142,24 @@ class TestPluginManager < JekyllUnitTest end should "conscientious require" do - site = double + site = double({ + :config => { "theme" => "test-dependency-theme" }, + :in_dest_dir => "/tmp/_site/", + }) plugin_manager = PluginManager.new(site) + expect(site).to receive(:theme).and_return(true) + expect(site).to receive(:process).and_return(true) expect(plugin_manager).to( - receive_messages([:require_plugin_files, :require_gems, :deprecation_checks]) + receive_messages([ + :require_theme_deps, + :require_plugin_files, + :require_gems, + :deprecation_checks, + ]) ) plugin_manager.conscientious_require + site.process + assert site.in_dest_dir("test.txt") end end