Skip to content

Commit 130f505

Browse files
author
Jared Turner
committed
Fix ical formatting and handle multi-line descriptions
1 parent df36be4 commit 130f505

File tree

5 files changed

+82
-40
lines changed

5 files changed

+82
-40
lines changed

Gemfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
PATH
22
remote: .
33
specs:
4-
add_to_calendar (0.2.1)
4+
add_to_calendar (0.2.2)
55
tzinfo (>= 1.1, < 3)
66
tzinfo-data (~> 1.2020)
77

lib/add_to_calendar.rb

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,10 @@ def ical_url
107107
end
108108
params[:SUMMARY] = url_encode(title)
109109
params[:URL] = url_encode(url) if url
110-
params[:DESCRIPTION] = url_encode(description) if description
110+
params[:DESCRIPTION] = url_encode_ical_description(description) if description
111111
if add_url_to_description && url
112112
if params[:DESCRIPTION]
113-
params[:DESCRIPTION] << "\n\n#{url_encode(url)}"
113+
params[:DESCRIPTION] << "\\n\\n#{url_encode(url)}"
114114
else
115115
params[:DESCRIPTION] = url_encode(url)
116116
end
@@ -121,7 +121,7 @@ def ical_url
121121

122122
new_line = "%0A"
123123
params.each do |key, value|
124-
calendar_url << "#{new_line}#{key}=#{value}"
124+
calendar_url << "#{new_line}#{key}:#{value}"
125125
end
126126

127127
calendar_url << "%0AEND:VEVENT%0AEND:VCALENDAR"
@@ -238,5 +238,15 @@ def seconds_to_hours_minutes(sec)
238238
def newlines_to_html_br(string)
239239
string.gsub(/(?:\n\r?|\r\n?)/, '<br>')
240240
end
241+
242+
def url_encode_ical_description(description)
243+
description.split("\n").map { |e|
244+
if e == "\n"
245+
"\\n"
246+
else
247+
url_encode(e) if e != "\n"
248+
end
249+
}.join("\\n")
250+
end
241251
end
242252
end

lib/add_to_calendar/version.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
module AddToCalendar
2-
VERSION = "0.2.1"
2+
VERSION = "0.2.2"
33
end

test/add_to_calendar_test.rb

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,13 +157,36 @@ def test_newlines_convert_to_html_br
157157
timezone: @timezone
158158
)
159159
string_without_newlines = cal.send(:newlines_to_html_br, "string without newlines")
160-
assert string_without_newlines = "string without newlines"
160+
assert string_without_newlines == "string without newlines"
161161

162162
string_with_newline = cal.send(:newlines_to_html_br, "string with\nnewline")
163-
assert string_with_newline = "string with<br>newline"
163+
assert string_with_newline == "string with<br>newline"
164164

165165
string_with_newlines = cal.send(:newlines_to_html_br, "string\nwith\n\nnewlines")
166-
assert string_with_newline = "string<br>with<br><br>newline"
166+
assert string_with_newlines == "string<br>with<br><br>newlines"
167+
end
168+
169+
def test_ical_description_url_encoded_with_newlines
170+
# final *.ics file must include `\n`
171+
# which means the string output must be `\\n` (not url encoded)
172+
# this method should:
173+
# url encode all characters except newlines \n
174+
# update all newlines \n to \\n
175+
cal = AddToCalendar::URLs.new(
176+
start_datetime: Time.new(@next_month_year,@next_month_month,@next_month_day,13,30,00,0),
177+
end_datetime: Time.new(@next_month_year,@next_month_month,@next_month_day,17,00,00,0),
178+
title: @title,
179+
timezone: @timezone
180+
)
181+
string_without_newlines = cal.send(:url_encode_ical_description, "string without newlines")
182+
assert string_without_newlines == "string%20without%20newlines"
183+
184+
string_with_newline = cal.send(:url_encode_ical_description, "string with\nnewline")
185+
assert string_with_newline == "string%20with\\nnewline"
186+
187+
string_with_newlines = cal.send(:url_encode_ical_description, "string\nwith\n\nnewlines")
188+
assert string_with_newlines == "string\\nwith\\n\\nnewlines"
189+
167190
end
168191

169192
end

test/urls/ical_url_test.rb

Lines changed: 41 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -17,28 +17,28 @@ def setup
1717
@description = "Come join us for lots of fun & cake!"
1818

