New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ThemeAssetsReader which reads assets from a theme #5364
Changes from all commits
13aec48
87b9cfe
cf26bf5
6d7f305
74baeb8
7309ecf
b78827c
29d8fee
279f151
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,7 +40,11 @@ def initialize(site, base, dir, name) | |
@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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you explain a bit more as to what's going on here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @benbalter AFAIK, it essentially makes sure that we're normalising into the theme directory, rather than into the source directory, otherwise you might get @parkr Have you tried this out with various symbolic links? I'm worried it might be a bit weird, depending on how There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @benbalter When you include |
||
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) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
module Jekyll | ||
class ThemeAssetsReader | ||
attr_reader :site | ||
def initialize(site) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Whitespace here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is copied from another reader. I don't have a personal preference and we don't have it enforced in our Rubocop config. |
||
@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}/", "")) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We do this same thing at least 2 different ways elsewhere, in the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would be nice to have a "relative_from" method or something but it depends on what you need. In this case, I want all directories within the theme directory without the forward slash at the beginning (e.g. |
||
name = File.basename(path) | ||
|
||
if Utils.has_yaml_header?(path) | ||
append_unless_exists site.pages, | ||
Jekyll::Page.new(site, base, dir, name) | ||
else | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Really elegant implementation. |
||
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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,15 +18,19 @@ def root | |
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 @@ def path_for(folder) | |
end | ||
|
||
def realpath_for(folder) | ||
File.realpath(Jekyll.sanitized_path(root, "_#{folder}")) | ||
File.realpath(Jekyll.sanitized_path(root, folder.to_s)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm torn here. Do we want to pass vanilla symbols (without the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we're passing symbols like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Special casing is a non-starter for me in this already complicated codebase. I want a way to fetch the path on disk for a directory. If the directory starts with a @spudowiar The difference here is that this uses There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Makes sense. Would a string be a better fit stylistically then? |
||
rescue Errno::ENOENT, Errno::EACCES, Errno::ELOOP | ||
nil | ||
end | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
.sample { | ||
color: red; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
--- | ||
--- | ||
alert "From your theme." |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
logo.png |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
--- | ||
--- | ||
@import "test-theme-{{ site.theme-color | default: "red" }}"; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
--- | ||
--- | ||
alert "From your site." |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,16 +34,16 @@ def setup | |
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 @@ def setup | |
|
||
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) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not happy with this at all, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's not, as I mention above. |
||
end | ||
end | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you want to test that it doesn't clobber site files? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Clobber? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If I have |
||
|
||
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's cheating! 😉
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😇