Almirah 0.0.8 → 0.0.9
Sign up to get free protection for your applications and to get access to all the features.
- 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
|