From de58513d5fb525a6a9d76bd427db422071e9cee5 Mon Sep 17 00:00:00 2001 From: "Ben Sheldon [he/him]" Date: Mon, 13 Jul 2026 20:09:51 -0700 Subject: [PATCH 1/2] Split CityCamp city page events into upcoming and past Adds separate "Upcoming events" and "Past events" sections to city pages instead of one combined list, computed via a Jekyll pre_render hook that partitions each city's events against the current date. Adds Timecop as a test dependency and a spec that freezes the date to verify the split, boundary behavior, and sort order. --- Gemfile | 1 + Gemfile.lock | 2 + _layouts/citycamp-city.html | 35 +++++++++++-- _plugins/citycamp_latest_event.rb | 9 ++-- spec/citycamp_events_split_spec.rb | 80 ++++++++++++++++++++++++++++++ 5 files changed, 120 insertions(+), 7 deletions(-) create mode 100644 spec/citycamp_events_split_spec.rb diff --git a/Gemfile b/Gemfile index 4e7367c..eab84ed 100644 --- a/Gemfile +++ b/Gemfile @@ -6,4 +6,5 @@ gem "jekyll-seo-tag" group :test do gem "rspec" + gem "timecop" end diff --git a/Gemfile.lock b/Gemfile.lock index 5f43e6f..cf937f9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -98,6 +98,7 @@ GEM google-protobuf (~> 4.31) terminal-table (3.0.2) unicode-display_width (>= 1.1.1, < 3) + timecop (0.9.11) unicode-display_width (2.6.0) webrick (1.9.2) @@ -111,6 +112,7 @@ DEPENDENCIES jekyll jekyll-seo-tag rspec + timecop RUBY VERSION ruby 4.0.2 diff --git a/_layouts/citycamp-city.html b/_layouts/citycamp-city.html index fd47e19..16be3c2 100644 --- a/_layouts/citycamp-city.html +++ b/_layouts/citycamp-city.html @@ -13,12 +13,39 @@

{{ page.city }}

← All CityCamp cities

- {% if page.events.size > 0 %} + {% if page.upcoming_events.size > 0 %} - {% assign sorted_events = page.events | sort: "date" | reverse %} - {% for event in sorted_events %} + {% for event in page.upcoming_events %} +
+
+
{{ event.date | date: "%B %-d, %Y" }}
+
{{ event.name }}
+ {% if event.venue %} +
{{ event.venue }}{% if event.address %} — {{ event.address }}{% endif %}
+ {% endif %} + {% if event.organizer %} +
Organized by {% if event.organizer_website %}{{ event.organizer }}{% else %}{{ event.organizer }}{% endif %}
+ {% endif %} + {% if event.website %} + + {% endif %} + {% if event.about %} +
{{ event.about | markdownify }}
+ {% endif %} +
+
+ {% endfor %} + {% endif %} + + {% if page.past_events.size > 0 %} + + {% for event in page.past_events %}
{{ event.date | date: "%B %-d, %Y" }}
diff --git a/_plugins/citycamp_latest_event.rb b/_plugins/citycamp_latest_event.rb index 6f30dba..b3422d2 100644 --- a/_plugins/citycamp_latest_event.rb +++ b/_plugins/citycamp_latest_event.rb @@ -15,10 +15,13 @@ past_events = [] site.collections["citycamp"]&.docs&.each do |doc| - (doc.data["events"] || []).each do |event| + events = doc.data["events"] || [] + upcoming, past = events.partition { |e| e["date"] && e["date"].strftime("%Y-%m-%d") >= today_str } + doc.data["upcoming_events"] = upcoming.sort_by { |e| e["date"].strftime("%Y-%m-%d") } + doc.data["past_events"] = past.sort_by { |e| e["date"].strftime("%Y-%m-%d") }.reverse + + past.each do |event| next unless event["date"] - date_str = event["date"].strftime("%Y-%m-%d") - next if date_str >= today_str past_events << { "city" => doc.data["city"], diff --git a/spec/citycamp_events_split_spec.rb b/spec/citycamp_events_split_spec.rb new file mode 100644 index 0000000..4c13ad8 --- /dev/null +++ b/spec/citycamp_events_split_spec.rb @@ -0,0 +1,80 @@ +require "jekyll" +require "timecop" +require "tmpdir" +require "fileutils" + +RSpec.describe "citycamp upcoming/past events split" do + Jekyll.logger.log_level = :error + + def build_site(today:) + source = Dir.mktmpdir + FileUtils.mkdir_p(File.join(source, "_citycamp")) + FileUtils.mkdir_p(File.join(source, "_layouts")) + FileUtils.mkdir_p(File.join(source, "_plugins")) + + File.write(File.join(source, "_layouts", "citycamp-city.html"), "---\n---\n{{ page.city }}") + FileUtils.cp( + File.join(__dir__, "..", "_plugins", "citycamp_latest_event.rb"), + File.join(source, "_plugins", "citycamp_latest_event.rb") + ) + FileUtils.cp( + File.join(__dir__, "..", "_plugins", "current_date.rb"), + File.join(source, "_plugins", "current_date.rb") + ) + + File.write(File.join(source, "_citycamp", "testville.md"), <<~MARKDOWN) + --- + layout: citycamp-city + city: "Testville" + country: "United States" + latitude: 1.0 + longitude: 1.0 + events: + - name: "Old Event" + date: 2020-01-01 + - name: "Today Event" + date: 2024-06-15 + - name: "Future Event" + date: 2099-01-01 + --- + MARKDOWN + + config = Jekyll.configuration( + "source" => source, + "destination" => File.join(source, "_site"), + "collections" => { "citycamp" => { "output" => true, "permalink" => "/citycamp/:name" } } + ) + + site = Timecop.freeze(today) do + site = Jekyll::Site.new(config) + site.read + site.render + site + end + + site.collections["citycamp"].docs.find { |doc| doc.data["city"] == "Testville" } + ensure + FileUtils.remove_entry(source) if source + end + + it "splits events into upcoming and past relative to the current date" do + doc = build_site(today: Date.new(2024, 6, 20)) + + expect(doc.data["upcoming_events"].map { |e| e["name"] }).to eq(["Future Event"]) + expect(doc.data["past_events"].map { |e| e["name"] }).to eq(["Today Event", "Old Event"]) + end + + it "treats an event dated today as upcoming" do + doc = build_site(today: Date.new(2024, 6, 15)) + + expect(doc.data["upcoming_events"].map { |e| e["name"] }).to eq(["Today Event", "Future Event"]) + expect(doc.data["past_events"].map { |e| e["name"] }).to eq(["Old Event"]) + end + + it "sorts upcoming events soonest-first and past events most-recent-first" do + doc = build_site(today: Date.new(2019, 1, 1)) + + expect(doc.data["upcoming_events"].map { |e| e["name"] }).to eq(["Old Event", "Today Event", "Future Event"]) + expect(doc.data["past_events"]).to eq([]) + end +end From 60a98649f6f55547cc30cb8c3415ffd3790e23e3 Mon Sep 17 00:00:00 2001 From: "Ben Sheldon [he/him]" Date: Fri, 17 Jul 2026 13:28:46 -0700 Subject: [PATCH 2/2] Add arm64-darwin-25 platform to Gemfile.lock --- Gemfile.lock | 1 + 1 file changed, 1 insertion(+) diff --git a/Gemfile.lock b/Gemfile.lock index 22249a3..c91dfe2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -142,6 +142,7 @@ GEM PLATFORMS arm64-darwin-21 arm64-darwin-22 + arm64-darwin-25 x86_64-linux DEPENDENCIES