Skip to content
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

Adding possibility to change pagination message by config file #324

Merged

Conversation

AlekseySpiridonov
Copy link
Contributor

Default message can by overriten by "paginator_message" parameter in _config.yml

This change allows you to change messages for localize the site to other languages.

@AlekseySpiridonov
Copy link
Contributor Author

I added information about this change to docs/advanced-usage.md

@AlekseySpiridonov AlekseySpiridonov force-pushed the add-custom-paginator-message branch 3 times, most recently from 9c5aedf to 692f467 Compare January 4, 2019 20:16
@AlekseySpiridonov
Copy link
Contributor Author

I am working on tests and changes for build.
I will update this PR.

@AlekseySpiridonov
Copy link
Contributor Author

I am working on tests. It takes some time. I will update this PR.

@AlekseySpiridonov
Copy link
Contributor Author

I have problem with tests for this change (Sorry, I am not Ruby developer. I just backported my own change for my site from local repository, because it looks like helpful for other users).

Looks like I need something like in file spec/jekyll_seo_tag/drop_spec.rb

  context "page_number" do
    let(:paginator) {{ "page" => 2, "total_pages" => 10 }}

    it "check paginator default message" do
      expect(subject.send(:page_number)).to eq("Page 2 of 10 for ")
    end
  end

for testing page_number function.
But it isn't work.

Could you please help\advise with tests for this change?
Thanks.

@ashmaroli
Copy link
Member

@AlekseySpiridonov Testing this particular change with RSpec appears to be hard because @context["paginator"] is defined by another plugin (jekyll-paginate) which is not loaded by default. But, if you go through the spec file and the spec_helper file, you'll realize that things are actually quite simple:

  context "pagination" do
    let(:context) do
      make_context(
        { :page => page, :site => site },
        "paginator" => { "page" => 2, "total_pages" => 10 }
      )
    end

    it "renders the correct page number" do
      expect(subject.send(:page_number)).to eq("Page 2 of 10 for ")
    end
  end

The above will pass for the default message. Once that's done, you need to test for the custom message as well:

  context "pagination" do
    let(:context) do
      make_context(
        { :page => page, :site => site },
        "paginator" => { "page" => 2, "total_pages" => 10 }
      )
    end

    it "renders the correct page number" do
      expect(subject.send(:page_number)).to eq("Page 2 of 10 for ")
    end

    # nested context
    context "with custom pagination message" do
      let(:config) { ... }

      it "" do
      end
    end

@AlekseySpiridonov
Copy link
Contributor Author

@ashmaroli I added tests but it always failed.

Commit - fbecf19

Logs:

Failures:

  1) Jekyll::SeoTag::Drop pagination renders the correct page number
     Failure/Error: paginator_message ||= @site["paginator_message"] || "Page #{current} of #{total} for "
     
     NoMethodError:
       undefined method `[]' for nil:NilClass
     # ./lib/jekyll-seo-tag/drop.rb:192:in `page_number'
     # ./spec/jekyll_seo_tag/drop_spec.rb:494:in `block (3 levels) in <top (required)>'

  2) Jekyll::SeoTag::Drop with custom pagination message renders the correct page number
     Failure/Error: let(:config) {{ "paginator_message" => "#{current} of #{total}" }}
     
     NameError:
       undefined local variable or method `current' for #<RSpec::ExampleGroups::JekyllSeoTagDrop::WithCustomPaginationMessage:0x00007f9f7f2a0d20>
     # ./spec/jekyll_seo_tag/drop_spec.rb:499:in `block (3 levels) in <top (required)>'
     # ./spec/jekyll_seo_tag/drop_spec.rb:7:in `block (2 levels) in <top (required)>'
     # ./spec/spec_helper.rb:35:in `make_page'
     # ./spec/jekyll_seo_tag/drop_spec.rb:6:in `block (2 levels) in <top (required)>'
     # ./spec/jekyll_seo_tag/drop_spec.rb:8:in `block (2 levels) in <top (required)>'
     # ./spec/jekyll_seo_tag/drop_spec.rb:10:in `block (2 levels) in <top (required)>'
     # ./spec/jekyll_seo_tag/drop_spec.rb:502:in `block (3 levels) in <top (required)>'

Finished in 1.12 seconds (files took 1.18 seconds to load)
202 examples, 2 failures

Could you please check my commit?
Thanks.

@ashmaroli
Copy link
Member

