Almirah 0.0.8 → 0.0.9
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/lib/almirah/doc_fabric.rb +33 -4
- data/lib/almirah/doc_items/blockquote.rb +2 -1
- data/lib/almirah/doc_items/controlled_paragraph.rb +2 -1
- data/lib/almirah/doc_items/controlled_table.rb +8 -6
- data/lib/almirah/doc_items/doc_item.rb +3 -1
- data/lib/almirah/doc_items/heading.rb +1 -1
- data/lib/almirah/doc_items/markdown_list.rb +118 -7
- data/lib/almirah/doc_items/markdown_table.rb +2 -1
- data/lib/almirah/doc_items/paragraph.rb +2 -2
- data/lib/almirah/doc_items/text_line.rb +169 -0
- data/lib/almirah/doc_types/specification.rb +26 -0
- data/lib/almirah/project.rb +1 -0
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9e500204a8575e500989c7d86e4db4dff7a6247b14d3768904620be7a3cef356
|
4
|
+
data.tar.gz: a12d76101a33fc1938c0c42d361f84ae9a8c796684becd1567e154e67f345cad
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eff42c3d45f0be71488484ce864740c5363e9169450d32469b9044136ea47af2989b32c4cb526c176c4d4721e60be0c5f484db8ed2245285eb042187a9c5df57
|
7
|
+
data.tar.gz: 2e5c4887b584428a71db8cbd33d244242c90df9b7b02aca8804f72f97fb017dfebc4aa8ff2ae52f924ae9895f7ac1b075cac2407ba84888db55cd36d97984344
|
data/lib/almirah/doc_fabric.rb
CHANGED
@@ -124,7 +124,7 @@ class DocFabric
|
|
124
124
|
|
125
125
|
doc.items.append(item)
|
126
126
|
|
127
|
-
elsif res = /^(\*\s?)
|
127
|
+
elsif res = /^(\*\s?)(.*)/.match(s) #check if unordered list start
|
128
128
|
|
129
129
|
if tempMdTable
|
130
130
|
doc.items.append tempMdTable
|
@@ -136,7 +136,26 @@ class DocFabric
|
|
136
136
|
if tempMdList
|
137
137
|
tempMdList.addRow(row)
|
138
138
|
else
|
139
|
-
item = MarkdownList.new(
|
139
|
+
item = MarkdownList.new(false)
|
140
|
+
item.addRow(s)
|
141
|
+
item.parent_doc = doc
|
142
|
+
tempMdList = item
|
143
|
+
end
|
144
|
+
|
145
|
+
elsif res = /^\d[.]\s(.*)/.match(s) #check if ordered list start
|
146
|
+
|
147
|
+
if tempMdTable
|
148
|
+
doc.items.append tempMdTable
|
149
|
+
tempMdTable = nil
|
150
|
+
end
|
151
|
+
|
152
|
+
row = res[1]
|
153
|
+
|
154
|
+
if tempMdList
|
155
|
+
tempMdList.addRow(row)
|
156
|
+
else
|
157
|
+
item = MarkdownList.new(true)
|
158
|
+
item.addRow(s)
|
140
159
|
item.parent_doc = doc
|
141
160
|
tempMdList = item
|
142
161
|
end
|
@@ -198,14 +217,24 @@ class DocFabric
|
|
198
217
|
tempMdTable = nil
|
199
218
|
end
|
200
219
|
if tempMdList
|
201
|
-
|
202
|
-
|
220
|
+
if MarkdownList.unordered_list_item?(s) || MarkdownList.ordered_list_item?(s)
|
221
|
+
tempMdList.addRow(s)
|
222
|
+
next
|
223
|
+
else
|
224
|
+
doc.items.append tempMdList
|
225
|
+
tempMdList = nil
|
226
|
+
end
|
203
227
|
end
|
204
228
|
|
205
229
|
item = Paragraph.new(s)
|
206
230
|
item.parent_doc = doc
|
207
231
|
doc.items.append(item)
|
208
232
|
end
|
233
|
+
else
|
234
|
+
if tempMdList # lists are separated by emty line from each other
|
235
|
+
doc.items.append tempMdList
|
236
|
+
tempMdList = nil
|
237
|
+
end
|
209
238
|
end
|
210
239
|
end
|
211
240
|
# Finalize non-closed elements
|
@@ -10,12 +10,13 @@ class Blockquote < DocItem
|
|
10
10
|
|
11
11
|
def to_html
|
12
12
|
s = ''
|
13
|
+
f_text = format_string(@text)
|
13
14
|
if @@htmlTableRenderInProgress
|
14
15
|
s += "</table>\n"
|
15
16
|
@@htmlTableRenderInProgress = false
|
16
17
|
end
|
17
18
|
|
18
|
-
s += "<div class=\"blockquote\"><p>#{
|
19
|
+
s += "<div class=\"blockquote\"><p>#{f_text}</div>\n"
|
19
20
|
return s
|
20
21
|
end
|
21
22
|
end
|
@@ -22,9 +22,10 @@ class ControlledParagraph < Paragraph
|
|
22
22
|
s += "\t<thead> <th>#</th> <th>Text</th> <th>UL</th> <th>DL</th> <th>COV</th> </thead>\n"
|
23
23
|
@@htmlTableRenderInProgress = true
|
24
24
|
end
|
25
|
+
f_text = format_string(@text)
|
25
26
|
s += "\t<tr>\n"
|
26
27
|
s += "\t\t<td class=\"item_id\"> <a name=\"#{@id}\" id=\"#{@id}\" href=\"##{@id}\">#{@id}</a></td>\n"
|
27
|
-
s += "\t\t<td class=\"item_text\">#{
|
28
|
+
s += "\t\t<td class=\"item_text\">#{f_text}</td>\n"
|
28
29
|
|
29
30
|
if @up_link
|
30
31
|
if tmp = /^([a-zA-Z]+)[-]\d+/.match(@up_link)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require_relative "controlled_table_row"
|
2
|
+
require_relative "text_line"
|
2
3
|
|
3
|
-
|
4
|
-
class ControlledTableColumn
|
4
|
+
class ControlledTableColumn < TextLine
|
5
5
|
|
6
6
|
attr_accessor :text
|
7
7
|
|
@@ -10,7 +10,8 @@ class ControlledTableColumn
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def to_html
|
13
|
-
|
13
|
+
f_text = format_string(@text)
|
14
|
+
"\t\t<td>#{f_text}</td>\n\r"
|
14
15
|
end
|
15
16
|
end
|
16
17
|
|
@@ -41,12 +42,13 @@ end
|
|
41
42
|
class TestStepResultColumn < ControlledTableColumn
|
42
43
|
|
43
44
|
def to_html
|
45
|
+
f_text = format_string(@text)
|
44
46
|
if @text.downcase == "pass"
|
45
|
-
"\t\t<td style=\"background-color: #cfc;\">#{
|
47
|
+
"\t\t<td style=\"background-color: #cfc;\">#{f_text}</td>\n\r"
|
46
48
|
elsif @text.downcase == "fail"
|
47
|
-
"\t\t<td style=\"background-color: #fcc;\">#{
|
49
|
+
"\t\t<td style=\"background-color: #fcc;\">#{f_text}</td>\n\r"
|
48
50
|
else
|
49
|
-
"\t\t<td>#{
|
51
|
+
"\t\t<td>#{f_text}</td>\n\r"
|
50
52
|
end
|
51
53
|
end
|
52
54
|
end
|
@@ -3,14 +3,107 @@ require_relative "doc_item"
|
|
3
3
|
class MarkdownList < DocItem
|
4
4
|
|
5
5
|
attr_accessor :rows
|
6
|
+
attr_accessor :text
|
7
|
+
attr_accessor :is_ordered
|
8
|
+
attr_accessor :indent_position
|
9
|
+
attr_accessor :current_nesting_level
|
6
10
|
|
7
|
-
|
11
|
+
@@lists_stack = Array.new
|
12
|
+
|
13
|
+
def initialize(is_ordered)
|
8
14
|
@rows = Array.new
|
9
|
-
@
|
15
|
+
@is_ordered = is_ordered
|
16
|
+
@current_nesting_level = 0
|
17
|
+
@indent_position = 0
|
18
|
+
@text = ''
|
19
|
+
|
20
|
+
@@lists_stack.push(self)
|
21
|
+
end
|
22
|
+
|
23
|
+
def addRow(raw_text)
|
24
|
+
puts raw_text
|
25
|
+
pos = calculate_text_position(raw_text)
|
26
|
+
row = raw_text[pos..-1]
|
27
|
+
|
28
|
+
pos = calculate_indent_position(raw_text)
|
29
|
+
|
30
|
+
if pos > @@lists_stack[-1].indent_position
|
31
|
+
|
32
|
+
prev_lists_stack_item = @@lists_stack[-1]
|
33
|
+
# the following line pushes new list to the lists_stack in the constructor!
|
34
|
+
nested_list = MarkdownList.new( MarkdownList.ordered_list_item?(raw_text) )
|
35
|
+
nested_list.current_nesting_level = @current_nesting_level + 1
|
36
|
+
nested_list.indent_position = pos
|
37
|
+
|
38
|
+
prev_row = prev_lists_stack_item.rows[-1]
|
39
|
+
if prev_row.is_a?(MarkdownList)
|
40
|
+
#cannot be there
|
41
|
+
else
|
42
|
+
nested_list.text = prev_row
|
43
|
+
puts "Length: " + prev_lists_stack_item.rows.length.to_s
|
44
|
+
prev_lists_stack_item.rows[-1] = nested_list
|
45
|
+
end
|
46
|
+
|
47
|
+
nested_list.addRow(raw_text)
|
48
|
+
|
49
|
+
elsif pos < @@lists_stack[-1].indent_position
|
50
|
+
|
51
|
+
@@lists_stack.pop
|
52
|
+
@@lists_stack[-1].rows.append(row)
|
53
|
+
|
54
|
+
else
|
55
|
+
@@lists_stack[-1].rows.append(row)
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def calculate_indent_position(s)
|
61
|
+
pos = 0
|
62
|
+
s.each_char do |c|
|
63
|
+
if non_blank?(c)
|
64
|
+
break
|
65
|
+
end
|
66
|
+
pos += 1
|
67
|
+
end
|
68
|
+
return pos
|
69
|
+
end
|
70
|
+
def calculate_text_position(s)
|
71
|
+
pos = 0
|
72
|
+
s.each_char do |c|
|
73
|
+
if letter?(c)
|
74
|
+
break
|
75
|
+
end
|
76
|
+
pos += 1
|
77
|
+
end
|
78
|
+
return pos
|
79
|
+
end
|
80
|
+
|
81
|
+
def letter?(c)
|
82
|
+
c.match?(/[[:alpha:]]/)
|
83
|
+
end
|
84
|
+
|
85
|
+
def numeric?(c)
|
86
|
+
c.match?(/[[:digit:]]/)
|
10
87
|
end
|
11
88
|
|
12
|
-
def
|
13
|
-
|
89
|
+
def non_blank?(c)
|
90
|
+
c.match?(/[[:graph:]]/)
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.unordered_list_item?(raw_text)
|
94
|
+
|
95
|
+
if res = /(\*\s?)(.*)/.match(raw_text)
|
96
|
+
return true
|
97
|
+
end
|
98
|
+
return false
|
99
|
+
end
|
100
|
+
|
101
|
+
def self.ordered_list_item?(raw_text)
|
102
|
+
|
103
|
+
if res = /\d[.]\s(.*)/.match(raw_text)
|
104
|
+
return true
|
105
|
+
end
|
106
|
+
return false
|
14
107
|
end
|
15
108
|
|
16
109
|
def to_html
|
@@ -20,11 +113,29 @@ class MarkdownList < DocItem
|
|
20
113
|
@@htmlTableRenderInProgress = false
|
21
114
|
end
|
22
115
|
|
23
|
-
|
116
|
+
if @is_ordered
|
117
|
+
s += "<ol>\n"
|
118
|
+
else
|
119
|
+
s += "<ul>\n"
|
120
|
+
end
|
121
|
+
|
24
122
|
@rows.each do |r|
|
25
|
-
|
123
|
+
if r.is_a?(MarkdownList)
|
124
|
+
f_text = format_string(r.text)
|
125
|
+
s += "\t<li>#{f_text}\n"
|
126
|
+
s += r.to_html()
|
127
|
+
s += "</li>\n"
|
128
|
+
else
|
129
|
+
f_text = format_string(r)
|
130
|
+
s += "\t<li>#{f_text}</li>\n"
|
131
|
+
end
|
26
132
|
end
|
27
|
-
|
133
|
+
|
134
|
+
if @is_ordered
|
135
|
+
s += "</ol>\n"
|
136
|
+
else
|
137
|
+
s += "</ul>\n"
|
138
|
+
end
|
28
139
|
|
29
140
|
return s
|
30
141
|
end
|
@@ -44,7 +44,8 @@ class MarkdownTable < DocItem
|
|
44
44
|
if col.to_i > 0 && col.to_i.to_s == col # autoalign cells with numbers
|
45
45
|
s += "\t\t<td style=\"text-align: center;\">#{col}</td>\n"
|
46
46
|
else
|
47
|
-
|
47
|
+
f_text = format_string(col)
|
48
|
+
s += "\t\t<td>#{f_text}</td>\n"
|
48
49
|
end
|
49
50
|
end
|
50
51
|
s += "\t</tr>\n"
|
@@ -9,7 +9,7 @@ class Paragraph < DocItem
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def getTextWithoutSpaces
|
12
|
-
return @text.split.join('-')
|
12
|
+
return @text.split.join('-').downcase
|
13
13
|
end
|
14
14
|
|
15
15
|
def to_html
|
@@ -19,7 +19,7 @@ class Paragraph < DocItem
|
|
19
19
|
@@htmlTableRenderInProgress = false
|
20
20
|
end
|
21
21
|
|
22
|
-
s += "<p
|
22
|
+
s += "<p>" + format_string(@text)
|
23
23
|
return s
|
24
24
|
end
|
25
25
|
end
|
@@ -0,0 +1,169 @@
|
|
1
|
+
class TextLine
|
2
|
+
|
3
|
+
def format_string(str)
|
4
|
+
state = 'default'
|
5
|
+
prev_state = 'default'
|
6
|
+
result = ''
|
7
|
+
stack = ''
|
8
|
+
prev_c = ''
|
9
|
+
link_text = ''
|
10
|
+
link_url = ''
|
11
|
+
str.each_char do |c|
|
12
|
+
if c == '*'
|
13
|
+
if state == 'default'
|
14
|
+
prev_state = state
|
15
|
+
state = 'first_asterisk_detected'
|
16
|
+
|
17
|
+
elsif state == 'first_asterisk_detected'
|
18
|
+
prev_state = state
|
19
|
+
state = 'second_asterisk_detected'
|
20
|
+
|
21
|
+
elsif state == 'second_asterisk_detected'
|
22
|
+
prev_state = state
|
23
|
+
state = 'third_asterisk_detected'
|
24
|
+
|
25
|
+
elsif state == 'second_asterisk_detected'
|
26
|
+
prev_state = state
|
27
|
+
state = 'third_asterisk_detected'
|
28
|
+
|
29
|
+
elsif state == 'italic_started'
|
30
|
+
prev_state = state
|
31
|
+
state = 'default'
|
32
|
+
result += italic(stack)
|
33
|
+
|
34
|
+
elsif state == 'bold_started'
|
35
|
+
prev_state = state
|
36
|
+
state = 'first_asterisk_after_bold_detected'
|
37
|
+
|
38
|
+
elsif state == 'first_asterisk_after_bold_detected'
|
39
|
+
prev_state = state
|
40
|
+
state = 'default'
|
41
|
+
result += bold(stack)
|
42
|
+
|
43
|
+
elsif state == 'bold_and_italic_started'
|
44
|
+
prev_state = state
|
45
|
+
state = 'first_asterisk_after_bold_and_italic_detected'
|
46
|
+
|
47
|
+
elsif state == 'first_asterisk_after_bold_and_italic_detected'
|
48
|
+
prev_state = state
|
49
|
+
state = 'second_asterisk_after_bold_and_italic_detected'
|
50
|
+
|
51
|
+
elsif state == 'second_asterisk_after_bold_and_italic_detected'
|
52
|
+
prev_state = state
|
53
|
+
state = 'default'
|
54
|
+
result += bold_and_italic(stack)
|
55
|
+
|
56
|
+
else
|
57
|
+
end
|
58
|
+
elsif c == '['
|
59
|
+
if state == 'default'
|
60
|
+
prev_state = state
|
61
|
+
state = 'square_bracket_left_detected'
|
62
|
+
else
|
63
|
+
end
|
64
|
+
elsif c == ']'
|
65
|
+
if state == 'square_bracket_left_detected'
|
66
|
+
prev_state = state
|
67
|
+
state = 'default'
|
68
|
+
result += '[]'
|
69
|
+
|
70
|
+
elsif state == 'link_text_started'
|
71
|
+
prev_state = state
|
72
|
+
state = 'square_bracket_right_detected'
|
73
|
+
link_text = stack
|
74
|
+
|
75
|
+
else
|
76
|
+
end
|
77
|
+
elsif c == '('
|
78
|
+
if state == 'square_bracket_right_detected'
|
79
|
+
prev_state = state
|
80
|
+
state = 'brace_left_detected'
|
81
|
+
else
|
82
|
+
end
|
83
|
+
elsif c == ')'
|
84
|
+
if state == 'brace_left_detected'
|
85
|
+
prev_state = state
|
86
|
+
state = 'default'
|
87
|
+
result += '()'
|
88
|
+
|
89
|
+
elsif state == 'link_url_started'
|
90
|
+
prev_state = state
|
91
|
+
state = 'default'
|
92
|
+
link_url = stack
|
93
|
+
result += link(link_text, link_url)
|
94
|
+
|
95
|
+
else
|
96
|
+
end
|
97
|
+
else
|
98
|
+
if state == 'default'
|
99
|
+
result += c
|
100
|
+
else
|
101
|
+
if state == 'first_asterisk_detected'
|
102
|
+
prev_state = state
|
103
|
+
state = 'italic_started'
|
104
|
+
stack = ''
|
105
|
+
|
106
|
+
elsif state == 'second_asterisk_detected'
|
107
|
+
prev_state = state
|
108
|
+
state = 'bold_started'
|
109
|
+
stack = ''
|
110
|
+
|
111
|
+
elsif state == 'third_asterisk_detected'
|
112
|
+
prev_state = state
|
113
|
+
state = 'bold_and_italic_started'
|
114
|
+
stack = ''
|
115
|
+
|
116
|
+
elsif state == 'first_asterisk_after_bold_detected'
|
117
|
+
prev_state = state
|
118
|
+
state = 'bold_started'
|
119
|
+
|
120
|
+
elsif state == 'first_asterisk_after_bold_and_italic_detected'
|
121
|
+
prev_state = state
|
122
|
+
state = 'bold_and_italic_started'
|
123
|
+
|
124
|
+
elsif state == 'second_asterisk_after_bold_and_italic_detected'
|
125
|
+
prev_state = state
|
126
|
+
state = 'bold_and_italic_started'
|
127
|
+
|
128
|
+
elsif state == 'square_bracket_left_detected'
|
129
|
+
prev_state = state
|
130
|
+
state = 'link_text_started'
|
131
|
+
stack = ''
|
132
|
+
|
133
|
+
elsif state == 'square_bracket_right_detected'
|
134
|
+
prev_state = state
|
135
|
+
state = 'default'
|
136
|
+
result += stack + c
|
137
|
+
c = ''
|
138
|
+
|
139
|
+
elsif state == 'brace_left_detected'
|
140
|
+
prev_state = state
|
141
|
+
state = 'link_url_started'
|
142
|
+
stack = ''
|
143
|
+
|
144
|
+
else
|
145
|
+
end
|
146
|
+
stack += c
|
147
|
+
end
|
148
|
+
end
|
149
|
+
prev_c = c
|
150
|
+
end
|
151
|
+
return result
|
152
|
+
end
|
153
|
+
|
154
|
+
def italic(str)
|
155
|
+
"<i>#{str}</i>"
|
156
|
+
end
|
157
|
+
|
158
|
+
def bold(str)
|
159
|
+
"<b>#{str}</b>"
|
160
|
+
end
|
161
|
+
|
162
|
+
def bold_and_italic(str)
|
163
|
+
"<b><i>#{str}</i></b>"
|
164
|
+
end
|
165
|
+
|
166
|
+
def link(link_text, link_url)
|
167
|
+
"<a href=\"#{link_url}\" class=\"external\">#{link_text}</a>"
|
168
|
+
end
|
169
|
+
end
|
@@ -67,6 +67,7 @@ class Specification < BaseDocument
|
|
67
67
|
|
68
68
|
@items.each do |item|
|
69
69
|
a = item.to_html
|
70
|
+
a = adjust_internal_links(a, nav_pane.specifications)
|
70
71
|
html_rows.append a
|
71
72
|
end
|
72
73
|
|
@@ -74,4 +75,29 @@ class Specification < BaseDocument
|
|
74
75
|
|
75
76
|
end
|
76
77
|
|
78
|
+
def adjust_internal_links(line, specifications)
|
79
|
+
# check if there are internal links to md files and replace them
|
80
|
+
if tmp = /<a\shref="(.*)"\sclass="external">.*<\/a>/.match(line)
|
81
|
+
if res = /(\w*)[.]md/.match(tmp[1])
|
82
|
+
id = res[1].downcase
|
83
|
+
res = /(\w*)[.]md(#.*)/.match(tmp[1])
|
84
|
+
|
85
|
+
specifications.each do |spec|
|
86
|
+
if spec.id.downcase == id
|
87
|
+
if res && res.length > 2
|
88
|
+
anchor = res[2]
|
89
|
+
line.sub!(/<a\shref="(.*)"\sclass="external">/,
|
90
|
+
"<a href=\".\\..\\#{id}\\#{id}.html#{anchor}\" class=\"external\">")
|
91
|
+
else
|
92
|
+
line.sub!(/<a\shref="(.*)"\sclass="external">/,
|
93
|
+
"<a href=\".\\..\\#{id}\\#{id}.html\" class=\"external\">")
|
94
|
+
end
|
95
|
+
break
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
return line
|
101
|
+
end
|
102
|
+
|
77
103
|
end
|
data/lib/almirah/project.rb
CHANGED
metadata
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: Almirah
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Oleksandr Ivanov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-03-03 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
|
-
description: The software part of the Almirah
|
13
|
+
description: The software part of the Almirah framework
|
14
14
|
email: oleksandr.ivanov.development@gmail.com
|
15
15
|
executables:
|
16
16
|
- almirah
|
@@ -30,6 +30,7 @@ files:
|
|
30
30
|
- lib/almirah/doc_items/markdown_list.rb
|
31
31
|
- lib/almirah/doc_items/markdown_table.rb
|
32
32
|
- lib/almirah/doc_items/paragraph.rb
|
33
|
+
- lib/almirah/doc_items/text_line.rb
|
33
34
|
- lib/almirah/doc_types/base_document.rb
|
34
35
|
- lib/almirah/doc_types/coverage.rb
|
35
36
|
- lib/almirah/doc_types/protocol.rb
|
@@ -57,7 +58,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
57
58
|
- !ruby/object:Gem::Version
|
58
59
|
version: '0'
|
59
60
|
requirements: []
|
60
|
-
rubygems_version: 3.
|
61
|
+
rubygems_version: 3.5.6
|
61
62
|
signing_key:
|
62
63
|
specification_version: 4
|
63
64
|
summary: Almirah
|