code-ruby 3.0.2 → 3.0.3
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/Gemfile.lock +8 -1
- data/VERSION +1 -1
- data/code-ruby.gemspec +1 -0
- data/lib/code/object/global.rb +3 -0
- data/lib/code/object/ics.rb +93 -0
- data/lib/code-ruby.rb +1 -0
- data/spec/code_spec.rb +48 -0
- metadata +16 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4adfeb34ead1c64815b7c1441fe958bdb800124060f85fe34e3e069d84471bf9
|
|
4
|
+
data.tar.gz: 47d16a2b78dfa78f09c3a85ceb96bec36462e5370c46c6da5bfa6cbeccb16704
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f3282f6775597df25231b0aef32f5d0a8a11d7cee0f33abdb0989c843fff87a16f908a01998c1269d81bebe507c5023cf56095a8037624be68066a6e82c15443
|
|
7
|
+
data.tar.gz: 49e847ebb8e89dad0b072b25e3116718d3cbb3de2c4b0252cb8e2d7ae0462e93992554dadbf1665f91cb821fd9fe05f0a1769b3a06ab8d1632d4d1a268b828bb
|
data/Gemfile.lock
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
code-ruby (3.0.
|
|
4
|
+
code-ruby (3.0.3)
|
|
5
5
|
activesupport
|
|
6
6
|
base64
|
|
7
7
|
bigdecimal
|
|
8
8
|
did-you-mean
|
|
9
9
|
dorian-arguments
|
|
10
|
+
icalendar
|
|
10
11
|
json
|
|
11
12
|
language-ruby
|
|
12
13
|
mail
|
|
@@ -95,6 +96,12 @@ GEM
|
|
|
95
96
|
strscan (>= 3.1.2)
|
|
96
97
|
i18n (1.14.8)
|
|
97
98
|
concurrent-ruby (~> 1.0)
|
|
99
|
+
icalendar (2.12.2)
|
|
100
|
+
base64
|
|
101
|
+
ice_cube (~> 0.16)
|
|
102
|
+
logger
|
|
103
|
+
ostruct
|
|
104
|
+
ice_cube (0.17.0)
|
|
98
105
|
json (2.18.1)
|
|
99
106
|
json-schema (6.1.0)
|
|
100
107
|
addressable (~> 2.8)
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
3.0.
|
|
1
|
+
3.0.3
|
data/code-ruby.gemspec
CHANGED
data/lib/code/object/global.rb
CHANGED
|
@@ -167,6 +167,9 @@ class Code
|
|
|
167
167
|
when "Json"
|
|
168
168
|
sig(args) { Object.repeat }
|
|
169
169
|
code_arguments.any? ? Json.new(*code_arguments.raw) : Class.new(Json)
|
|
170
|
+
when "Ics"
|
|
171
|
+
sig(args) { Object.repeat }
|
|
172
|
+
code_arguments.any? ? Ics.new(*code_arguments.raw) : Class.new(Ics)
|
|
170
173
|
when "evaluate"
|
|
171
174
|
sig(args) { Object }
|
|
172
175
|
Code.code_evaluate(code_value.code_to_string, **globals)
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class Code
|
|
4
|
+
class Object
|
|
5
|
+
class Ics < Object
|
|
6
|
+
EVENT_ATTRIBUTES = %i[
|
|
7
|
+
uid
|
|
8
|
+
summary
|
|
9
|
+
description
|
|
10
|
+
location
|
|
11
|
+
url
|
|
12
|
+
status
|
|
13
|
+
organizer
|
|
14
|
+
categories
|
|
15
|
+
attendees
|
|
16
|
+
geo
|
|
17
|
+
].freeze
|
|
18
|
+
|
|
19
|
+
def self.call(**args)
|
|
20
|
+
code_operator = args.fetch(:operator, nil).to_code
|
|
21
|
+
code_arguments = args.fetch(:arguments, []).to_code
|
|
22
|
+
code_value = code_arguments.code_first
|
|
23
|
+
|
|
24
|
+
case code_operator.to_s
|
|
25
|
+
when "parse"
|
|
26
|
+
sig(args) { String }
|
|
27
|
+
code_parse(code_value)
|
|
28
|
+
else
|
|
29
|
+
super
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def self.code_parse(value)
|
|
34
|
+
source = value.to_code.raw
|
|
35
|
+
calendars = ::Icalendar::Calendar.parse(source)
|
|
36
|
+
calendars
|
|
37
|
+
.flat_map(&:events)
|
|
38
|
+
.map { |event| serialize_event(event) }
|
|
39
|
+
.to_code
|
|
40
|
+
rescue StandardError
|
|
41
|
+
[].to_code
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def self.serialize_event(event)
|
|
45
|
+
EVENT_ATTRIBUTES.each_with_object({}) do |attribute, result|
|
|
46
|
+
next unless event.respond_to?(attribute)
|
|
47
|
+
|
|
48
|
+
serialized = serialize_value(event.public_send(attribute))
|
|
49
|
+
serialized = serialized.flatten(1) if attribute == :categories && serialized.is_a?(::Array)
|
|
50
|
+
result[attribute] = serialized unless serialized.nil?
|
|
51
|
+
end.merge(
|
|
52
|
+
timestamp: serialize_value(event.dtstamp),
|
|
53
|
+
starts_at: serialize_value(event.dtstart),
|
|
54
|
+
ends_at: serialize_value(event.dtend),
|
|
55
|
+
all_day: !!serialize_date_like(event.dtstart).is_a?(::Date)
|
|
56
|
+
).compact
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def self.serialize_value(value)
|
|
60
|
+
case value
|
|
61
|
+
when nil
|
|
62
|
+
nil
|
|
63
|
+
when ::String, ::Symbol, ::Integer, ::Float, ::BigDecimal, true, false
|
|
64
|
+
value
|
|
65
|
+
when ::Array
|
|
66
|
+
value.map { |item| serialize_value(item) }
|
|
67
|
+
when ::Hash
|
|
68
|
+
value.transform_values { |item| serialize_value(item) }
|
|
69
|
+
else
|
|
70
|
+
serialized_date = serialize_date_like(value)
|
|
71
|
+
return serialized_date unless serialized_date.nil?
|
|
72
|
+
|
|
73
|
+
if value.respond_to?(:value)
|
|
74
|
+
serialize_value(value.value)
|
|
75
|
+
elsif value.respond_to?(:to_ical)
|
|
76
|
+
value.to_ical
|
|
77
|
+
else
|
|
78
|
+
value.to_s
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def self.serialize_date_like(value)
|
|
84
|
+
case value
|
|
85
|
+
when ::Time, ::Date, ::ActiveSupport::TimeWithZone
|
|
86
|
+
value
|
|
87
|
+
when ::DateTime
|
|
88
|
+
value.to_time
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
data/lib/code-ruby.rb
CHANGED
data/spec/code_spec.rb
CHANGED
|
@@ -151,6 +151,7 @@ RSpec.describe Code do
|
|
|
151
151
|
Json.parse('[]')
|
|
152
152
|
Json.parse('{}')
|
|
153
153
|
Json.parse('random-string')
|
|
154
|
+
Ics.parse("BEGIN:VCALENDAR\nEND:VCALENDAR")
|
|
154
155
|
{}["".to_string]
|
|
155
156
|
] + ["Time.hour >= 6 and Time.hour <= 23"]
|
|
156
157
|
).each do |input|
|
|
@@ -557,4 +558,51 @@ RSpec.describe Code do
|
|
|
557
558
|
described_class.evaluate("UnknownConstant.zone = 1")
|
|
558
559
|
end.to raise_error(Code::Error, /UnknownConstant is not defined/)
|
|
559
560
|
end
|
|
561
|
+
|
|
562
|
+
it "parses ics events into dictionaries" do
|
|
563
|
+
result = described_class.evaluate(<<~CODE)
|
|
564
|
+
events = Ics.parse("BEGIN:VCALENDAR
|
|
565
|
+
VERSION:2.0
|
|
566
|
+
PRODID:-//code-ruby//EN
|
|
567
|
+
BEGIN:VEVENT
|
|
568
|
+
UID:event-1
|
|
569
|
+
DTSTART:20260327T120000Z
|
|
570
|
+
DTEND:20260327T133000Z
|
|
571
|
+
SUMMARY:Lunch
|
|
572
|
+
DESCRIPTION:Team lunch
|
|
573
|
+
LOCATION:Paris
|
|
574
|
+
URL:https://example.com/events/1
|
|
575
|
+
CATEGORIES:food,team
|
|
576
|
+
END:VEVENT
|
|
577
|
+
END:VCALENDAR")
|
|
578
|
+
|
|
579
|
+
{
|
|
580
|
+
size: events.size,
|
|
581
|
+
summary: events.first.summary,
|
|
582
|
+
location: events.first.location,
|
|
583
|
+
uid: events.first.uid,
|
|
584
|
+
categories: events.first.categories,
|
|
585
|
+
starts_at: events.first.starts_at.to_string,
|
|
586
|
+
ends_at: events.first.ends_at.to_string,
|
|
587
|
+
all_day: events.first.all_day
|
|
588
|
+
}
|
|
589
|
+
CODE
|
|
590
|
+
|
|
591
|
+
expect(result).to eq(
|
|
592
|
+
{
|
|
593
|
+
size: 1,
|
|
594
|
+
summary: "Lunch",
|
|
595
|
+
location: "Paris",
|
|
596
|
+
uid: "event-1",
|
|
597
|
+
categories: ["food", "team"],
|
|
598
|
+
starts_at: "2026-03-27 12:00:00 UTC",
|
|
599
|
+
ends_at: "2026-03-27 13:30:00 UTC",
|
|
600
|
+
all_day: false
|
|
601
|
+
}.to_code
|
|
602
|
+
)
|
|
603
|
+
end
|
|
604
|
+
|
|
605
|
+
it "returns an empty list for invalid ics" do
|
|
606
|
+
expect(described_class.evaluate('Ics.parse("not an ics file")')).to eq([].to_code)
|
|
607
|
+
end
|
|
560
608
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: code-ruby
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.0.
|
|
4
|
+
version: 3.0.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dorian Marié
|
|
@@ -79,6 +79,20 @@ dependencies:
|
|
|
79
79
|
- - ">="
|
|
80
80
|
- !ruby/object:Gem::Version
|
|
81
81
|
version: '0'
|
|
82
|
+
- !ruby/object:Gem::Dependency
|
|
83
|
+
name: icalendar
|
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
|
85
|
+
requirements:
|
|
86
|
+
- - ">="
|
|
87
|
+
- !ruby/object:Gem::Version
|
|
88
|
+
version: '0'
|
|
89
|
+
type: :runtime
|
|
90
|
+
prerelease: false
|
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
92
|
+
requirements:
|
|
93
|
+
- - ">="
|
|
94
|
+
- !ruby/object:Gem::Version
|
|
95
|
+
version: '0'
|
|
82
96
|
- !ruby/object:Gem::Dependency
|
|
83
97
|
name: json
|
|
84
98
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -275,6 +289,7 @@ files:
|
|
|
275
289
|
- lib/code/object/global.rb
|
|
276
290
|
- lib/code/object/html.rb
|
|
277
291
|
- lib/code/object/http.rb
|
|
292
|
+
- lib/code/object/ics.rb
|
|
278
293
|
- lib/code/object/identifier_list.rb
|
|
279
294
|
- lib/code/object/integer.rb
|
|
280
295
|
- lib/code/object/json.rb
|