diff --git a/gems/kettle-jem/lib/kettle/jem.rb b/gems/kettle-jem/lib/kettle/jem.rb
index f98085488..e3260962e 100644
--- a/gems/kettle-jem/lib/kettle/jem.rb
+++ b/gems/kettle-jem/lib/kettle/jem.rb
@@ -6063,7 +6063,7 @@ def transfer_changelog_context(project_root, env: ENV)
"feature.appraisals" => File.file?(File.join(project_root, "Appraisals")),
"feature.rubyforum" => !rubyforum_facts(config, env, package_name: transfer_changelog_package_name(project_root)).empty?,
"feature.rubyforum_project_tag" => !normalize_rubyforum_tag(project_tag).empty?,
- "feature.corporate_sponsors" => sponsors.any?,
+ "feature.corporate_sponsors" => sponsors.any? { |sponsor| readme_corporate_sponsor_active?(sponsor, Date.today) || readme_corporate_sponsor_past?(sponsor, Date.today) },
"feature.organization_logo" => readme_top_logo_options(config).any? || readme_h2_synopsis_logo_options(config).any?,
"feature.structuredmerge_driver" => config.fetch("git_drivers", "semantic-diff").to_s == "semantic-diff",
"feature.dedicated_version_gem" => version_gem_mode == "dedicated" || File.file?(File.join(project_root, "lib", entrypoint, "version_gem.rb")),
@@ -17882,10 +17882,39 @@ def readme_logo_facts(config, package_name:, github_org:, repository: {})
def readme_corporate_sponsors_facts(config, env)
sponsors = readme_corporate_sponsors(config, env)
+ today = Date.today
+ active = sponsors.select { |sponsor| readme_corporate_sponsor_active?(sponsor, today) }.map do |sponsor|
+ next sponsor unless sponsor[:members]
+
+ sponsor.merge(members: sponsor[:members].select { |member| readme_corporate_sponsor_active?(member, today) })
+ end
+ past = sponsors.select { |sponsor| readme_corporate_sponsor_past?(sponsor, today) }
+ past_links = past.map do |sponsor|
+ link = "[#{sponsor.fetch(:name)}](#{sponsor.fetch(:url)})"
+ members = Array(sponsor[:members]).select { |member| !member[:since] || member[:since] <= today }
+ unless members.empty?
+ links = members.map { |member| "[#{member.fetch(:name)}](#{member.fetch(:url)})" }.join(", ")
+ link = "#{link} (backed by #{links})"
+ end
+ link
+ end
+ sponsors.each do |sponsor|
+ next unless readme_corporate_sponsor_active?(sponsor, today)
+
+ members = Array(sponsor[:members]).select { |member| readme_corporate_sponsor_past?(member, today) }
+ next if members.empty?
+
+ links = members.map { |member| "[#{member.fetch(:name)}](#{member.fetch(:url)})" }.join(", ")
+ past_links << "#{links} (formerly backing [#{sponsor.fetch(:name)}](#{sponsor.fetch(:url)}))"
+ end
+ detail = readme_corporate_sponsors_detail(active)
+ past_detail = past_links.empty? ? "" : "Past sponsors: #{past_links.join(', ')}"
compact_hash(
- entries: sponsors,
- row: readme_corporate_sponsors_row(sponsors),
- detail: readme_corporate_sponsors_detail(sponsors)
+ entries: active,
+ past_entries: past,
+ row: readme_corporate_sponsors_row(active),
+ detail: [detail, past_detail].reject(&:empty?).join("\n\n"),
+ past_detail: past_detail
)
end
@@ -17895,15 +17924,11 @@ def readme_corporate_sponsors(config, env)
readme_config["corporate_sponsors"] || readme_config["sponsors"]
)
inherited = normalize_readme_corporate_sponsors_json(env["KETTLE_JEM_CORPORATE_SPONSORS_JSON"])
- sponsors = deduplicate_readme_corporate_sponsors(configured + inherited)
- today = Date.today
- sponsors
- .select { |sponsor| readme_corporate_sponsor_active?(sponsor, today) }
- .map do |sponsor|
- next sponsor unless sponsor[:members]
+ deduplicate_readme_corporate_sponsors(configured + inherited)
+ end
- sponsor.merge(members: sponsor[:members].select { |member| readme_corporate_sponsor_active?(member, today) })
- end
+ def readme_corporate_sponsor_past?(sponsor, today)
+ (!sponsor[:since] || sponsor[:since] <= today) && sponsor[:until] && sponsor[:until] < today
end
def readme_corporate_sponsor_active?(sponsor, today)
diff --git a/gems/kettle-jem/spec/integration/config_metadata_template_spec.rb b/gems/kettle-jem/spec/integration/config_metadata_template_spec.rb
index f1dc701b7..df161cf04 100644
--- a/gems/kettle-jem/spec/integration/config_metadata_template_spec.rb
+++ b/gems/kettle-jem/spec/integration/config_metadata_template_spec.rb
@@ -1286,7 +1286,7 @@
end
end
- it "filters corporate sponsors by their since/until window" do
+ it "renders expired corporate sponsors separately and hides future sponsors" do
tmp_root = File.expand_path("../tmp", __dir__)
FileUtils.mkdir_p(tmp_root)
Dir.mktmpdir("kettle-jem-readme-sponsor-window-slice", tmp_root) do |root|
@@ -1330,6 +1330,7 @@
{KJ|README:CORPORATE_SPONSORS}
## 🦷 FLOSS Funding
+ {KJ|README:CORPORATE_SPONSORS_DETAIL}
MARKDOWN
})
@@ -1341,11 +1342,30 @@
expect(final_content).to include("Corporate sponsor:")
expect(final_content).to include(%(
"Former Fund", "url" => "https://former.example", "img_src" => "https://former.example/logo.svg", "until" => yesterday,
+ "members" => [
+ {"name" => "Former Member", "url" => "https://member.example", "until" => yesterday},
+ {"name" => "Future Member", "url" => "https://future.example", "since" => tomorrow}
+ ]
+ }]
+ facts = described_class.send(:readme_corporate_sponsors_facts, {}, {"KETTLE_JEM_CORPORATE_SPONSORS_JSON" => JSON.generate(inherited)})
+
+ expect(facts[:row].to_s).to be_empty
+ expect(facts[:detail]).to include("Past sponsors: [Former Fund](https://former.example) (backed by [Former Member](https://member.example))")
+ expect(facts[:detail]).not_to include("Future Member")
+ expect(facts[:past_entries].size).to eq(1)
+ end
+
it "rejects corporate sponsor entries with invalid since/until dates" do
expect {
described_class.send(
@@ -1410,7 +1430,7 @@
expect(final_content).to include(
%(-
[Umbrella Fund](https://umbrella.example) — backed by [Member One](https://one.example), [Member Two](https://two.example))
)
- expect(final_content).not_to include("Lapsed Member")
+ expect(final_content).to include("Past sponsors: [Lapsed Member](https://lapsed.example) (formerly backing [Umbrella Fund](https://umbrella.example))")
expect(template_report.dig(:metadata, :template_tokens)).to include(
"KJ|README:CORPORATE_SPONSORS_DETAIL" => a_string_including("backed by")
)