Skip to content

Commit 631889b

Browse files
String#split and better ics
1 parent c6dbba0 commit 631889b

3 files changed

Lines changed: 80 additions & 6 deletions

File tree

lib/code/object/ics.rb

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,14 @@ def self.serialize_event(event)
4646
next unless event.respond_to?(attribute)
4747

4848
serialized = serialize_value(event.public_send(attribute))
49-
serialized = serialized.flatten(1) if attribute == :categories && serialized.is_a?(::Array)
49+
serialized =
50+
if attribute == :categories && serialized.is_a?(::Array)
51+
serialized.flatten(1)
52+
elsif scalar_event_attribute?(attribute) && serialized.is_a?(::Array)
53+
serialized.join(",")
54+
else
55+
serialized
56+
end
5057
result[attribute] = serialized unless serialized.nil?
5158
end.merge(
5259
timestamp: serialize_value(event.dtstamp),
@@ -60,7 +67,9 @@ def self.serialize_value(value)
6067
case value
6168
when nil
6269
nil
63-
when ::String, ::Symbol, ::Integer, ::Float, ::BigDecimal, true, false
70+
when ::String
71+
normalize_string(value)
72+
when ::Symbol, ::Integer, ::Float, ::BigDecimal, true, false
6473
value
6574
when ::Array
6675
value.map { |item| serialize_value(item) }
@@ -73,13 +82,24 @@ def self.serialize_value(value)
7382
if value.respond_to?(:value)
7483
serialize_value(value.value)
7584
elsif value.respond_to?(:to_ical)
76-
value.to_ical
85+
normalize_string(value.to_ical)
7786
else
78-
value.to_s
87+
normalize_string(value.to_s)
7988
end
8089
end
8190
end
8291

92+
def self.scalar_event_attribute?(attribute)
93+
!%i[categories attendees geo].include?(attribute)
94+
end
95+
96+
def self.normalize_string(value)
97+
value
98+
.dup
99+
.force_encoding(::Encoding::UTF_8)
100+
.encode(::Encoding::UTF_8, invalid: :replace, undef: :replace)
101+
end
102+
83103
def self.serialize_date_like(value)
84104
case value
85105
when ::Time, ::Date, ::ActiveSupport::TimeWithZone

lib/code/object/string.rb

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ def call(**args)
7474
sig(args)
7575
code_strip
7676
when "split"
77-
sig(args) { String }
77+
sig(args) { String.maybe }
7878
code_split(code_value)
7979
else
8080
super
@@ -162,7 +162,11 @@ def code_strip
162162
def code_split(value)
163163
code_value = value.to_code
164164

165-
List.new(raw.split(code_value.to_s))
165+
if code_value.nothing?
166+
List.new(raw.split)
167+
else
168+
List.new(raw.split(code_value.to_s))
169+
end
166170
end
167171

168172
def present?

spec/code/object/ics_spec.rb

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# frozen_string_literal: true
2+
3+
require "spec_helper"
4+
5+
RSpec.describe Code::Object::Ics do
6+
it "normalizes binary event strings before json serialization" do
7+
source =
8+
<<~ICS
9+
BEGIN:VCALENDAR
10+
VERSION:2.0
11+
PRODID:-//code-ruby//EN
12+
BEGIN:VEVENT
13+
UID:event-1
14+
DTSTART:20260327T120000Z
15+
DTEND:20260327T133000Z
16+
SUMMARY:Joséphine
17+
DESCRIPTION:https://luma.com/opv3owre
18+
END:VEVENT
19+
END:VCALENDAR
20+
ICS
21+
22+
events = described_class.code_parse(Code::Object::String.new(source.b))
23+
24+
expect { expect(events.to_json).to include("Joséphine") }.not_to output.to_stderr
25+
end
26+
27+
it "serializes comma-separated descriptions as strings" do
28+
source =
29+
<<~ICS
30+
BEGIN:VCALENDAR
31+
VERSION:2.0
32+
PRODID:-//code-ruby//EN
33+
BEGIN:VEVENT
34+
UID:event-2
35+
DTSTART:20260401T170000Z
36+
DTEND:20260401T190000Z
37+
SUMMARY:Le Cirque du Donut
38+
DESCRIPTION:Bonjour Paris !\\nLe 1er avril, Kate Raworth vous donne rendez-vous, pour une soirée inédite.
39+
END:VEVENT
40+
END:VCALENDAR
41+
ICS
42+
43+
events = described_class.code_parse(Code::Object::String.new(source))
44+
description = events.raw.first.code_get("description").raw
45+
46+
expect(description).to be_a(String)
47+
expect(description).to include("Le 1er avril, Kate Raworth")
48+
expect(description).to include("rendez-vous, pour")
49+
end
50+
end

0 commit comments

Comments
 (0)