code-ruby 3.1.2 → 4.0.0
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/VERSION +1 -1
- data/bin/code +97 -20
- data/lib/code/concerns/shared.rb +331 -15
- data/lib/code/format.rb +15 -1
- data/lib/code/network.rb +87 -0
- data/lib/code/node/call.rb +79 -2
- data/lib/code/node/call_argument.rb +14 -0
- data/lib/code/node/code.rb +5 -4
- data/lib/code/node/function_parameter.rb +7 -4
- data/lib/code/node/list.rb +29 -1
- data/lib/code/object/base_64.rb +132 -6
- data/lib/code/object/boolean.rb +60 -0
- data/lib/code/object/class.rb +138 -2
- data/lib/code/object/code.rb +111 -3
- data/lib/code/object/context.rb +57 -1
- data/lib/code/object/cryptography.rb +63 -0
- data/lib/code/object/date.rb +13339 -462
- data/lib/code/object/decimal.rb +1725 -0
- data/lib/code/object/dictionary.rb +1790 -11
- data/lib/code/object/duration.rb +28 -0
- data/lib/code/object/function.rb +261 -23
- data/lib/code/object/global.rb +534 -1
- data/lib/code/object/html.rb +179 -7
- data/lib/code/object/http.rb +244 -14
- data/lib/code/object/ics.rb +75 -13
- data/lib/code/object/identifier_list.rb +17 -2
- data/lib/code/object/integer.rb +1937 -2
- data/lib/code/object/json.rb +75 -1
- data/lib/code/object/list.rb +3383 -10
- data/lib/code/object/nothing.rb +53 -0
- data/lib/code/object/number.rb +110 -0
- data/lib/code/object/parameter.rb +140 -0
- data/lib/code/object/range.rb +576 -14
- data/lib/code/object/smtp.rb +95 -12
- data/lib/code/object/string.rb +944 -3
- data/lib/code/object/super.rb +10 -1
- data/lib/code/object/time.rb +13358 -498
- data/lib/code/object/url.rb +65 -0
- data/lib/code/object.rb +543 -0
- data/lib/code/parser.rb +161 -24
- data/lib/code-ruby.rb +3 -0
- data/lib/code.rb +30 -3
- metadata +135 -84
- data/.github/dependabot.yml +0 -15
- data/.github/workflows/ci.yml +0 -38
- data/.gitignore +0 -30
- data/.node-version +0 -1
- data/.npm-version +0 -1
- data/.prettierignore +0 -2
- data/.rspec +0 -1
- data/.rubocop.yml +0 -140
- data/.ruby-version +0 -1
- data/.tool-versions +0 -3
- data/AGENTS.md +0 -43
- data/Gemfile +0 -22
- data/Gemfile.lock +0 -292
- data/Rakefile +0 -5
- data/bin/bundle +0 -123
- data/bin/bundle-audit +0 -31
- data/bin/bundler-audit +0 -31
- data/bin/dorian +0 -31
- data/bin/rspec +0 -31
- data/bin/rubocop +0 -31
- data/bin/test +0 -5
- data/code-ruby.gemspec +0 -34
- data/docs/precedence.txt +0 -36
- data/package-lock.json +0 -14
- data/package.json +0 -7
- data/spec/bin/code_spec.rb +0 -48
- data/spec/code/format_spec.rb +0 -153
- data/spec/code/node/call_spec.rb +0 -11
- data/spec/code/object/boolean_spec.rb +0 -18
- data/spec/code/object/cryptography_spec.rb +0 -25
- data/spec/code/object/decimal_spec.rb +0 -50
- data/spec/code/object/dictionary_spec.rb +0 -98
- data/spec/code/object/function_spec.rb +0 -268
- data/spec/code/object/http_spec.rb +0 -33
- data/spec/code/object/ics_spec.rb +0 -50
- data/spec/code/object/integer_spec.rb +0 -42
- data/spec/code/object/list_spec.rb +0 -22
- data/spec/code/object/nothing_spec.rb +0 -14
- data/spec/code/object/range_spec.rb +0 -23
- data/spec/code/object/string_spec.rb +0 -26
- data/spec/code/parser/boolean_spec.rb +0 -11
- data/spec/code/parser/chained_call_spec.rb +0 -16
- data/spec/code/parser/dictionary_spec.rb +0 -18
- data/spec/code/parser/function_spec.rb +0 -16
- data/spec/code/parser/group_spec.rb +0 -11
- data/spec/code/parser/if_modifier_spec.rb +0 -18
- data/spec/code/parser/list_spec.rb +0 -17
- data/spec/code/parser/number_spec.rb +0 -11
- data/spec/code/parser/string_spec.rb +0 -20
- data/spec/code/parser_spec.rb +0 -52
- data/spec/code/type_spec.rb +0 -21
- data/spec/code_spec.rb +0 -717
- data/spec/spec_helper.rb +0 -21
- data/spec/zeitwerk/loader_spec.rb +0 -7
data/lib/code/object/ics.rb
CHANGED
|
@@ -3,6 +3,33 @@
|
|
|
3
3
|
class Code
|
|
4
4
|
class Object
|
|
5
5
|
class Ics < Object
|
|
6
|
+
CLASS_DOCUMENTATION = {
|
|
7
|
+
name: "Ics",
|
|
8
|
+
description: "parses icalendar text and exposes events as dictionaries.",
|
|
9
|
+
examples: [
|
|
10
|
+
"Ics.parse(\"BEGIN:VCALENDAR\\nBEGIN:VEVENT\\nSUMMARY:meet\\nEND:VEVENT\\nEND:VCALENDAR\")",
|
|
11
|
+
"Ics.parse(\"BEGIN:VCALENDAR\\nVERSION:2.0\\nEND:VCALENDAR\")",
|
|
12
|
+
"Ics.parse(\"\")"
|
|
13
|
+
]
|
|
14
|
+
}.freeze
|
|
15
|
+
CLASS_FUNCTIONS = {
|
|
16
|
+
"parse" => {
|
|
17
|
+
name: "parse",
|
|
18
|
+
description: "returns event dictionaries parsed from icalendar text.",
|
|
19
|
+
examples: [
|
|
20
|
+
"Ics.parse(\"BEGIN:VCALENDAR\\nBEGIN:VEVENT\\nUID:1\\nSUMMARY:demo\\nEND:VEVENT\\nEND:VCALENDAR\")",
|
|
21
|
+
"Ics.parse(\"BEGIN:VCALENDAR\\nEND:VCALENDAR\")",
|
|
22
|
+
"Ics.parse(\"not calendar data\")"
|
|
23
|
+
]
|
|
24
|
+
}
|
|
25
|
+
}.freeze
|
|
26
|
+
|
|
27
|
+
def self.function_documentation(scope)
|
|
28
|
+
return CLASS_FUNCTIONS if scope == :class
|
|
29
|
+
|
|
30
|
+
{}
|
|
31
|
+
end
|
|
32
|
+
|
|
6
33
|
EVENT_ATTRIBUTES = %i[
|
|
7
34
|
uid
|
|
8
35
|
summary
|
|
@@ -15,6 +42,9 @@ class Code
|
|
|
15
42
|
attendees
|
|
16
43
|
geo
|
|
17
44
|
].freeze
|
|
45
|
+
MISSING_ATTRIBUTE = Object.new.freeze
|
|
46
|
+
MAX_EVENTS = 10_000
|
|
47
|
+
MAX_NESTING = 50
|
|
18
48
|
|
|
19
49
|
def self.call(**args)
|
|
20
50
|
code_operator = args.fetch(:operator, nil).to_code
|
|
@@ -32,11 +62,14 @@ class Code
|
|
|
32
62
|
|
|
33
63
|
def self.code_parse(value)
|
|
34
64
|
source = value.to_code.raw
|
|
65
|
+
::Code.ensure_input_size!(source, label: "ics")
|
|
35
66
|
calendars = ::Icalendar::Calendar.parse(source)
|
|
36
|
-
calendars
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
67
|
+
events = calendars.flat_map(&:events)
|
|
68
|
+
raise Error, "ics has too many events" if events.size > MAX_EVENTS
|
|
69
|
+
|
|
70
|
+
events.map { |event| serialize_event(event) }.to_code
|
|
71
|
+
rescue ::Code::Error
|
|
72
|
+
raise
|
|
40
73
|
rescue StandardError
|
|
41
74
|
[].to_code
|
|
42
75
|
end
|
|
@@ -44,9 +77,9 @@ class Code
|
|
|
44
77
|
def self.serialize_event(event)
|
|
45
78
|
EVENT_ATTRIBUTES
|
|
46
79
|
.each_with_object({}) do |attribute, result|
|
|
47
|
-
|
|
80
|
+
serialized = serialize_value(event_attribute(event, attribute))
|
|
81
|
+
next if serialized == MISSING_ATTRIBUTE
|
|
48
82
|
|
|
49
|
-
serialized = serialize_value(event.public_send(attribute))
|
|
50
83
|
serialized =
|
|
51
84
|
if attribute == :categories && serialized.is_a?(::Array)
|
|
52
85
|
serialized.flatten(1)
|
|
@@ -67,7 +100,36 @@ class Code
|
|
|
67
100
|
.compact
|
|
68
101
|
end
|
|
69
102
|
|
|
70
|
-
def self.
|
|
103
|
+
def self.event_attribute(event, attribute)
|
|
104
|
+
case attribute
|
|
105
|
+
when :uid
|
|
106
|
+
event.uid
|
|
107
|
+
when :summary
|
|
108
|
+
event.summary
|
|
109
|
+
when :description
|
|
110
|
+
event.description
|
|
111
|
+
when :location
|
|
112
|
+
event.location
|
|
113
|
+
when :url
|
|
114
|
+
event.url
|
|
115
|
+
when :status
|
|
116
|
+
event.status
|
|
117
|
+
when :organizer
|
|
118
|
+
event.organizer
|
|
119
|
+
when :categories
|
|
120
|
+
event.categories
|
|
121
|
+
when :attendees
|
|
122
|
+
event.attendees
|
|
123
|
+
when :geo
|
|
124
|
+
event.geo
|
|
125
|
+
end
|
|
126
|
+
rescue NoMethodError
|
|
127
|
+
MISSING_ATTRIBUTE
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def self.serialize_value(value, depth: 0)
|
|
131
|
+
raise Error, "ics is too deeply nested" if depth > MAX_NESTING
|
|
132
|
+
|
|
71
133
|
case value
|
|
72
134
|
when nil
|
|
73
135
|
nil
|
|
@@ -76,17 +138,17 @@ class Code
|
|
|
76
138
|
when ::Symbol, ::Integer, ::Float, ::BigDecimal, true, false
|
|
77
139
|
value
|
|
78
140
|
when ::Array
|
|
79
|
-
value.map { |item| serialize_value(item) }
|
|
141
|
+
value.map { |item| serialize_value(item, depth: depth + 1) }
|
|
80
142
|
when ::Hash
|
|
81
|
-
value.transform_values
|
|
143
|
+
value.transform_values do |item|
|
|
144
|
+
serialize_value(item, depth: depth + 1)
|
|
145
|
+
end
|
|
82
146
|
else
|
|
83
147
|
serialized_date = serialize_date_like(value)
|
|
84
148
|
return serialized_date unless serialized_date.nil?
|
|
85
149
|
|
|
86
|
-
if value.
|
|
87
|
-
serialize_value(value.value)
|
|
88
|
-
elsif value.respond_to?(:to_ical)
|
|
89
|
-
normalize_string(value.to_ical)
|
|
150
|
+
if value.is_a?(::Icalendar::Value)
|
|
151
|
+
serialize_value(value.value, depth: depth + 1)
|
|
90
152
|
else
|
|
91
153
|
normalize_string(value.to_s)
|
|
92
154
|
end
|
|
@@ -3,6 +3,15 @@
|
|
|
3
3
|
class Code
|
|
4
4
|
class Object
|
|
5
5
|
class IdentifierList < List
|
|
6
|
+
CLASS_DOCUMENTATION = {
|
|
7
|
+
name: "IdentifierList",
|
|
8
|
+
description: "stores ordered identifier names used to assign nested values.",
|
|
9
|
+
examples: [
|
|
10
|
+
"IdentifierList",
|
|
11
|
+
"IdentifierList.new([:user, :name]).first",
|
|
12
|
+
"IdentifierList.new([:user, :name]).join(\".\")"
|
|
13
|
+
]
|
|
14
|
+
}.freeze
|
|
6
15
|
def call(**args)
|
|
7
16
|
code_operator = args.fetch(:operator, nil).to_code
|
|
8
17
|
code_arguments = args.fetch(:arguments, []).to_code
|
|
@@ -87,7 +96,7 @@ class Code
|
|
|
87
96
|
**args,
|
|
88
97
|
operator: "#{raw.last}=",
|
|
89
98
|
arguments: Object::List.new([code_value])
|
|
90
|
-
)
|
|
99
|
+
).tap { persist_class_receiver(receiver, args.fetch(:context)) }
|
|
91
100
|
else
|
|
92
101
|
next_value =
|
|
93
102
|
receiver.call(
|
|
@@ -104,9 +113,15 @@ class Code
|
|
|
104
113
|
**args,
|
|
105
114
|
operator: "#{raw.last}=",
|
|
106
115
|
arguments: Object::List.new([next_value])
|
|
107
|
-
)
|
|
116
|
+
).tap { persist_class_receiver(receiver, args.fetch(:context)) }
|
|
108
117
|
end
|
|
109
118
|
end
|
|
119
|
+
|
|
120
|
+
def persist_class_receiver(receiver, context)
|
|
121
|
+
return unless receiver.is_a?(Object::Class)
|
|
122
|
+
|
|
123
|
+
context.code_set(raw.first, receiver)
|
|
124
|
+
end
|
|
110
125
|
end
|
|
111
126
|
end
|
|
112
127
|
end
|