-
-
Notifications
You must be signed in to change notification settings - Fork 112
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
Refactor front matter handling and extract behavior into loaders #778
Refactor front matter handling and extract behavior into loaders #778
Conversation
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 a high-level review of things that I thought of while working on this. It's been several months in the making and I wanted to get it up for review before working through it anymore.
FrontmatterDefaults = ActiveSupport::Deprecation::DeprecatedConstantProxy.new( | ||
"FrontmatterDefaults", | ||
"Bridgetown::FrontMatter::Defaults" | ||
) | ||
|
||
FrontMatterImporter = ActiveSupport::Deprecation::DeprecatedConstantProxy.new( | ||
"FrontMatterImporter", | ||
"Bridgetown::FrontMatter::Importer" | ||
) |
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.
comment: I kept these to honor the move fast but try not to break things principle.
question: These don't use the Bridgetown::Deprecator
. Do we want to refactor to use it?
autoload :Ruby, "bridgetown-core/front_matter/loaders/ruby" | ||
autoload :YAML, "bridgetown-core/front_matter/loaders/yaml" | ||
|
||
Result = Struct.new(:content, :front_matter, :line_count, keyword_init: true) |
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.
comment: This should likely be marked private. I believe it should be a temporary thing.
# Registers a new type of front matter loader | ||
# | ||
# @param loader_class [Loader::Base] | ||
# @return [void] | ||
def self.register(loader_class) | ||
registry.push(loader_class) | ||
end | ||
|
||
private_class_method def self.registry | ||
@registry ||= [] | ||
end | ||
|
||
register YAML | ||
register Ruby |
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.
comment: This is at MVP stage and it's what I'm least excited about. If you notice, I register YAML before Ruby. This is because it needs to be higher precedence to maintain the original business logic of the read_from_matter
method.
I didn't want to overengineer here, but I think having both (1) symbol-based registration and (2) a priority level would be useful here. That way people can override by type and give higher precedence to a loader if needed.
Thoughts?
class Base | ||
# @param origin_or_layout [Bridgetown::Model::RepoOrigin, Bridgetown::Layout] | ||
def initialize(origin_or_layout) | ||
@origin_or_layout = origin_or_layout |
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.
comment: I don't know if there's a higher-level concept that these things both have in common. Is there?
@@ -69,7 +69,7 @@ def read_directories(dir = "") | |||
file_path = @site.in_source_dir(base, entry) | |||
if File.directory?(file_path) | |||
entries_dirs << entry | |||
elsif Utils.has_yaml_header?(file_path) || Utils.has_rbfm_header?(file_path) | |||
elsif FrontMatter::Loaders.front_matter?(file_path) |
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.
question: Would it be worth exposing this method on FrontMatter
instead?
@@ -16,7 +16,7 @@ class TestGeneratedSite < BridgetownUnitTest | |||
end | |||
|
|||
should "ensure post count is as expected" do | |||
assert_equal 51, @site.collections.posts.resources.size | |||
assert_equal 52, @site.collections.posts.resources.size |
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.
comment: This test is fragile. Should we remove it?
@@ -21,7 +21,7 @@ def setup | |||
end | |||
|
|||
should "return accept objects which respond to url" do | |||
assert_equal "<a href=\"/2020/09/10/further-nested/\">Label</a>", @helpers.link_to("Label", @site.collections.posts.resources.first) | |||
assert_equal "<a href=\"/2023/06/30/ruby-front-matter/\">Label</a>", @helpers.link_to("Label", @site.collections.posts.resources.first) |
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.
comment: This test is fragile as well. Does it pay for itself?
@@ -387,20 +387,26 @@ class TestUtils < BridgetownUnitTest | |||
end | |||
|
|||
context "The `Utils.has_yaml_header?` method" do | |||
should "accept files with YAML front matter" do |
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.
comment: These tests move into the YAML loader tests.
@@ -30,7 +30,7 @@ def eval_route_file(file, file_slug, app) # rubocop:disable Lint/UnusedMethodArg | |||
|
|||
code = File.read(file) | |||
code_postmatch = nil | |||
ruby_content = code.match(Bridgetown::FrontMatterImporter::RUBY_BLOCK) | |||
ruby_content = code.match(Bridgetown::FrontMatter::Loaders::Ruby::BLOCK) |
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.
comment: This appears to be dealing with front matter without really stating that fact. Perhaps we should refactor it?
1. `HEADER` matches the opening line of the front matter | ||
2. `BLOCK` matches the contents of the front matter block with the first capturing group being the content and the regular expression consuming the ending delimiter |
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.
question: Is this worth mentioning?
Apologies I haven't had a chance to dig into this @michaelherold, hope to soon. Thanks for working on this as it's an idea that's come up before. In fact, I could foresee relocating all of the front matter logic out to a separate gem (which then is a dependency of core), but probably it's fine to keep it in house for now (though more standalone). |
As I was working on this, I imagined having a gem that Bridgetown would use, so we're thinking along the same lines! |
This change refactors the loading of front matter into a series of classes. This is a first step toward making front matter loaders pluggable to allow, for example, [TOML][1]- or [KDL][2]-based front matter. [1]: https://toml.io [2]: https://kdl.dev/
These were developed prior to FrontMatterImporter and are no longer used.
This change reorganizes the front matter-related code so it is fully contained within the Bridgetown::FrontMatter module. That makes it easier to find the functionality and standardizes the way that Bridgetown refers to front matter. It also adds deprecated constant proxies for backwards-compatibility. It's unclear whether the moved modules were public API or not so the proxies make it so updating will not break anyone's site without warning.
This is already done by the include of the importer so isn't necessary at this point.
2ca74e3
to
11d328d
Compare
Rebased for the green checkmarks (and hit a flaky test). |
@michaelherold Better late than never! This PR looks really good, so I'm going to go ahead and merge with the expectation to release in Bridgetown v2.0. If there were any more details you wanted to go over, just let me know in a follow-up issue/PR. Thanks! |
@michaelherold don't worry, I didn't revert this for 2.0, just for the latest 1.3.3 point release (because I needed other stuff that was also in main). Still excited to get this in! |
This is a 🙋 feature or enhancement.
Summary
This change reorganizes the front matter-related code so it is fully contained within the Bridgetown::FrontMatter module. That makes it easier to find the functionality and standardizes the way that Bridgetown refers to front matter.
It also adds deprecated constant proxies for backwards-compatibility. It's unclear whether the moved modules were public API or not so the proxies make it so updating will not break anyone's site without warning.
This change also refactors the loading of front matter into a series of classes. This is a first step toward making front matter loaders pluggable to allow, for example, TOML- or KDL-based front matter.
Context
This accomplishes much of the "open to extension" goal in #777.