1919
@url_with_defaults_required = "data:text/calendar;charset=utf8,BEGIN:VCALENDAR%0AVERSION:2.0%0ABEGIN:VEVENT" +
20-
"%0ADTSTART=#{@next_month_year}#{@next_month_month}#{@next_month_day}T123000Z" +
21-
"%0ADTEND=#{@next_month_year}#{@next_month_month}#{@next_month_day}T133000Z" +
22-
"%0ASUMMARY=Holly%27s%208th%20Birthday%21"
20+
"%0ADTSTART:#{@next_month_year}#{@next_month_month}#{@next_month_day}T123000Z" +
21+
"%0ADTEND:#{@next_month_year}#{@next_month_month}#{@next_month_day}T133000Z" +
22+
"%0ASUMMARY:Holly%27s%208th%20Birthday%21"
2323
@url_end = "%0AEND:VEVENT%0AEND:VCALENDAR"
2424

25-
# "%0AUID=-20200610T123000Z-Holly%27s%208th%20Birthday%21%0AEND:VEVENT%0AEND:VCALENDAR"
25+
# "%0AUID:-20200610T123000Z-Holly%27s%208th%20Birthday%21%0AEND:VEVENT%0AEND:VCALENDAR"
2626
end
2727

2828
def test_with_only_required_attributes
2929
cal = AddToCalendar::URLs.new(start_datetime: Time.new(@next_month_year,@next_month_month,@next_month_day,13,30,00,0), title: @title, timezone: @timezone)
30-
uid = "%0AUID=-#{cal.send(:utc_datetime, cal.start_datetime)}-#{url_encode(cal.title)}"
30+
uid = "%0AUID:-#{cal.send(:utc_datetime, cal.start_datetime)}-#{url_encode(cal.title)}"
3131
assert cal.ical_url == @url_with_defaults_required + uid + @url_end
3232
end
3333

3434
def test_without_end_datetime
3535
# should set end as start + 1 hour
3636
cal = AddToCalendar::URLs.new(start_datetime: Time.new(@next_month_year,@next_month_month,@next_month_day,13,30,00,0), title: @title, timezone: @timezone)
37-
uid = "%0AUID=-#{cal.send(:utc_datetime, cal.start_datetime)}-#{url_encode(cal.title)}"
37+
uid = "%0AUID:-#{cal.send(:utc_datetime, cal.start_datetime)}-#{url_encode(cal.title)}"
3838
assert cal.ical_url == "data:text/calendar;charset=utf8,BEGIN:VCALENDAR%0AVERSION:2.0%0ABEGIN:VEVENT" +
39-
"%0ADTSTART=#{@next_month_year}#{@next_month_month}#{@next_month_day}T123000Z" +
40-
"%0ADTEND=#{@next_month_year}#{@next_month_month}#{@next_month_day}T133000Z" +
41-
"%0ASUMMARY=Holly%27s%208th%20Birthday%21" +
39+
"%0ADTSTART:#{@next_month_year}#{@next_month_month}#{@next_month_day}T123000Z" +
40+
"%0ADTEND:#{@next_month_year}#{@next_month_month}#{@next_month_day}T133000Z" +
41+
"%0ASUMMARY:Holly%27s%208th%20Birthday%21" +
4242
uid +
4343
@url_end
4444
end
@@ -50,11 +50,11 @@ def test_with_end_datetime
5050
title: @title,
5151
timezone: @timezone
5252
)
53-
uid = "%0AUID=-#{cal.send(:utc_datetime, cal.start_datetime)}-#{url_encode(cal.title)}"
53+
uid = "%0AUID:-#{cal.send(:utc_datetime, cal.start_datetime)}-#{url_encode(cal.title)}"
5454
assert cal.ical_url == "data:text/calendar;charset=utf8,BEGIN:VCALENDAR%0AVERSION:2.0%0ABEGIN:VEVENT" +
55-
"%0ADTSTART=#{@next_month_year}#{@next_month_month}#{@next_month_day}T123000Z" +
56-
"%0ADTEND=#{@next_month_year}#{@next_month_month}#{@next_month_day}T160000Z" +
57-
"%0ASUMMARY=Holly%27s%208th%20Birthday%21" +
55+
"%0ADTSTART:#{@next_month_year}#{@next_month_month}#{@next_month_day}T123000Z" +
56+
"%0ADTEND:#{@next_month_year}#{@next_month_month}#{@next_month_day}T160000Z" +
57+
"%0ASUMMARY:Holly%27s%208th%20Birthday%21" +
5858
uid +
5959
@url_end
6060
end
@@ -66,31 +66,39 @@ def test_with_end_datetime_after_midnight
6666
title: @title,
6767
timezone: @timezone
6868
)
69-
uid = "%0AUID=-#{cal.send(:utc_datetime, cal.start_datetime)}-#{url_encode(cal.title)}"
69+
uid = "%0AUID:-#{cal.send(:utc_datetime, cal.start_datetime)}-#{url_encode(cal.title)}"
7070
assert cal.ical_url == "data:text/calendar;charset=utf8,BEGIN:VCALENDAR%0AVERSION:2.0%0ABEGIN:VEVENT" +
71-
"%0ADTSTART=#{@next_month_year}#{@next_month_month}#{@next_month_day}T123000Z" +
72-
"%0ADTEND=#{@next_month_year}#{@next_month_month}#{@next_month_day.to_i+1}T160000Z" +
73-
"%0ASUMMARY=Holly%27s%208th%20Birthday%21" +
71+
"%0ADTSTART:#{@next_month_year}#{@next_month_month}#{@next_month_day}T123000Z" +
72+
"%0ADTEND:#{@next_month_year}#{@next_month_month}#{@next_month_day.to_i+1}T160000Z" +
73+
"%0ASUMMARY:Holly%27s%208th%20Birthday%21" +
7474
uid +
7575
@url_end
7676
end
7777

