Merge pull request #5364 from jekyll/themes-asset-folder
Merge pull request 5364
This commit is contained in:
commit
3a45bf7d26
|
@ -16,7 +16,7 @@ Lint/UnreachableCode:
|
|||
Lint/UselessAccessModifier:
|
||||
Enabled: false
|
||||
Metrics/AbcSize:
|
||||
Max: 20
|
||||
Max: 21
|
||||
Metrics/ClassLength:
|
||||
Exclude:
|
||||
- !ruby/regexp /features\/.*.rb$/
|
||||
|
|
|
@ -17,7 +17,7 @@ Feature: Writing themes
|
|||
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';"
|
||||
And I have a "css/main.scss" page that contains "@import 'test-theme-black';"
|
||||
When I run jekyll build
|
||||
Then I should get a zero exit status
|
||||
And the _site directory should exist
|
||||
|
|
|
@ -55,6 +55,7 @@ module Jekyll
|
|||
autoload :PostReader, "jekyll/readers/post_reader"
|
||||
autoload :PageReader, "jekyll/readers/page_reader"
|
||||
autoload :StaticFileReader, "jekyll/readers/static_file_reader"
|
||||
autoload :ThemeAssetsReader, "jekyll/readers/theme_assets_reader"
|
||||
autoload :LogAdapter, "jekyll/log_adapter"
|
||||
autoload :Page, "jekyll/page"
|
||||
autoload :PluginManager, "jekyll/plugin_manager"
|
||||
|
|
|
@ -40,7 +40,11 @@ module Jekyll
|
|||
@base = base
|
||||
@dir = dir
|
||||
@name = name
|
||||
@path = site.in_source_dir(base, dir, name)
|
||||
@path = if site.in_theme_dir(base) == base # we're in a theme
|
||||
site.in_theme_dir(base, dir, name)
|
||||
else
|
||||
site.in_source_dir(base, dir, name)
|
||||
end
|
||||
|
||||
process(name)
|
||||
read_yaml(File.join(base, dir), name)
|
||||
|
|
|
@ -18,6 +18,7 @@ module Jekyll
|
|||
sort_files!
|
||||
@site.data = DataReader.new(site).read(site.config["data_dir"])
|
||||
CollectionReader.new(site).read
|
||||
ThemeAssetsReader.new(site).read
|
||||
end
|
||||
|
||||
# Sorts posts, pages, and static files.
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
module Jekyll
|
||||
class ThemeAssetsReader
|
||||
attr_reader :site
|
||||
def initialize(site)
|
||||
@site = site
|
||||
end
|
||||
|
||||
def read
|
||||
return unless site.theme && site.theme.assets_path
|
||||
|
||||
Find.find(site.theme.assets_path) do |path|
|
||||
next if File.directory?(path)
|
||||
if File.symlink?(path)
|
||||
Jekyll.logger.warn "Theme reader:", "Ignored symlinked asset: #{path}"
|
||||
else
|
||||
read_theme_asset(path)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def read_theme_asset(path)
|
||||
base = site.theme.root
|
||||
dir = File.dirname(path.sub("#{site.theme.root}/", ""))
|
||||
name = File.basename(path)
|
||||
|
||||
if Utils.has_yaml_header?(path)
|
||||
append_unless_exists site.pages,
|
||||
Jekyll::Page.new(site, base, dir, name)
|
||||
else
|
||||
append_unless_exists site.static_files,
|
||||
Jekyll::StaticFile.new(site, base, dir, name)
|
||||
end
|
||||
end
|
||||
|
||||
def append_unless_exists(haystack, new_item)
|
||||
if haystack.any? { |file| file.relative_path == new_item.relative_path }
|
||||
Jekyll.logger.debug "Theme:",
|
||||
"Ignoring #{new_item.relative_path} in theme due to existing file " \
|
||||
"with that path in site."
|
||||
return
|
||||
end
|
||||
|
||||
haystack << new_item
|
||||
end
|
||||
end
|
||||
end
|
|
@ -18,15 +18,19 @@ module Jekyll
|
|||
end
|
||||
|
||||
def includes_path
|
||||
path_for :includes
|
||||
path_for "_includes".freeze
|
||||
end
|
||||
|
||||
def layouts_path
|
||||
path_for :layouts
|
||||
path_for "_layouts".freeze
|
||||
end
|
||||
|
||||
def sass_path
|
||||
path_for :sass
|
||||
path_for "_sass".freeze
|
||||
end
|
||||
|
||||
def assets_path
|
||||
path_for "assets".freeze
|
||||
end
|
||||
|
||||
def configure_sass
|
||||
|
@ -43,7 +47,7 @@ module Jekyll
|
|||
end
|
||||
|
||||
def realpath_for(folder)
|
||||
File.realpath(Jekyll.sanitized_path(root, "_#{folder}"))
|
||||
File.realpath(Jekyll.sanitized_path(root, folder.to_s))
|
||||
rescue Errno::ENOENT, Errno::EACCES, Errno::ELOOP
|
||||
nil
|
||||
end
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
class Jekyll::ThemeBuilder
|
||||
SCAFFOLD_DIRECTORIES = %w(
|
||||
_layouts _includes _sass
|
||||
assets _layouts _includes _sass
|
||||
).freeze
|
||||
|
||||
attr_reader :name, :path, :code_of_conduct
|
||||
|
|
|
@ -27,6 +27,7 @@ Jekyll themes set default layouts, includes, and stylesheets, that can be overri
|
|||
|
||||
Jekyll will look first to your site's content, before looking to the theme's defaults, for any requested file in the following folders:
|
||||
|
||||
* `/assets`
|
||||
* `/_layouts`
|
||||
* `/_includes`
|
||||
* `/_sass`
|
||||
|
@ -68,6 +69,12 @@ Theme layouts and includes work just like they work in any Jekyll site. Place la
|
|||
|
||||
For example, if your theme has a `/_layouts/page.html` file, and a page has `layout: page` in its YAML front matter, Jekyll will first look to the site's `_layouts` folder for a the `page` layout, and if none exists, will use your theme's `page` layout.
|
||||
|
||||
### Assets
|
||||
|
||||
Any file in `/assets` will be copied over to the user's site upon build unless they have a file with the same relative path. You may ship any kind of asset here: SCSS, an image, a webfont, etc. These files behave just like pages and static files in Jekyll: if the file has [YAML front matter]({{ site.baseurl }}/docs/frontmatter/) at the top, then it will be rendered. If it does not have YAML front matter, it will simply be copied over into the resulting site. This allows theme creators to ship a default `/assets/styles.scss` file which their layouts can depend on as `/assets/styles.css`.
|
||||
|
||||
All files in `/assets` will be output into the compiled site in the `/assets` folder just as you'd expect from using Jekyll on your sites.
|
||||
|
||||
### Stylesheets
|
||||
|
||||
Your theme's stylesheets should be placed in your theme's `/_sass` folder, again, just as you would when authoring a Jekyll site. Your theme's styles can be included in the user's stylesheet using the `@import` directive.
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
.sample {
|
||||
color: red;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
---
|
||||
---
|
||||
alert "From your theme."
|
|
@ -0,0 +1 @@
|
|||
logo.png
|
Binary file not shown.
After Width: | Height: | Size: 3.4 KiB |
|
@ -0,0 +1,3 @@
|
|||
---
|
||||
---
|
||||
@import "test-theme-{{ site.theme-color | default: "red" }}";
|
|
@ -0,0 +1,3 @@
|
|||
---
|
||||
---
|
||||
alert "From your site."
|
|
@ -475,7 +475,7 @@ class TestFilters < JekyllUnitTest
|
|||
g["items"].is_a?(Array),
|
||||
"The list of grouped items for '' is not an Array."
|
||||
)
|
||||
assert_equal 14, g["items"].size
|
||||
assert_equal 15, g["items"].size
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -180,6 +180,7 @@ class TestSite < JekyllUnitTest
|
|||
%#\ +.md
|
||||
.htaccess
|
||||
about.html
|
||||
application.coffee
|
||||
bar.html
|
||||
coffeescript.coffee
|
||||
contacts.html
|
||||
|
|
|
@ -34,16 +34,16 @@ class TestTheme < JekyllUnitTest
|
|||
end
|
||||
|
||||
context "path generation" do
|
||||
[:layouts, :includes, :sass].each do |folder|
|
||||
[:assets, :_layouts, :_includes, :_sass].each do |folder|
|
||||
should "know the #{folder} path" do
|
||||
expected = File.expand_path("_#{folder}", @expected_root)
|
||||
assert_equal expected, @theme.public_send("#{folder}_path")
|
||||
expected = File.expand_path(folder.to_s, @expected_root)
|
||||
assert_equal expected, @theme.public_send("#{folder.to_s.tr("_", "")}_path")
|
||||
end
|
||||
end
|
||||
|
||||
should "generate folder paths" do
|
||||
expected = File.expand_path("./_sass", @expected_root)
|
||||
assert_equal expected, @theme.send(:path_for, :sass)
|
||||
assert_equal expected, @theme.send(:path_for, :_sass)
|
||||
end
|
||||
|
||||
should "not allow paths outside of the theme root" do
|
||||
|
@ -56,7 +56,7 @@ class TestTheme < JekyllUnitTest
|
|||
|
||||
should "return the resolved path when a symlink & resolved path exists" do
|
||||
expected = File.expand_path("./_layouts", @expected_root)
|
||||
assert_equal expected, @theme.send(:path_for, :symlink)
|
||||
assert_equal expected, @theme.send(:path_for, :_symlink)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
require "helper"
|
||||
|
||||
class TestThemeAssetsReader < JekyllUnitTest
|
||||
def setup
|
||||
@site = fixture_site(
|
||||
"theme" => "test-theme",
|
||||
"theme-color" => "black"
|
||||
)
|
||||
assert @site.theme
|
||||
end
|
||||
|
||||
def assert_file_with_relative_path(haystack, relative_path)
|
||||
assert haystack.any? { |f|
|
||||
f.relative_path == relative_path
|
||||
}, "Site should read in the #{relative_path} file, " \
|
||||
"but it was not found in #{haystack.inspect}"
|
||||
end
|
||||
|
||||
def refute_file_with_relative_path(haystack, relative_path)
|
||||
refute haystack.any? { |f|
|
||||
f.relative_path == relative_path
|
||||
}, "Site should not have read in the #{relative_path} file, " \
|
||||
"but it was found in #{haystack.inspect}"
|
||||
end
|
||||
|
||||
context "with a valid theme" do
|
||||
should "read all assets" do
|
||||
@site.reset
|
||||
ThemeAssetsReader.new(@site).read
|
||||
assert_file_with_relative_path @site.static_files, "assets/img/logo.png"
|
||||
assert_file_with_relative_path @site.pages, "assets/style.scss"
|
||||
end
|
||||
|
||||
should "convert pages" do
|
||||
@site.process
|
||||
|
||||
file = @site.pages.find { |f| f.relative_path == "assets/style.scss" }
|
||||
refute_nil file
|
||||
assert_equal @site.in_dest_dir("assets/style.css"), file.destination(@site.dest)
|
||||
assert_includes file.output, ".sample {\n color: black; }"
|
||||
end
|
||||
|
||||
should "not overwrite site content with the same relative path" do
|
||||
@site.reset
|
||||
@site.read
|
||||
|
||||
file = @site.pages.find { |f| f.relative_path == "assets/application.coffee" }
|
||||
refute_nil file
|
||||
assert_includes file.content, "alert \"From your site.\""
|
||||
end
|
||||
end
|
||||
|
||||
context "with a valid theme without an assets dir" do
|
||||
should "not read any assets" do
|
||||
site = fixture_site("theme" => "test-theme")
|
||||
allow(site.theme).to receive(:assets_path).and_return(nil)
|
||||
ThemeAssetsReader.new(site).read
|
||||
refute_file_with_relative_path site.static_files, "assets/img/logo.png"
|
||||
refute_file_with_relative_path site.pages, "assets/style.scss"
|
||||
end
|
||||
end
|
||||
|
||||
context "with no theme" do
|
||||
should "not read any assets" do
|
||||
site = fixture_site("theme" => nil)
|
||||
ThemeAssetsReader.new(site).read
|
||||
refute_file_with_relative_path site.static_files, "assets/img/logo.png"
|
||||
refute_file_with_relative_path site.pages, "assets/style.scss"
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue