Almirah 0.1.1 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4194e03230075235a57516fed73b44215dde4a7cb42474b641bdbd7ce8a6ad55
4
- data.tar.gz: f1a4f05ca5b4cf643cd179019c67cb08ea69c8876a235dfa368e99ec782ab21f
3
+ metadata.gz: 48020d93e573f2cf9f630bc92e1b74f0f64fcdf3fe74986ab1f833437bb13aed
4
+ data.tar.gz: e38751efb3beaa7abc28c9eb58d0b604c0dc658a22e25498b39e27001e5c163c
5
5
  SHA512:
6
- metadata.gz: 56dc9e44de93dccbaf9424d6b654c00e08591b9cdcd62b5061d3356441b68f3c5b6a61778cc9d78bcf277fceb8c25d1b6f9bf34ca6f1a0a0f0284ce361d346a2
7
- data.tar.gz: 59790d27191f78845e8b7ca8e19f0c26858234dbb419f248de5034a1aac3451ed9afbcc26905fa062c2efc13b0613f3a60e2b9e57b590c3f6cd01ff55df83809
6
+ metadata.gz: 1cf68af758e43a86e79215b9017084246713b3a72b189a154e609a7f8da1709d7fe30de638493d52668349ed4a49e07977e53b6534f4a6fd92ba3ad8d484c4ac
7
+ data.tar.gz: 4eed1d68e546d5cb6ef70e7b6f6e2cb2217a22b6c6ba1356108cc341456889e3d857b50551a1398c53fe5d54eb1f27674a17955f60e7606b7fa4003b2eee12f0
@@ -8,6 +8,7 @@ require_relative "doc_items/doc_item"
8
8
  require_relative "doc_items/heading"
9
9
  require_relative "doc_items/paragraph"
10
10
  require_relative "doc_items/blockquote"
11
+ require_relative "doc_items/todo_block"
11
12
  require_relative "doc_items/controlled_paragraph"
12
13
  require_relative "doc_items/markdown_table"
13
14
  require_relative "doc_items/controlled_table"
@@ -58,25 +59,32 @@ class DocFabric
58
59
 
59
60
  level = res[1].length
60
61
  value = res[2]
62
+
63
+ if level == 1 && doc.title == ""
64
+ doc.title = value
65
+ Heading.reset_global_section_number()
66
+ end
67
+
61
68
  item = Heading.new(value, level)
62
69
  item.parent_doc = doc
63
70
  doc.items.append(item)
64
71
  doc.headings.append(item)
65
-
66
- if level == 1 && doc.title == ""
67
- doc.title = value
68
- end
72
+
69
73
  elsif res = /^\%\s(.*)/.match(s) # Pandoc Document Title
70
74
 
71
75
  title = res[1]
76
+
77
+ if doc.title == ""
78
+ doc.title = title
79
+ Heading.reset_global_section_number()
80
+ end
81
+
72
82
  item = Heading.new(title, 1)
73
83
  item.parent_doc = doc
74
84
  doc.items.append(item)
75
85
  doc.headings.append(item)
76
86
 
77
- if doc.title == ""
78
- doc.title = title
79
- end
87
+ Heading.reset_global_section_number() # Pandoc Document Title is not a section, so it shall not be taken into account in numbering
80
88
 
81
89
  elsif res = /^\[(\S*)\]\s+(.*)/.match(s) # Controlled Paragraph
82
90
 
@@ -91,35 +99,70 @@ class DocFabric
91
99
 
92
100
  id = res[1]
93
101
  text = res[2]
102
+ up_links = nil
103
+
104
+ #check if it contains the uplink (one or many)
105
+ #TODO: check this regular expression
106
+ first_pos = text.length # for trailing commas
107
+ tmp = text.scan( /(>\[(?>[^\[\]]|\g<0>)*\])/ ) # >[SRS-001], >[SYS-002]
108
+ if tmp.length >0
109
+ up_links = Array.new
110
+ tmp.each do |ul|
111
+ up_links.append(ul[0])
112
+ # try to find the real end of text
113
+ pos = text.index(ul[0])
114
+ if pos < first_pos
115
+ first_pos = pos
116
+ end
117
+ # remove uplink from text
118
+ text = text.split(ul[0]).join("")
119
+ end
120
+ # remove trailing commas and spaces
121
+ if text.length > first_pos
122
+ first_pos -= 1
123
+ text = text[0..first_pos].strip
124
+ end
125
+ end
94
126
 
95
- #check if it contains the uplink
96
- if tmp = /(.*)\s+>\[(\S*)\]$/.match(text) # >[SRS-001]
127
+ # since we already know id and text
128
+ item = ControlledParagraph.new( text, id )
97
129
 
98
- text = tmp[1]
99
- up_link = tmp[2]
100
-
101
- if tmp = /^([a-zA-Z]+)[-]\d+/.match(up_link) # SRS
102
- doc.up_link_doc_id[ tmp[1].downcase.to_s ] = tmp[1].downcase # multiple documents could be up-linked
130
+ if up_links
131
+ doc.items_with_uplinks_number += 1 #for statistics
132
+ up_links.each do |ul|
133
+ if tmp = />\[(\S*)\]$/.match(ul) # >[SRS-001]
134
+ up_link_id = tmp[1]
135
+
136
+ unless item.up_link_ids
137
+ item.up_link_ids = Array.new
138
+ end
139
+
140
+ item.up_link_ids.append(up_link_id)
141
+
142
+ if tmp = /^([a-zA-Z]+)[-]\d+/.match(up_link_id) # SRS
143
+ doc.up_link_doc_id[ tmp[1].downcase.to_s ] = tmp[1].downcase # multiple documents could be up-linked
144
+ end
145
+ end
103
146
  end
104
147
  end
105
148
 
106
- item = ControlledParagraph.new( text, id )
149
+
107
150
  item.parent_doc = doc
108
151
  item.parent_heading = doc.headings[-1]
109
- if up_link
110
- item.up_link = up_link
111
- doc.items_with_uplinks_number += 1 #for statistics
112
- end
113
152
 
114
153
  doc.items.append(item)
115
- doc.dictionary[ id.to_s ] = item #for fast search
154
+ #for statistics
155
+ if doc.dictionary.has_key?( id.to_s )
156
+ doc.duplicated_ids_number += 1
157
+ doc.duplicates_list.append(item)
158
+ else
159
+ doc.dictionary[ id.to_s ] = item #for fast search
160
+ end
116
161
  doc.controlled_items.append(item) #for fast search
117
162
 
118
163
  #for statistics
119
164
  n = /\d+/.match(id)[0].to_i
120
- if n == doc.last_used_id_number
121
- doc.duplicated_ids_number += 1
122
- elsif n > doc.last_used_id_number
165
+ if n > doc.last_used_id_number
123
166
  doc.last_used_id = id
124
167
  doc.last_used_id_number = n
125
168
  end
@@ -229,6 +272,24 @@ class DocFabric
229
272
  item = Blockquote.new(res[1])
230
273
  item.parent_doc = doc
231
274
  doc.items.append(item)
275
+
276
+ elsif res = /^TODO\:(.*)/.match(s) #check if TODO block
277
+
278
+ if tempMdTable
279
+ doc.items.append tempMdTable
280
+ tempMdTable = nil
281
+ end
282
+ if tempMdList
283
+ doc.items.append tempMdList
284
+ tempMdList = nil
285
+ end
286
+
287
+ text = "**TODO**: " + res[1]
288
+
289
+ item = TodoBlock.new(text)
290
+ item.parent_doc = doc
291
+ doc.items.append(item)
292
+ doc.todo_blocks.append(item)
232
293
 
233
294
  else # Reqular Paragraph
234
295
  if tempMdTable
@@ -3,14 +3,14 @@ require_relative "paragraph"
3
3
  class ControlledParagraph < Paragraph
4
4
 
5
5
  attr_accessor :id
6
- attr_accessor :up_link
6
+ attr_accessor :up_link_ids
7
7
  attr_accessor :down_links
8
8
  attr_accessor :coverage_links
9
9
 
10
10
  def initialize(text, id)
11
11
  @text = text.strip
12
12
  @id = id
13
- @up_link = nil
13
+ @up_link_ids = nil
14
14
  @down_links = nil
15
15
  @coverage_links = nil
16
16
  end
@@ -27,11 +27,27 @@ class ControlledParagraph < Paragraph
27
27
  s += "\t\t<td class=\"item_id\"> <a name=\"#{@id}\" id=\"#{@id}\" href=\"##{@id}\">#{@id}</a></td>\n"
28
28
  s += "\t\t<td class=\"item_text\">#{f_text}</td>\n"
29
29
 
30
- if @up_link
31
- if tmp = /^([a-zA-Z]+)[-]\d+/.match(@up_link)
32
- up_link_doc_name = tmp[1].downcase
30
+ if @up_link_ids
31
+ if @up_link_ids.length == 1
32
+ if tmp = /^([a-zA-Z]+)[-]\d+/.match(@up_link_ids[0])
33
+ up_link_doc_name = tmp[1].downcase
34
+ end
35
+ s += "\t\t<td class=\"item_id\"><a href=\"./../#{up_link_doc_name}/#{up_link_doc_name}.html##{@up_link_ids[0]}\" class=\"external\">#{@up_link_ids[0]}</a></td>\n"
36
+ else
37
+ s += "\t\t<td class=\"item_id\">"
38
+ s += "<div id=\"DL_#{@id}\" style=\"display: block;\">"
39
+ s += "<a href=\"#\" onclick=\"downlink_OnClick(this.parentElement); return false;\" class=\"external\">#{@up_link_ids.length}</a>"
40
+ s += "</div>"
41
+ s += "<div id=\"DLS_#{@id}\" style=\"display: none;\">"
42
+ @up_link_ids.each do |lnk|
43
+ if tmp = /^([a-zA-Z]+)[-]\d+/.match(lnk)
44
+ up_link_doc_name = tmp[1].downcase
45
+ end
46
+ s += "\t\t\t<a href=\"./../#{up_link_doc_name}/#{up_link_doc_name}.html##{lnk}\" class=\"external\">#{lnk}</a>\n<br>"
47
+ end
48
+ s += "</div>"
49
+ s += "</td>\n"
33
50
  end
34
- s += "\t\t<td class=\"item_id\"><a href=\"./../#{up_link_doc_name}/#{up_link_doc_name}.html##{@up_link}\" class=\"external\">#{@up_link}</a></td>\n"
35
51
  else
36
52
  s += "\t\t<td class=\"item_id\"></td>\n"
37
53
  end
@@ -13,7 +13,7 @@ class Heading < Paragraph
13
13
  @level = level
14
14
  @anchor_id = getTextWithoutSpaces()
15
15
 
16
- if @@global_section_number = ""
16
+ if @@global_section_number == ""
17
17
  @@global_section_number = "1"
18
18
  for n in 1..(level-1) do
19
19
  @@global_section_number += ".1"
@@ -27,16 +27,21 @@ class Heading < Paragraph
27
27
  a[-1] = (a[-1].to_i() +1).to_s
28
28
  @@global_section_number = a.join(".")
29
29
 
30
- elsif previous_level < level
30
+ elsif level > previous_level
31
31
 
32
32
  a = @@global_section_number.split(".")
33
33
  a.push("1")
34
34
  @@global_section_number = a.join(".")
35
35
 
36
- else # previous_level > level
36
+ else # level < previous_level
37
37
 
38
38
  a = @@global_section_number.split(".")
39
- a.pop
39
+ delta = previous_level - level
40
+ a.pop(delta)
41
+ @@global_section_number = a.join(".")
42
+ # increment
43
+ a = @@global_section_number.split(".")
44
+ a[-1] = (a[-1].to_i() +1).to_s
40
45
  @@global_section_number = a.join(".")
41
46
  end
42
47
  end
@@ -59,4 +64,8 @@ class Heading < Paragraph
59
64
  s += "&para;</a></h#{headingLevel}>"
60
65
  return s
61
66
  end
67
+
68
+ def self.reset_global_section_number
69
+ @@global_section_number = ""
70
+ end
62
71
  end
@@ -21,7 +21,8 @@ class Image < DocItem
21
21
  @@htmlTableRenderInProgress = false
22
22
  end
23
23
 
