-
-
Notifications
You must be signed in to change notification settings - Fork 9.9k
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
Conversation
If the theme includes the 'assets' directory, it will be walked and items will be added to the site based on the normal rules of Jekyll: if there is YAML front matter, it will be added as a (convertible) Page, otherwise it will be added as a StaticFile.
@@ -16,7 +16,7 @@ Lint/UnreachableCode: | |||
Lint/UselessAccessModifier: | |||
Enabled: false | |||
Metrics/AbcSize: | |||
Max: 20 | |||
Max: 21 |
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.
😇
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.
This is awesome. So excited for this. This will hugely simplify the user experience for themes and in improve the developer experience for theme creators. Two other things to do in this PR, in my mind:
- Update the docs
- Update the default site to not to write a CSS file (and add that file to minima instead)
@@ -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 comment
The 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 comment
The 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 /home/user/work/home/user/.gems/[...]/theme.html
instead of /home/user/.gems/[...]/theme.html
.
@parkr Have you tried this out with various symbolic links? I'm worried it might be a bit weird, depending on how base
is set (I haven't checked, myself)
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.
@benbalter When you include assets/styles.scss
with YAML front matter, it's a Jekyll::Page
. To ensure it's read properly, we need to make sure we're looking in the theme's directory rather than your site's directory. This if
says "if this Page is inside our theme directory then ensure the @path
gets set properly."
module Jekyll | ||
class ThemeAssetsReader | ||
attr_reader :site | ||
def initialize(site) |
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.
Whitespace here?
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.
This is copied from another reader. I don't have a personal preference and we don't have it enforced in our Rubocop config.
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 comment
The reason will be displayed to describe this comment to others. Learn more.
Really elegant implementation.
@@ -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 comment
The 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 _
) and special case assets
so that we treat all of them as named folders, rather than paths?
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.
If we're passing symbols like :_layouts
, why is it called realpath_for
? It's just like Site#in_theme_dir
, except it takes a symbol. I think realpath_for
should be an abstraction (special case :assets
, for example)
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.
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 _
, then let's ask for it that way. It's way more direct to ask for _sass
and get _sass
then to ask for sass
and get _sass
.
@spudowiar The difference here is that this uses File.realpath
which resolves symlinks. Site#in_theme_dir
does not.
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.
Makes sense. Would a string be a better fit stylistically then?
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 comment
The 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 comment
The 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 comment
The reason will be displayed to describe this comment to others. Learn more.
If I have /assets/foo.js
in my site, and /assets/foo.js
in my theme, to confirm /assests/foo.js
in the resulting site contain's the site's content, not the theme's.
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 comment
The 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 Jekyll::Layout
we use the equivalent of path.sub(site.theme.root, "")
and in the Jekyll::Document
we use Pathutil
and there are probably more ways we're doing this. 😖
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.
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. assets
). If you do path.sub(site.theme.root, "")
, you get /assets
and we can't use Pathutil because it doesn't work on Windows the way we're using it.
@@ -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) |
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.
Not happy with this at all, Theme#path_for
sounds like it should be an abstraction, looks like it's just a sugary version of Site#in_theme_dir
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.
It's not, as I mention above.
@benbalter I think we're ready for another review. I left a few comments. As for "Update the default site to not to write a CSS file (and add that file to minima instead)", this will have to be in another PR which results from a minima release. I don't think that's a good idea to do here. |
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.
One question about if we need a test to ensure the files in the site's assets folder are given preference over files in the theme's asset folder, otherwise, LGTM. Nice work. Glad this wasn't too crazy to implement.
…xisting site files.
Done in 29d8fee. |
@jekyllbot: merge +minor |
If the theme includes the 'assets' directory, it will be walked and items will be added to the site based on the normal rules of Jekyll: if there is YAML front matter, it will be added as a (convertible) Page, otherwise it will be added as a StaticFile. It will output to the
assets/
directory.[Image available, but airplane WiFi is spotty.]
jekyll new-theme
looks forassets/
if present/cc @jekyll/ecosystem @benbalter @broccolini