From c9401e45433ea45b46f9a8faf1e7e537e4683244 Mon Sep 17 00:00:00 2001 From: erdgeist Date: Fri, 10 Jul 2026 18:07:15 +0200 Subject: Fix rrule/url column overflow on events#index Long RRULEs previously overflowed their column with no wrap point; now escaped and rendered with a after each semicolon, so a long rule wraps at a clause boundary instead of running off the table. Deliberately not truncated -- a cut-off RRULE's trailing clause (BYDAY, BYMONTH, etc.) is usually the most specific part. The url column is now a real link, truncated with an ellipsis at a fixed width -- deliberately no tooltip, since hovering a real link already shows the full address in the browser's own status bar. rrule_with_break_opportunities splits on the raw string's own semicolons before escaping each piece, not after -- escaping first and searching the result for semicolons also matches the ones inside </> entities, corrupting anything containing a literal < or >. --- app/helpers/events_helper.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'app/helpers') diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb index 8a9a878..5e84f53 100644 --- a/app/helpers/events_helper.rb +++ b/app/helpers/events_helper.rb @@ -1,2 +1,13 @@ +require 'cgi' + module EventsHelper + # Insert a zero-width break opportunity after each semicolon, so a long + # RRULE can wrap at a clause boundary instead of overflowing its column. + # Deliberately , not ellipsis -- unlike a URL, an RRULE's trailing + # characters (BYDAY, BYMONTH, etc.) are usually the most specific part, + # and truncating them would hide exactly the wrong end of the string. + def rrule_with_break_opportunities(rrule) + return "" if rrule.blank? + raw(rrule.split(';', -1).map { |part| CGI.escapeHTML(part) }.join(';')) + end end -- cgit v1.3