24
- s += "<p style=\"margin-top: 15px;\"><img src=\"#{@path}\" alt=\"#{@text}\">"
24
+ s += "<p style=\"margin-top: 15px;\"><img src=\"#{@path}\" alt=\"#{@text}\" "
25
+ s += "href=\"javascript:void(0)\" onclick=\"image_OnClick(this)\">"
25
26
  return s
26
27
  end
27
28
  end
@@ -0,0 +1,22 @@
1
+ require_relative "doc_item"
2
+
3
+ class TodoBlock < DocItem
4
+
5
+ attr_accessor :text
6
+
7
+ def initialize(text)
8
+ @text = text
9
+ end
10
+
11
+ def to_html
12
+ s = ''
13
+ f_text = format_string(@text)
14
+ if @@htmlTableRenderInProgress
15
+ s += "</table>\n"
16
+ @@htmlTableRenderInProgress = false
17
+ end
18
+
19
+ s += "<div class=\"todoblock\"><p>#{f_text}</div>\n"
20
+ return s
21
+ end
22
+ end
@@ -34,6 +34,7 @@ class Index < BaseDocument
34
34
  s += "\t\t<th>Items<br>w/ Downlinks</th>\n"
35
35
  s += "\t\t<th>Covered<br>by Tests</th>\n"
36
36
  s += "\t\t<th>Duplicated<br>ids</th>\n"
37
+ s += "\t\t<th>TODOs</th>\n"
37
38
  s += "\t\t<th>Last Used<br>id</th>\n"
38
39
  s += "</thead>\n"
39
40
  html_rows.append s
@@ -47,7 +48,27 @@ class Index < BaseDocument
47
48
  s += "\t\t<td class=\"item_id\" style='width: 7%;'>#{doc.items_with_uplinks_number.to_s}</td>\n"
48
49
  s += "\t\t<td class=\"item_id\" style='width: 7%;'>#{doc.items_with_downlinks_number.to_s}</td>\n"
49
50
  s += "\t\t<td class=\"item_id\" style='width: 7%;'>#{doc.items_with_coverage_number.to_s}</td>\n"
50
- s += "\t\t<td class=\"item_id\" style='width: 7%;'>#{doc.duplicated_ids_number.to_s}</td>\n"
51
+
52
+ if doc.duplicated_ids_number >0
53
+ s += "\t\t<td class=\"item_id\" style='width: 7%; background-color: #fcc;'>"
54
+ s += "<div id=\"DL_#{doc.id}\" style=\"display: block;\">"
55
+ s += "<a href=\"#\" onclick=\"downlink_OnClick(this.parentElement); return false;\" class=\"external\">#{doc.duplicated_ids_number.to_s}</a>"
56
+ s += "</div>"
57
+ s += "<div id=\"DLS_#{doc.id}\" style=\"display: none;\">"
58
+ doc.duplicates_list.each do |lnk|
59
+ s += "\t\t\t<a href=\"./specifications/#{doc.id}/#{doc.id}.html##{lnk.id}\" class=\"external\">#{lnk.id}</a>\n<br>"
60
+ end
61
+ s += "</div>"
62
+ s += "</td>\n"
63
+ else
64
+ s += "\t\t<td class=\"item_id\" style='width: 7%;'>#{doc.duplicated_ids_number.to_s}</td>\n"
65
+ end
66
+ if doc.todo_blocks.length >0
67
+ color = "background-color: #fcc;"
68
+ else
69
+ color = ""
70
+ end
71
+ s += "\t\t<td class=\"item_id\" style='width: 7%; #{color}'>#{doc.todo_blocks.length.to_s}</td>\n"
51
72
  s += "\t\t<td class=\"item_id\" style='width: 7%;'>#{doc.last_used_id.to_s}</td>\n"
52
73
  s += "</tr>\n"
53
74
  html_rows.append s
@@ -5,11 +5,13 @@ class Specification < BaseDocument
5
5
  attr_accessor :up_link_doc_id
6
6
  attr_accessor :dictionary
7
7
  attr_accessor :controlled_items
8
+ attr_accessor :todo_blocks
8
9
 
9
10
  attr_accessor :items_with_uplinks_number
10
11
  attr_accessor :items_with_downlinks_number
11
12
  attr_accessor :items_with_coverage_number