7878
def test_with_location
7979
cal = AddToCalendar::URLs.new(start_datetime: Time.new(@next_month_year,@next_month_month,@next_month_day,13,30,00,0), title: @title, timezone: @timezone, location: @location)
80-
uid = "%0AUID=-#{cal.send(:utc_datetime, cal.start_datetime)}-#{url_encode(cal.title)}"
81-
assert cal.ical_url == @url_with_defaults_required + "%0ALOCATION=Flat%204%2C%20The%20Edge%2C%2038%20Smith-Dorrien%20St%2C%20London%2C%20N1%207GU" + uid + @url_end
80+
uid = "%0AUID:-#{cal.send(:utc_datetime, cal.start_datetime)}-#{url_encode(cal.title)}"
81+
assert cal.ical_url == @url_with_defaults_required + "%0ALOCATION:Flat%204%2C%20The%20Edge%2C%2038%20Smith-Dorrien%20St%2C%20London%2C%20N1%207GU" + uid + @url_end
8282
end
8383

8484
def test_with_url_without_description
8585
cal = AddToCalendar::URLs.new(start_datetime: Time.new(@next_month_year,@next_month_month,@next_month_day,13,30,00,0), title: @title, timezone: @timezone, url: @url)
86-
uid = "%0AUID=-#{url_encode(cal.url)}"
87-
assert cal.ical_url == @url_with_defaults_required + "%0AURL=https%3A%2F%2Fwww.example.com%2Fevent-details%0ADESCRIPTION=https%3A%2F%2Fwww.example.com%2Fevent-details" + uid + @url_end
86+
uid = "%0AUID:-#{url_encode(cal.url)}"
87+
assert cal.ical_url == @url_with_defaults_required + "%0AURL:https%3A%2F%2Fwww.example.com%2Fevent-details%0ADESCRIPTION:https%3A%2F%2Fwww.example.com%2Fevent-details" + uid + @url_end
8888
end
8989

