icalendar 2.12.2 → 2.12.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/main.yml +2 -1
- data/CHANGELOG.md +7 -0
- data/benchmarks/memory_per_event_ical.rb +27 -0
- data/icalendar.gemspec +1 -1
- data/lib/icalendar/has_properties.rb +5 -7
- data/lib/icalendar/values/text.rb +4 -4
- data/lib/icalendar/version.rb +1 -1
- data/spec/values/text_spec.rb +33 -0
- metadata +7 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6a9a656fd81bc80eb43cf61e14d95a3b582f66bae80417da16a7e5d621910581
|
|
4
|
+
data.tar.gz: df88f0f0a1619dbdcba157316aba616019d146fe74e46aba6d7603dc30b40c26
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a0ad4eb07a4123fba9260916530046bd008a9f076a26a276f09a31cce789aa0801a38fff3d553b7b11fcb3de072c72aff758921ad601d7e643b808495425b0df
|
|
7
|
+
data.tar.gz: 06bab135b068613fdf8c4d10554a327a35b2072eb5e37c5e7bc7509b8e62b05e596153cfa8985065b2739e99eb7bc90dd8282c173972929900aa763d58e218b1
|
data/.github/workflows/main.yml
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
## Unreleased
|
|
2
2
|
|
|
3
|
+
## 2.12.4 - 2026-07-31
|
|
4
|
+
- TEXT unescape fix - Vincent Gao
|
|
5
|
+
|
|
6
|
+
## 2.12.3 - 2026-05-13
|
|
7
|
+
- Memory use optimization - Jared Menard
|
|
8
|
+
- Run CI against Ruby 4.0 - Artem Chubchenko
|
|
9
|
+
|
|
3
10
|
## 2.12.2 - 2026-03-21
|
|
4
11
|
- Fix a potential property injection issue through escaping control characters in URI values - Wes Ring
|
|
5
12
|
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require 'memory_profiler'
|
|
2
|
+
require 'icalendar'
|
|
3
|
+
|
|
4
|
+
# Profiles the per-event calendar wrapping pattern:
|
|
5
|
+
# cal = Icalendar::Calendar.new
|
|
6
|
+
# ical_event.parent&.timezones&.each { |tz| cal.add_timezone tz }
|
|
7
|
+
# cal.add_event(ical_event)
|
|
8
|
+
# cal.to_ical
|
|
9
|
+
|
|
10
|
+
cal_string = File.read(File.join(__dir__, '..', 'spec/fixtures/timezone.ics'))
|
|
11
|
+
source_calendar = Icalendar::Calendar.parse(cal_string).first
|
|
12
|
+
events = source_calendar.events
|
|
13
|
+
|
|
14
|
+
ITERATIONS = 1000
|
|
15
|
+
|
|
16
|
+
report = MemoryProfiler.report do
|
|
17
|
+
ITERATIONS.times do
|
|
18
|
+
events.each do |ical_event|
|
|
19
|
+
cal = Icalendar::Calendar.new
|
|
20
|
+
ical_event.parent&.timezones&.each { |tz| cal.add_timezone tz }
|
|
21
|
+
cal.add_event(ical_event)
|
|
22
|
+
cal.to_ical
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
report.pretty_print(scale_bytes: true, top: 20)
|
data/icalendar.gemspec
CHANGED
|
@@ -37,7 +37,7 @@ ActiveSupport is required for TimeWithZone support, but not required for general
|
|
|
37
37
|
s.add_dependency 'ostruct'
|
|
38
38
|
|
|
39
39
|
s.add_development_dependency 'rake', '~> 13.0'
|
|
40
|
-
s.add_development_dependency 'bundler'
|
|
40
|
+
s.add_development_dependency 'bundler'
|
|
41
41
|
|
|
42
42
|
# test with all groups of tzinfo dependencies
|
|
43
43
|
# tzinfo 2.x
|
|
@@ -172,13 +172,11 @@ module Icalendar
|
|
|
172
172
|
private
|
|
173
173
|
|
|
174
174
|
def map_property_value(value, klass, multi_valued, new_property)
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
if value.
|
|
180
|
-
value
|
|
181
|
-
elsif value.is_a? ::Array
|
|
175
|
+
return value if value.nil? || value.is_a?(Icalendar::Value)
|
|
176
|
+
|
|
177
|
+
params = new_property ? {'VALUE': klass.value_type} : {}
|
|
178
|
+
|
|
179
|
+
if value.is_a? ::Array
|
|
182
180
|
Icalendar::Values::Helpers::Array.new value, klass, params, {delimiter: (multi_valued ? ',' : ';')}
|
|
183
181
|
else
|
|
184
182
|
klass.new value, params
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
module Icalendar
|
|
4
4
|
module Values
|
|
5
5
|
class Text < Value
|
|
6
|
+
UNESCAPE_GSUB_REGEX = /\\([\\,;nN])/.freeze
|
|
7
|
+
|
|
6
8
|
def initialize(value, *args)
|
|
7
|
-
|
|
8
|
-
value.gsub
|
|
9
|
-
value.gsub!('\;', ';')
|
|
10
|
-
value.gsub!('\\\\') { '\\' }
|
|
9
|
+
# One left-to-right pass keeps unescape the exact inverse of value_ical; \n and \N are newline.
|
|
10
|
+
value = value.gsub(UNESCAPE_GSUB_REGEX) { |_| %w[n N].include?($1) ? "\n" : $1 }
|
|
11
11
|
super value, *args
|
|
12
12
|
end
|
|
13
13
|
|
data/lib/icalendar/version.rb
CHANGED
data/spec/values/text_spec.rb
CHANGED
|
@@ -30,6 +30,39 @@ describe Icalendar::Values::Text do
|
|
|
30
30
|
end
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
+
describe 'unescape is the exact inverse of value_ical' do
|
|
34
|
+
bs = "\\"
|
|
35
|
+
{
|
|
36
|
+
'a literal backslash before n (windows path)' => ["C:#{bs}#{bs}next", "C:#{bs}next"],
|
|
37
|
+
'a UNC path with several backslashes' => ["#{bs * 4}srv#{bs * 2}sh", "#{bs * 2}srv#{bs}sh"],
|
|
38
|
+
'an escaped backslash alone' => ["a#{bs}#{bs}b", "a#{bs}b"],
|
|
39
|
+
'an escaped comma' => ["a#{bs},b", 'a,b'],
|
|
40
|
+
'an escaped semicolon' => ["a#{bs};b", 'a;b'],
|
|
41
|
+
'a lowercase newline escape' => ["a#{bs}nb", "a\nb"],
|
|
42
|
+
'plain text without backslashes' => ['plain summary text', 'plain summary text'],
|
|
43
|
+
}.each do |desc, (onwire, content)|
|
|
44
|
+
context "given #{desc}" do
|
|
45
|
+
subject { described_class.new onwire.dup }
|
|
46
|
+
|
|
47
|
+
it 'decodes to the original content' do
|
|
48
|
+
expect(subject.value).to eq content
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it 'round-trips back to the on-wire form' do
|
|
52
|
+
expect(subject.value_ical).to eq onwire
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it 'decodes a capital-N newline escape (RFC 5545 3.3.11)' do
|
|
58
|
+
expect(described_class.new("a#{bs}Nb").value).to eq "a\nb"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it 'leaves a backslash before a non-escape char untouched' do
|
|
62
|
+
expect(described_class.new("a#{bs}:b").value).to eq "a#{bs}:b"
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
33
66
|
describe 'escapes parameter text properly' do
|
|
34
67
|
subject { described_class.new escaped, {'param' => param_value} }
|
|
35
68
|
context 'single value, no special characters' do
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: icalendar
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.12.
|
|
4
|
+
version: 2.12.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ryan Ahearn
|
|
@@ -83,16 +83,16 @@ dependencies:
|
|
|
83
83
|
name: bundler
|
|
84
84
|
requirement: !ruby/object:Gem::Requirement
|
|
85
85
|
requirements:
|
|
86
|
-
- - "
|
|
86
|
+
- - ">="
|
|
87
87
|
- !ruby/object:Gem::Version
|
|
88
|
-
version: '
|
|
88
|
+
version: '0'
|
|
89
89
|
type: :development
|
|
90
90
|
prerelease: false
|
|
91
91
|
version_requirements: !ruby/object:Gem::Requirement
|
|
92
92
|
requirements:
|
|
93
|
-
- - "
|
|
93
|
+
- - ">="
|
|
94
94
|
- !ruby/object:Gem::Version
|
|
95
|
-
version: '
|
|
95
|
+
version: '0'
|
|
96
96
|
- !ruby/object:Gem::Dependency
|
|
97
97
|
name: activesupport
|
|
98
98
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -209,6 +209,7 @@ files:
|
|
|
209
209
|
- LICENSE
|
|
210
210
|
- README.md
|
|
211
211
|
- Rakefile
|
|
212
|
+
- benchmarks/memory_per_event_ical.rb
|
|
212
213
|
- icalendar.gemspec
|
|
213
214
|
- lib/icalendar.rb
|
|
214
215
|
- lib/icalendar/alarm.rb
|
|
@@ -319,7 +320,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
319
320
|
- !ruby/object:Gem::Version
|
|
320
321
|
version: '0'
|
|
321
322
|
requirements: []
|
|
322
|
-
rubygems_version:
|
|
323
|
+
rubygems_version: 4.0.6
|
|
323
324
|
specification_version: 4
|
|
324
325
|
summary: A ruby implementation of the iCalendar specification (RFC-5545).
|
|
325
326
|
test_files:
|