Load config file from within current theme-gem (#7304)

Merge pull request 7304
This commit is contained in:
Ashwin Maroli 2018-10-28 15:38:32 +05:30 committed by jekyllbot
parent 56c35f1a7d
commit d67cbb4e5f
5 changed files with 83 additions and 1 deletions

View File

@ -274,6 +274,24 @@ Jekyll will automatically require all whitelisted `runtime_dependencies` of your
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.
{% if site.version == '4.0.0' %}
{% comment %} Remove this encapsulation when `v4.0` ships {% endcomment %}
### Pre-configuring Theme-gems {%- include docs_version_badge.html version="4.0.0" -%}
Jekyll will read-in a `_config.yml` at the root of the theme-gem and merge its data into the site's existing configuration data.
But unlike other entities loaded from within the theme, loading the config file comes with a few restrictions, as summarized below:
* Jekyll's default settings cannot be overridden by a theme-config. That *ball is still in the user's court.*
* The theme-config-file cannot be a symlink, irrespective of `safe mode` and whether the file pointed to by the symlink is a legitimate file within the theme-gem.
* The theme-config should be a set of key-value pairs. An empty config file, a config file that simply *lists items* under a key, or a config file with just a simple string of text will simply be ignored silently. Users will not get a warning or any log output regarding this discrepancy.
* Any settings defined by the theme-config can be overridden by the user.
While this feature is to enable easier adoption of a theme, the restrictions ensure that a theme-config cannot affect the build in a concerning manner. Any plugins required by the theme will have to be listed manually by the user or provided by the theme's `gemspec` file.
This feature will let the theme-gem to work with *theme-specific config variables* out-of-the-box.
{% endif %}
### 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?

View File

@ -0,0 +1,25 @@
Feature: Bundling Config file with Theme gems
As a web developer who likes to share my expertise
I want to be able to pre-configure my gemified theme
In order to make it easier for other Jekyllites to use my theme
Scenario: Easy onboarding with a pre-configured theme
Given I have a configuration file with "theme" set to "test-theme"
And I have an "index.md" page that contains "{{ site.test_theme.skin }}"
When I run jekyll build
Then I should get a zero exit status
And the _site directory should exist
And I should see "aero" in "_site/index.html"
Scenario: A pre-configured theme with valid config file overriding Jekyll defaults
Given I have a configuration file with "theme" set to "test-theme"
And I have an "index.md" page that contains "{{ site.baseurl }}"
And I have a node_modules directory
And I have a "node_modules/alert.js" file that contains "alert('foo');"
When I run jekyll build
Then I should get a zero exit status
And the _site directory should exist
And the "_site/index.html" file should exist
But the "_site/node_modules/alert.js" file should not exist
And the "_site/extras/banner.html" file should not exist
And I should not see "/test-theme" in "_site/index.html"

View File

@ -59,6 +59,8 @@ module Jekyll
self.permalink_style = config["permalink"].to_sym
# Read in a _config.yml from the current theme-gem at the very end.
@config = load_theme_configuration(config) if theme
@config
end
@ -409,6 +411,25 @@ module Jekyll
private
def load_theme_configuration(config)
theme_config_file = in_theme_dir("_config.yml")
return config unless File.exist?(theme_config_file)
# Bail out if the theme_config_file is a symlink file irrespective of safe mode
return config if File.symlink?(theme_config_file)
theme_config = SafeYAML.load_file(theme_config_file)
return config unless theme_config.is_a?(Hash)
Jekyll.logger.info "Theme Config file:", theme_config_file
# theme_config should not be overriding Jekyll's defaults
theme_config.delete_if { |key, _| Configuration::DEFAULTS.key?(key) }
# Override theme_config with existing config and return the result.
Utils.deep_merge_hashes(theme_config, config)
end
# Limits the current posts; removes the posts which exceed the limit_posts
#
# Returns nothing

14
test/fixtures/test-theme/_config.yml vendored Normal file
View File

@ -0,0 +1,14 @@
title: Hello World
baseurl: "/test-theme"
include: ["_extras/banner.md"]
exclude:
- README.md
- CHANGELOG.md
- Rakefile
- test/**/*
# theme-specific settings
test_theme:
skin: aero # aero / chrome / dark / neon
date_format: "%b -d %Y" # any format supported by strftime
header_links: true # generate header links automatically

View File

@ -588,7 +588,11 @@ class TestSite < JekyllUnitTest
should "set a theme if the config is a string" do
[:debug, :info, :warn, :error].each do |level|
expect(Jekyll.logger.writer).not_to receive(level)
if level == :info
expect(Jekyll.logger.writer).to receive(level)
else
expect(Jekyll.logger.writer).not_to receive(level)
end
end
site = fixture_site("theme" => "test-theme")
assert_instance_of Jekyll::Theme, site.theme