Class: Code::Object::Ics
Constant Summary
collapse
- CLASS_DOCUMENTATION =
{
name: "Ics",
description:
"parses icalendar text and exposes events as dictionaries.",
examples: [
"Ics.parse(\"BEGIN:VCALENDAR\\nBEGIN:VEVENT\\nSUMMARY:meet\\nEND:VEVENT\\nEND:VCALENDAR\")",
"Ics.parse(\"BEGIN:VCALENDAR\\nVERSION:2.0\\nEND:VCALENDAR\")",
"Ics.parse(\"\")"
]
}.freeze
- CLASS_FUNCTIONS =
{
"parse" => {
name: "parse",
description: "returns event dictionaries parsed from icalendar text.",
examples: [
"Ics.parse(\"BEGIN:VCALENDAR\\nBEGIN:VEVENT\\nUID:1\\nSUMMARY:demo\\nEND:VEVENT\\nEND:VCALENDAR\")",
"Ics.parse(\"BEGIN:VCALENDAR\\nEND:VCALENDAR\")",
"Ics.parse(\"not calendar data\")"
]
}
}.freeze
- EVENT_ATTRIBUTES =
%i[
uid
summary
description
location
url
status
organizer
categories
attendees
geo
].freeze
- MISSING_ATTRIBUTE =
Object.new.freeze
- MAX_EVENTS =
10_000
- MAX_NESTING =
50
Constants inherited
from Code::Object
INSTANCE_FUNCTIONS, NUMBER_CLASSES
Concerns::Shared::COMPOUND_ASSIGNMENT_OPERATORS, Concerns::Shared::OPERATOR_METHOD_ALIASES, Concerns::Shared::SHARED_OPERATORS
Instance Attribute Summary
#functions, #raw
Class Method Summary
collapse
class_documentation, class_functions, code_new, #code_new, documentation, documentation_for, documented_functions_for, function_documentation_for, function_documentation_registry_for, functions, inherited_function_documentation_for, #initialize, instance_functions, maybe, #name, repeat, sorted_dictionary, |
#<=>, #==, #as_json, #blank?, #call, #code_and, #code_as_json, #code_blank?, #code_class_functions, #code_compare, #code_deep_duplicate, #code_different, #code_documentable_functions, #code_documentation, #code_duplicate, #code_dynamic_call, #code_equal, #code_exclamation_mark, #code_exclusive_range, #code_false?, #code_falsy?, code_fetch, #code_fetch, #code_functions, code_get, #code_get, #code_greater, #code_greater_or_equal, #code_has_key?, #code_inclusive_range, #code_inspect, #code_instance_functions, #code_instance_of?, #code_is_a?, #code_itself, #code_less, #code_less_or_equal, #code_name, #code_nothing?, #code_or, #code_presence, #code_presence_in, #code_present?, #code_respond_to?, #code_same_object?, #code_self, #code_send, code_set, #code_set, #code_something?, #code_strict_different, #code_strict_equal, #code_tap, #code_then, #code_to_boolean, #code_to_class, #code_to_date, #code_to_decimal, #code_to_dictionary, #code_to_duration, #code_to_integer, #code_to_json, #code_to_list, #code_to_nothing, #code_to_parameter, #code_to_range, #code_to_string, #code_to_time, #code_true?, #code_truthy?, #eql?, #falsy?, #hash, #inspect, #multi_fetch, #nothing?, #present?, #sig, #something?, #succ, #to_code, #to_i, #to_json, #to_s, #truthy?
Constructor Details
This class inherits a constructor from Code::Object
Class Method Details
.call(**args) ⇒ Object
50
51
52
53
54
55
56
57
58
59
60
61
62
|
# File 'lib/code/object/ics.rb', line 50
def self.call(**args)
code_operator = args.fetch(:operator, nil).to_code
code_arguments = args.fetch(:arguments, []).to_code
code_value = code_arguments.code_first
case code_operator.to_s
when "parse"
sig(args) { String }
code_parse(code_value)
else
super
end
end
|
.code_parse(value) ⇒ Object
64
65
66
67
68
69
70
71
72
73
74
75
76
|
# File 'lib/code/object/ics.rb', line 64
def self.code_parse(value)
source = value.to_code.raw
::Code.ensure_input_size!(source, label: "ics")
calendars = ::Icalendar::Calendar.parse(source)
events = calendars.flat_map(&:events)
raise Error, "ics has too many events" if events.size > MAX_EVENTS
events.map { |event| serialize_event(event) }.to_code
rescue ::Code::Error
raise
rescue StandardError
[].to_code
end
|
.event_attribute(event, attribute) ⇒ Object
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
# File 'lib/code/object/ics.rb', line 104
def self.event_attribute(event, attribute)
case attribute
when :uid
event.uid
when :summary
event.summary
when :description
event.description
when :location
event.location
when :url
event.url
when :status
event.status
when :organizer
event.organizer
when :categories
event.categories
when :attendees
event.attendees
when :geo
event.geo
end
rescue NoMethodError
MISSING_ATTRIBUTE
end
|
.function_documentation(scope) ⇒ Object
28
29
30
31
32
|
# File 'lib/code/object/ics.rb', line 28
def self.function_documentation(scope)
return CLASS_FUNCTIONS if scope == :class
{}
end
|
.normalize_string(value) ⇒ Object
163
164
165
166
167
168
|
# File 'lib/code/object/ics.rb', line 163
def self.normalize_string(value)
value
.dup
.force_encoding(::Encoding::UTF_8)
.encode(::Encoding::UTF_8, invalid: :replace, undef: :replace)
end
|
.scalar_event_attribute?(attribute) ⇒ Boolean
159
160
161
|
# File 'lib/code/object/ics.rb', line 159
def self.scalar_event_attribute?(attribute)
!%i[categories attendees geo].include?(attribute)
end
|
.serialize_date_like(value) ⇒ Object
170
171
172
173
174
175
176
177
|
# File 'lib/code/object/ics.rb', line 170
def self.serialize_date_like(value)
case value
when ::Time, ::Date, ::ActiveSupport::TimeWithZone
value
when ::DateTime
value.to_time
end
end
|
.serialize_event(event) ⇒ Object
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
# File 'lib/code/object/ics.rb', line 78
def self.serialize_event(event)
EVENT_ATTRIBUTES
.each_with_object({}) do |attribute, result|
serialized = serialize_value(event_attribute(event, attribute))
next if serialized == MISSING_ATTRIBUTE
serialized =
if attribute == :categories && serialized.is_a?(::Array)
serialized.flatten(1)
elsif scalar_event_attribute?(attribute) &&
serialized.is_a?(::Array)
serialized.join(",")
else
serialized
end
result[attribute] = serialized unless serialized.nil?
end
.merge(
timestamp: serialize_value(event.dtstamp),
starts_at: serialize_value(event.dtstart),
ends_at: serialize_value(event.dtend),
all_day: !!serialize_date_like(event.dtstart).is_a?(::Date)
)
.compact
end
|
.serialize_value(value, depth: 0) ⇒ Object
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
|
# File 'lib/code/object/ics.rb', line 131
def self.serialize_value(value, depth: 0)
raise Error, "ics is too deeply nested" if depth > MAX_NESTING
case value
when nil
nil
when ::String
normalize_string(value)
when ::Symbol, ::Integer, ::Float, ::BigDecimal, true, false
value
when ::Array
value.map { |item| serialize_value(item, depth: depth + 1) }
when ::Hash
value.transform_values do |item|
serialize_value(item, depth: depth + 1)
end
else
serialized_date = serialize_date_like(value)
return serialized_date unless serialized_date.nil?
if value.is_a?(::Icalendar::Value)
serialize_value(value.value, depth: depth + 1)
else
normalize_string(value.to_s)
end
end
end
|