12
13
  attr_accessor :duplicated_ids_number
14
+ attr_accessor :duplicates_list
13
15
  attr_accessor :last_used_id
14
16
  attr_accessor :last_used_id_number
15
17
 
@@ -21,6 +23,8 @@ class Specification < BaseDocument
21
23
  @headings = Array.new
22
24
  @controlled_items = Array.new
23
25
  @dictionary = Hash.new
26
+ @duplicates_list = Array.new
27
+ @todo_blocks = Array.new
24
28
 
25
29
  @items_with_uplinks_number = 0
26
30
  @items_with_downlinks_number = 0
@@ -137,15 +137,20 @@ class Project
137
137
  #puts "Link: #{doc_A.id} - #{doc_B.id}"
138
138
  bottom_document.controlled_items.each do |item|
139
139
 
140
- if top_document.dictionary.has_key?(item.up_link.to_s)
141
-
142
- topItem = top_document.dictionary[item.up_link.to_s]
143
-
144
- unless topItem.down_links
145
- topItem.down_links = Array.new
146
- top_document.items_with_downlinks_number += 1 # for statistics
140
+ if item.up_link_ids
141
+ item.up_link_ids.each do |up_lnk|
142
+
143
+ if top_document.dictionary.has_key?(up_lnk.to_s)
144
+
145
+ topItem = top_document.dictionary[up_lnk.to_s]
146
+
147
+ unless topItem.down_links
148
+ topItem.down_links = Array.new
149
+ top_document.items_with_downlinks_number += 1 # for statistics
150
+ end
151
+ topItem.down_links.append(item)
152
+ end
147
153
  end
148
- topItem.down_links.append(item)
149
154
  end
150
155
  end
151
156
  # create treceability document
@@ -2,6 +2,7 @@
2
2
  <html lang="en">
3
3
  <head>
4
4
  <meta charset="utf-8" />
5
+ <title>{{DOCUMENT_TITLE}}</title>
5
6
  <!-- CSS -->
6
7
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
7
8
  <style>
@@ -144,6 +145,25 @@
144
145
  margin-top: 4px;
145
146
  margin-bottom: 4px;
146
147
  }
148
+ div.todoblock {
149
+ display: block;
150
+ background:#fcc;
151
+ border-left: 3px double #bbb;
152
+ font-style: italic;
153
+ padding: 4px 1em 4px 4px;
154
+ margin-top: 4px;
155
+ margin-bottom: 4px;
156
+ }
157
+ img:hover{
158
+ transition: 0.3s;
159
+ }
160
+ img{
161
+ opacity: 0.9;
162
+ cursor: pointer;
163
+ }
164
+ #modal_image_id{
165
+ cursor: default;
166
+ }
147
167
  #nav_pane{
148
168
  flex-shrink: 0;
149
169
  padding: 16px 8px 2px 8px;
@@ -164,6 +184,7 @@
164
184
  overflow: hidden;
165
185
  position: fixed;
166
186
  width: 100%;
187
+ z-index: 1;
167
188
  }
168
189
  #top_nav a {
169
190
  float: left;
@@ -191,7 +212,67 @@
191
212
  background-color: #169;
192
213
  color: white;
193
214
  }