@AlekseySpiridonov I knew it would fail. That's the beauty of test-driven-development.
I did not tell it to you beforehand because you would not be able to understand why it would fail..

The fact is that while your implementation works, technically it is not the proper way.
paginator_message.sub("#\{current\}", current.to_s).sub("#\{total\}", total.to_s) is just a hack. Additionally, there is one other mistake in your implementation.

  • ||= is not what you think it is doing and is useless in the current context.
  • Instead of gsub-ing placeholders, use a proper "string template"

So, the :page_number method ought to be something like:

      def page_number
        return unless @context["paginator"] && @context["paginator"]["page"]

        current = @context["paginator"]["page"]
        total = @context["paginator"]["total_pages"]
        paginator_message = site["paginator_message"] || "Page %<current>s of %<total>s for "

        format(paginator_message, :current => current, :total => total) if current > 1
      end

"Page %<current>s of %<total>s for " is the string-template which will "rendered" by the format() call in the succeeding line.

There's one other teeny mistake in your test as well: your custom-message context is not nested under the default-message context. Perhaps, my example wasn't clear enough.
It should be something like:

context "..." do
  ...
  context "..." do
    ...
  end
end

So, the test will be something like:

context "pagination" do
  let(:context) do
    ...
  end

  it "renders.." do
    ...
  end

  # nested context
  context "with custom message..." do
    let(:config) { { "paginator_message" => "%<current>s of %<total>s" }  }

    it "renders..." do
      ...
    end
  end
end

Now what you have to do is:

  • Correct the test
  • Correct your implementation
  • Correct the documentation asking users to provide the "string template" that contains two variables current and total that will be replaced as necessary.

@AlekseySpiridonov AlekseySpiridonov force-pushed the add-custom-paginator-message branch 2 times, most recently from 6266ea5 to 95a80e3 Compare January 5, 2019 21:20
Default message can by overriten by "paginator_message" parameter in _config.yml
@AlekseySpiridonov AlekseySpiridonov force-pushed the add-custom-paginator-message branch from 95a80e3 to 39269ed Compare January 5, 2019 21:22
@AlekseySpiridonov
Copy link
Contributor Author

@ashmaroli thank you so much.
I changed my PR.

@ashmaroli
Copy link
Member

ashmaroli commented Jan 6, 2019

TODO: Merge in master once #325 gets merged

@ashmaroli
Copy link
Member

@jekyll/plugin-core Should we nest the paginator_message key under a plugin-specific config key..? If yes, what would the key be..?

@ashmaroli ashmaroli requested a review from a team January 7, 2019 02:57
@benbalter
Copy link
Collaborator

Would it make sense to change the message (in all cases) to "Page ___ / ____" and then just allow "page" to be localized, rather than going down the path of string interpolation? If we are going that route, would a sprintf style %d make more sense/be a cleaner implementation than matching pseduo-ruby in a string?

@ashmaroli
Copy link
Member

ashmaroli commented Jan 7, 2019

would a sprintf style %d make more sense/be a cleaner implementation than matching pseduo-ruby in a string?

@benbalter The current approach uses Kernel#format. Isn't that synonymous with / superior over Kernel#sprintf?
Please excuse my naivety, but could you explain how using sprintf would be a cleaner impl.. and what you meant by "matching pseudo-ruby in a string"..??

@benbalter
Copy link
Collaborator

@ashmaroli I think I was looking at an outdated diff. Sorry for the noise and thanks for taking the time to further explain. 👍

Copy link
Member

@DirtyF DirtyF left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's nice to be able to localize messages.
I wish every plugin would use a proper namespace though instead of adding another global config key. Maybe we can revisit all current settings under a common key in next major version?

@AlekseySpiridonov
Copy link
Contributor Author

Do you need some additional changes from my side or we are waiting review?

@berserk24
Copy link

I need this change. +1 for merge this pool request.

Copy link
Member

@DirtyF DirtyF left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yay for string translations.

@mattr-
Copy link
Member

mattr- commented Oct 8, 2019

@jekyllbot: merge +minor

@jekyllbot jekyllbot merged commit 32ce891 into jekyll:master Oct 8, 2019
jekyllbot added a commit that referenced this pull request Oct 8, 2019
@AlekseySpiridonov
Copy link
Contributor Author

Thanks a lot!

@jekyll jekyll locked and limited conversation to collaborators Oct 17, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants