-
Notifications
You must be signed in to change notification settings - Fork 117
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
Push redirect logic to the redirect page model #131
Conversation
For me, as long as all the pre-existing integration-level tests pass without alteration (i.e. it still generates all the redirect_from and redirect_to pages as it did previously), then I'm happy with whatever architecture is easiest to maintain. I can't take a close look at this now, but I'll try to get to it soon. I gladly defer to @pathawks's judgement here as well, so if he thinks it's 👍 then merge and release! |
@@ -9,18 +9,11 @@ matrix: | |||
- # GitHub Pages | |||
rvm: 2.1.1 |
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.
Note to self that this should be bumped to 2.3.3
at some point.
Explicitly, there are two integration tests, which I expanded on. There are also a handful of integration-ish specs (does this file exist?) in the redirector spec, which I believe I ported over, |
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.
Let's separate the extensionless HTML files discussion into a separate PR and for now continue the previous behavior.
Otherwise, the only change in behavior I can find is that in one particular circumstance, the previous version would output a relative URL where this outputs an absolute URL.
Because in other circumstances the previous version would output an absolute URL, I am willing to call this a bug in the old code and say the _new_behavior is correct.
# to which the document should be redirected | ||
def redirect_to | ||
if to_liquid["redirect_to"].is_a?(Array) | ||
to_liquid["redirect_to"].compact.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.
I see this is the current behavior, but something has gone wrong if this is an array, right?
We can save that for later.
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.
Correct. redirect_to
can be an array, an we absorb the complexity of YAML and just deal with it. I'm fine with that, as many users think that array-style markup with a single entry is the proper way to do things (and I'd rather add a few method calls then break their site).
<!DOCTYPE html> | ||
<html lang="en-US"> | ||
<meta charset="utf-8"> | ||
<title>Redirecting...</title> |
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 we change these back to …
?
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 strongly opinionated, but what's the value?
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 mean to use an ellipsis. We can use an ellipsis. We should use an ellipsis.
# Overwrite the default read_yaml method since the file doesn't exist | ||
def read_yaml(_base, _name, _opts = {}) | ||
self.content = "" | ||
self.data ||= DEFAULT_DATA.dup |
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.
Why ||=
? It seems like it should either be just an assignment or a merge.
When would self.data
already be set at this point?
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.
Ahh. You are correct.
class RedirectPage < Jekyll::Page | ||
# Initialize a new RedirectPage. | ||
# Use Jekyll's native absolute_url filter | ||
include Jekyll::Filters::URLFilters |
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 really wish there were a better way to do this.
Maybe the relative URL logic should be broken into a utility method?
|
||
Jekyll::Hooks.trigger :pages, :post_init, self if JekyllRedirectFrom.jekyll_3? | ||
# Redirects without a trailing slash should produce extentionless 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.
This is a regression.
Some servers will not serve extensionless files as text/html
, which causes the browser to just download the binary file instead of loading it and following the redirect.
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 agree, but was going off of what was in the README. What's the desired behavior here?
Can you clarify? Although I personally disagree with it, I thought I was implementing the behavior described in the README, no? (or is that what you're suggesting?)
That was my thinking, especially because there's a canonical URL field, that must be absolute. Also glad to expose relative and absolute URL fields, but I feel like that's overly complicated what should be a decision on our part. |
It seems the behavior changed for Jekyll 3. Current tests check to make sure that files have extensions. spec_helper.rb: def forced_output_ext
JekyllRedirectFrom.jekyll_3? ? ".html" : ""
end redirector_spec.rb: it "generates the refresh page for the post properly" do
expect(dest_dir("posts/23128432159832/mary-had-a-little-lamb#{forced_output_ext}")).to exist
end If |
If you compare the |
So |
According to the fixture site: ---
redirect_from: /articles/23128432159832/mary-had-a-little-lamb
--- is rendered as That is the current behavior as of v0.11.0. |
Here are the relevant tests:
Just want to confirm before I implement the change, this line from the README:
Is not true? If we're not implementing the documented behavior, is that a bug or are the docs just out of date? Basically, it sounds like the desired behavior is that a redirect from without an extension should be given a |
Yes, it sounds like the docs and the code are in conflict. Relevant PR: #96 |
@pathawks take a look at 124f85a, which should now implement that logic (always append jekyll-redirect-from/spec/integrations_spec.rb Lines 51 to 56 in 124f85a
|
@pathawks, thanks, as always, for the critical 👀. |
@@ -18,10 +18,11 @@ Gem::Specification.new do |spec| | |||
spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) | |||
spec.require_paths = ["lib"] | |||
|
|||
spec.add_runtime_dependency "jekyll", ">= 2.0" | |||
spec.add_runtime_dependency "jekyll", "~> 3.0" |
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.
3.3 since we're using URL filters
Thank you for all of the work here @benbalter This will make the plugin much more robust 👍 |
@jekyllbot: merge +major. |
Can we make a note in the release notes about respecting a custom Thanks! |
https://github.com/jekyll/jekyll-redirect-from/releases/tag/v0.12.0 had "Support for custom redirect templates" as the first major change. Updated to "Use |
I did exactly what you're not supposed to do, but I did it, so I'm hoping we could still use it.
I went to tackle #125, but realized the way things were architechted, it'd be a bit tricky to do, since so much of the redirect logic was in the generator model, which was procedural and already large.
This all began when I opened Atom, and Rubocop started complaining about method length and complexity. So I started to add Rubocop, but in order to get
Generator#render
small enough, I needed to keep pushing logic into smaller methods, and it felt very un-OO to be passing the document/page around.Then I thought, that instead, the RedirectPage should know all the things it needs to know to build itself. That's how object-oriented programming is supposed to work! So I began to pull the redirect logic out of the generator (which should concern itself with looping through things), and pushed it into the RedirectPage model.
That's all a long way to say that this embarrassingly large PR does a few things, while (theoretically) maintaining the existing functionality:
redirect_from
andredirect_to
YAML parsing logic into the Page and Document models directly (with#redirect_from
andredirect_to
helper methods that return consistent output)_layout/redirect.html
to their sitePage#read_yaml
, the RedirectPage uses the standardPage#initialize
method (less custom code)absolute_url
filter to generate canonical URLsredirect_to
'sis_*?
andhas_*?
helpers from the generatorFrom a developer benefit, the big benefit here is adherence to Jekyll style (including method length and complexity), and a more object-oriented architecture.
From an end-user perspective, the benefit is relying more heavily on Jekyll internals, meaning theoretically, more consistent behavior, and new features going forward, in addition to custom template support.
From a going forward perspective, #125 can now be as simple as
site.pages.map { |p| p.data["redirect"] }.compact.to_json
.I believe @parkr's 🚗, but /cc @pathawks for 👀?
Fixes #128, #130
I think it should also fix #129 and #114.