From f728f6968daf156628eb1392a790ef68fa5aee99 Mon Sep 17 00:00:00 2001 From: Pierre de La Morinerie Date: Mon, 30 Oct 2023 22:58:25 +0100 Subject: [PATCH] Truncate to words, and add setting and doc --- docs/advanced-usage.md | 10 ++++++++ lib/jekyll-seo-tag/drop.rb | 13 +++++++++- spec/jekyll_seo_tag/drop_spec.rb | 18 ++++++++++++++ spec/jekyll_seo_tag_integration_spec.rb | 33 +++++++++++++++++++++++++ 4 files changed, 73 insertions(+), 1 deletion(-) diff --git a/docs/advanced-usage.md b/docs/advanced-usage.md index f334496..0a5ad70 100644 --- a/docs/advanced-usage.md +++ b/docs/advanced-usage.md @@ -80,6 +80,16 @@ You can set it the same way as the other author properties. For example, you can url: https://example.com/ ``` +### Customizing description length + +By default the description is limited to the first 50 words of the full content. + +You can adjust this limit either at the page level or at the site level, by using the `seo_description_max_words` page property: + +```yml + seo_description_max_words: 100 +``` + ### Customizing JSON-LD output The following options can be set for any particular page. While the default options are meant to serve most users in the most common circumstances, there may be situations where more precise control is necessary. diff --git a/lib/jekyll-seo-tag/drop.rb b/lib/jekyll-seo-tag/drop.rb index 56a291e..525e946 100644 --- a/lib/jekyll-seo-tag/drop.rb +++ b/lib/jekyll-seo-tag/drop.rb @@ -90,7 +90,7 @@ module Jekyll def description @description ||= begin value = format_string(page["description"] || page["excerpt"]) || site_description - filters.truncate(value, 280) + snippet(value, description_max_words) end end @@ -176,6 +176,10 @@ module Jekyll end end + def description_max_words + @description_max_words ||= page["seo_description_max_words"] || site["seo_description_max_words"] || 50 + end + private def filters @@ -218,6 +222,13 @@ module Jekyll string unless string.empty? end + def snippet(string, max_words) + return string if string.nil? + + result = string.split(%r!\s+!, max_words + 1)[0...max_words].join(" ") + result.length < string.length ? result.concat("…") : result + end + def seo_name @seo_name ||= format_string(page_seo["name"]) if page_seo["name"] end diff --git a/spec/jekyll_seo_tag/drop_spec.rb b/spec/jekyll_seo_tag/drop_spec.rb index 574213f..53f48f9 100644 --- a/spec/jekyll_seo_tag/drop_spec.rb +++ b/spec/jekyll_seo_tag/drop_spec.rb @@ -233,6 +233,24 @@ RSpec.describe Jekyll::SeoTag::Drop do expect(subject.description).to be_nil end end + + context "truncation" do + context "without seo_description_max_words" do + let(:page_meta) { { "description" => "word " * 150 } } + + it "truncates the description to the first 200 words" do + expect(subject.description).to eql(("word " * 100).chop.concat("…")) + end + end + + context "with an explicit seo_description_max_words property" do + let(:page_meta) { { "description" => "For a long time, I went to bed early", "seo_description_max_words" => 6 } } + + it "truncates the description to the configured words count" do + expect(subject.description).to eql("For a long time, I went…") + end + end + end end context "author" do diff --git a/spec/jekyll_seo_tag_integration_spec.rb b/spec/jekyll_seo_tag_integration_spec.rb index f7b1cb8..2117c51 100755 --- a/spec/jekyll_seo_tag_integration_spec.rb +++ b/spec/jekyll_seo_tag_integration_spec.rb @@ -350,6 +350,39 @@ RSpec.describe Jekyll::SeoTag do it "removes null values from JSON-LD" do expect(output).to_not match(%r!:null!) end + + context "description" do + context "with site.seo_description_max_words" do + let(:site) { make_site("url" => "http://example.invalid", "seo_description_max_words" => 6) } + let(:meta) do + { + "title" => "post", + "description" => "For a long time, I went to bed early", + "image" => "/img.png" + } + end + + it "truncates the description" do + expect(json_data["description"]).to eql("For a long time, I went…") + end + end + + context "with page.seo_description_max_words" do + let(:site) { make_site("url" => "http://example.invalid", "seo_description_max_words" => 10) } + let(:meta) do + { + "title" => "post", + "description" => "For a long time, I went to bed early", + "image" => "/img.png", + "seo_description_max_words" => 6, + } + end + + it "truncates the description" do + expect(json_data["description"]).to eql("For a long time, I went…") + end + end + end end end