194
-
215
+ .modal {
216
+ display: none; /* Hidden by default */
217
+ position: fixed; /* Stay in place */
218
+ z-index: 1; /* Sit on top */
219
+ padding-top: 100px; /* Location of the box */
220
+ left: 0;
221
+ top: 0;
222
+ width: 100%; /* Full width */
223
+ height: 100%; /* Full height */
224
+ overflow: auto; /* Enable scroll if needed */
225
+ background-color: rgb(0,0,0); /* Fallback color */
226
+ background-color: rgba(0,0,0,0.9); /* Black w/ opacity */
227
+ }
228
+ .modal_image {
229
+ margin: auto;
230
+ display: block;
231
+ width: 97%;
232
+ /*max-width: 700px;*/
233
+ }
234
+ #modal_image_caption {
235
+ margin: auto;
236
+ display: block;
237
+ width: 80%;
238
+ max-width: 700px;
239
+ text-align: center;
240
+ color: #ccc;
241
+ padding: 10px 0;
242
+ height: 150px;
243
+ }
244
+ .modal_image, #modal_image_caption {
245
+ animation-name: zoom;
246
+ animation-duration: 0.6s;
247
+ }
248
+ @keyframes zoom {
249
+ from {transform: scale(0.1)}
250
+ to {transform: scale(1)}
251
+ }
252
+ .modal_close_btn {
253
+ position: absolute;
254
+ top: 15px;
255
+ right: 35px;
256
+ color: #f1f1f1;
257
+ font-size: 30px;
258
+ font-weight: bold;
259
+ transition: 0.3s;
260
+ }
261
+ .modal_close_btn:hover,
262
+ .modal_close_btn:focus {
263
+ color: #bbb;
264
+ text-decoration: none;
265
+ cursor: pointer;
266
+ }
267
+ #footer {
268
+ clear: both;
269
+ border-top: 1px solid #bbb;
270
+ font-size: 0.9em;
271
+ color: #aaa;
272
+ padding: 5px;
273
+ text-align:center;
274
+ background:#fff;
275
+ }
195
276
  </style>
196
277
  <script>
197
278
  function openNav() {
@@ -221,11 +302,36 @@ function downlink_OnClick(clicked){
221
302
  required_id = "DLS_" + id_parts[1];
222
303
  document.getElementById(required_id).style.display = 'block';
223
304
  }
305
+
306
+ function navigate_to_home(){
307
+ if (document.title != "Document Index")
308
+ {
309
+ window.location.href = "./../../index.html";
310
+ }
311
+ }
312
+
313
+ // Modal window for image zoom
314
+ function image_OnClick(clicked){
315
+
316
+ var modal = document.getElementById('image_modal_div');
317
+ var modalImg = document.getElementById("modal_image_id");
318
+ var captionText = document.getElementById("modal_image_caption");
319
+
320
+ modal.style.display = "block";
321
+ modalImg.src = clicked.src;
322
+ captionText.innerHTML = clicked.alt;
323
+ }
324
+
325
+ function modal_close_OnClick(clicked){
326
+ var modal = document.getElementById('image_modal_div');
327
+ modal.style.display = "none";
328
+ }
329
+
224
330
  </script>
225
331
  </head>
226
332
  <body>
227
333
  <div id="top_nav">
228
- <a href="./../../index.html"><span><i class="fa fa-home" aria-hidden="true"></i></span>&nbsp;Home</a>
334
+ <a href="javascript:void(0)" onclick="navigate_to_home()"><span><i class="fa fa-home" aria-hidden="true"></i></span>&nbsp;Home</a>
229
335
  <!--a href="javascript:void(0)"> About</a-->
230
336
  <a class="split">{{DOCUMENT_TITLE}}</a>
231
337
  </div>
@@ -237,5 +343,14 @@ function downlink_OnClick(clicked){
237
343
  {{CONTENT}}
238
344
  </div>
239
345
  </div>
346
+ <!-- The modal window for image zoom -->
347
+ <div id="image_modal_div" class="modal">
348
+ <span class="modal_close_btn" href="javascript:void(0)" onclick="modal_close_OnClick(this)">&times;</span>
349
+ <img class="modal_image" id="modal_image_id">
350
+ <div id="modal_image_caption"></div>
351
+ </div>
352
+ <div id="footer">
353
+ Powered by <a target="_blank" rel="noopener" href="https://www.almirah.site/">Almirah Framework</a>
354
+ </div>
240
355
  </body>
241
356
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: Almirah
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.3
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-03-13 00:00:00.000000000 Z
11
+ date: 2024-03-30 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: The software part of the Almirah framework
14
14
  email: oleksandr.ivanov.development@gmail.com
@@ -31,6 +31,7 @@ files:
31
31
  - lib/almirah/doc_items/markdown_table.rb
32
32
  - lib/almirah/doc_items/paragraph.rb
33
33
  - lib/almirah/doc_items/text_line.rb
34
+ - lib/almirah/doc_items/todo_block.rb
34
35
  - lib/almirah/doc_types/base_document.rb
35
36
  - lib/almirah/doc_types/coverage.rb
36
37
  - lib/almirah/doc_types/index.rb