Almirah 0.1.1 → 0.1.3

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 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