9090
def test_with_url_and_description
9191
cal = AddToCalendar::URLs.new(start_datetime: Time.new(@next_month_year,@next_month_month,@next_month_day,13,30,00,0), title: @title, timezone: @timezone, url: @url, description: @description)
92-
uid = "%0AUID=-#{url_encode(cal.url)}"
93-
assert cal.ical_url == @url_with_defaults_required + "%0AURL=https%3A%2F%2Fwww.example.com%2Fevent-details%0ADESCRIPTION=Come%20join%20us%20for%20lots%20of%20fun%20%26%20cake%21\n\nhttps%3A%2F%2Fwww.example.com%2Fevent-details" + uid + @url_end
92+
uid = "%0AUID:-#{url_encode(cal.url)}"
93+
assert cal.ical_url == @url_with_defaults_required + "%0AURL:https%3A%2F%2Fwww.example.com%2Fevent-details%0ADESCRIPTION:Come%20join%20us%20for%20lots%20of%20fun%20%26%20cake%21\\n\\nhttps%3A%2F%2Fwww.example.com%2Fevent-details" + uid + @url_end
94+
end
95+
96+
def test_description_with_newlines
97+
# final *.ics file must include `\n`
98+
# which means the string output must be `\\n`
99+
cal = AddToCalendar::URLs.new(start_datetime: Time.new(@next_month_year,@next_month_month,@next_month_day,13,30,00,0), title: @title, timezone: @timezone, description: "Come join us for lots of fun & cake!\n\nBring a towel!")
100+
uid = "%0AUID:-#{cal.send(:utc_datetime, cal.start_datetime)}-#{url_encode(cal.title)}"
101+
assert cal.ical_url == @url_with_defaults_required + "%0ADESCRIPTION:Come%20join%20us%20for%20lots%20of%20fun%20%26%20cake%21\\n\\nBring%20a%20towel%21" + uid + @url_end
94102
end
95103

96104
def test_add_url_to_description_false_without_url
@@ -100,7 +108,7 @@ def test_add_url_to_description_false_without_url
100108
timezone: @timezone,
101109
add_url_to_description: false,
102110
)
103-
uid = "%0AUID=-#{cal.send(:utc_datetime, cal.start_datetime)}-#{url_encode(cal.title)}"
111+
uid = "%0AUID:-#{cal.send(:utc_datetime, cal.start_datetime)}-#{url_encode(cal.title)}"
104112
assert cal.ical_url == @url_with_defaults_required + uid + @url_end
105113
end
106114

@@ -112,8 +120,8 @@ def test_add_url_to_description_false_with_url
112120
add_url_to_description: false,
113121
url: @url,
114122
)
115-
uid = "%0AUID=-#{url_encode(cal.url)}"
116-
assert cal.ical_url == @url_with_defaults_required + "%0AURL=https%3A%2F%2Fwww.example.com%2Fevent-details" + uid + @url_end
123+
uid = "%0AUID:-#{url_encode(cal.url)}"
124+
assert cal.ical_url == @url_with_defaults_required + "%0AURL:https%3A%2F%2Fwww.example.com%2Fevent-details" + uid + @url_end
117125
end
118126

119127
def test_with_all_attributes
@@ -126,13 +134,14 @@ def test_with_all_attributes
126134
location: @location,
127135
description: @description,
128136
)
129-
uid = "%0AUID=-#{url_encode(cal.url)}"
137+
uid = "%0AUID:-#{url_encode(cal.url)}"
130138
assert cal.ical_url == "data:text/calendar;charset=utf8,BEGIN:VCALENDAR%0AVERSION:2.0%0ABEGIN:VEVENT" +
131-
"%0ADTSTART=#{@next_month_year}#{@next_month_month}#{@next_month_day}T123000Z" +
132-
"%0ADTEND=#{@next_month_year}#{@next_month_month}#{@next_month_day}T160000Z" +
133-
"%0ASUMMARY=Holly%27s%208th%20Birthday%21" +
134-
"%0AURL=https%3A%2F%2Fwww.example.com%2Fevent-details%0ADESCRIPTION=Come%20join%20us%20for%20lots%20of%20fun%20%26%20cake%21\n\nhttps%3A%2F%2Fwww.example.com%2Fevent-details" +
135-
"%0ALOCATION=Flat%204%2C%20The%20Edge%2C%2038%20Smith-Dorrien%20St%2C%20London%2C%20N1%207GU" +
139+
"%0ADTSTART:#{@next_month_year}#{@next_month_month}#{@next_month_day}T123000Z" +
140+
"%0ADTEND:#{@next_month_year}#{@next_month_month}#{@next_month_day}T160000Z" +
141+
"%0ASUMMARY:Holly%27s%208th%20Birthday%21" +
142+
"%0AURL:https%3A%2F%2Fwww.example.com%2Fevent-details" +
143+
"%0ADESCRIPTION:Come%20join%20us%20for%20lots%20of%20fun%20%26%20cake%21\\n\\nhttps%3A%2F%2Fwww.example.com%2Fevent-details" +
144+
"%0ALOCATION:Flat%204%2C%20The%20Edge%2C%2038%20Smith-Dorrien%20St%2C%20London%2C%20N1%207GU" +
136145
uid +
137146
@url_end
138147
end

0 commit comments

Comments
 (0)