Almirah 0.2.0 → 0.2.1
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 +3 -333
- data/lib/almirah/doc_items/controlled_paragraph.rb +3 -1
- data/lib/almirah/doc_items/controlled_table.rb +1 -1
- data/lib/almirah/doc_items/heading.rb +7 -2
- data/lib/almirah/doc_items/markdown_list.rb +5 -2
- data/lib/almirah/doc_parser.rb +334 -0
- data/lib/almirah/doc_types/base_document.rb +1 -6
- data/lib/almirah/doc_types/coverage.rb +1 -5
- data/lib/almirah/doc_types/index.rb +1 -3
- data/lib/almirah/doc_types/persistent_document.rb +20 -0
- data/lib/almirah/doc_types/protocol.rb +3 -15
- data/lib/almirah/doc_types/specification.rb +3 -11
- data/lib/almirah/doc_types/traceability.rb +1 -4
- data/lib/almirah/dom/document.rb +1 -1
- data/lib/almirah/project.rb +4 -4
- data/lib/almirah/search/specifications_db.rb +30 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: da8737eaa32966b6559639becfd0737c25394340b1f32cc682a1063a78205190
|
4
|
+
data.tar.gz: 40914f94ceda02630a170c04965d65a83a5073db6d5aa32eb678caaf2823ee96
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a3f545f59badec9c749b0b9104eb9a2ae7737bd47f2c36a1c5d2b743df8a6931654500b798b6309b3a96368b926d64e8dd52f4faae4fd83affe453a861cbad9e
|
7
|
+
data.tar.gz: eeb982a3da8bbba0dadf6832fc9491d334e31b06aaf8749921e8a4bb0dc6fa9b94a8a249b05c883f3a288b242550be46342a9bccdec11b809910caaa5644930c
|
data/lib/almirah/doc_fabric.rb
CHANGED
@@ -1,20 +1,7 @@
|
|
1
1
|
require_relative 'doc_types/base_document'
|
2
2
|
require_relative 'doc_types/specification'
|
3
3
|
require_relative 'doc_types/protocol'
|
4
|
-
require_relative '
|
5
|
-
require_relative 'doc_items/doc_item'
|
6
|
-
require_relative 'doc_items/heading'
|
7
|
-
require_relative 'doc_items/paragraph'
|
8
|
-
require_relative 'doc_items/blockquote'
|
9
|
-
require_relative 'doc_items/code_block'
|
10
|
-
require_relative 'doc_items/todo_block'
|
11
|
-
require_relative 'doc_items/controlled_paragraph'
|
12
|
-
require_relative 'doc_items/markdown_table'
|
13
|
-
require_relative 'doc_items/controlled_table'
|
14
|
-
require_relative 'doc_items/image'
|
15
|
-
require_relative 'doc_items/markdown_list'
|
16
|
-
require_relative 'doc_items/doc_footer'
|
17
|
-
|
4
|
+
require_relative 'doc_parser'
|
18
5
|
require_relative 'dom/document'
|
19
6
|
|
20
7
|
class DocFabric
|
@@ -45,332 +32,15 @@ class DocFabric
|
|
45
32
|
end
|
46
33
|
|
47
34
|
def self.parse_document(doc)
|
48
|
-
temp_md_table = nil
|
49
|
-
temp_md_list = nil
|
50
|
-
temp_code_block = nil
|
51
35
|
|
52
36
|
file = File.open(doc.path)
|
53
37
|
file_lines = file.readlines
|
54
38
|
file.close
|
55
39
|
|
56
|
-
|
57
|
-
if s.lstrip != ''
|
58
|
-
if res = /^(\#{1,})\s(.*)/.match(s) # Heading
|
59
|
-
|
60
|
-
if temp_md_table
|
61
|
-
doc.items.append temp_md_table
|
62
|
-
temp_md_table = nil
|
63
|
-
end
|
64
|
-
if temp_md_list
|
65
|
-
doc.items.append temp_md_list
|
66
|
-
temp_md_list = nil
|
67
|
-
end
|
68
|
-
|
69
|
-
level = res[1].length
|
70
|
-
value = res[2]
|
71
|
-
|
72
|
-
if level == 1 && doc.title == ''
|
73
|
-
doc.title = value
|
74
|
-
level = 0 # Doc Title is a Root
|
75
|
-
Heading.reset_global_section_number
|
76
|
-
end
|
77
|
-
|
78
|
-
item = Heading.new(value, level)
|
79
|
-
item.parent_doc = doc
|
80
|
-
doc.items.append(item)
|
81
|
-
doc.headings.append(item)
|
82
|
-
|
83
|
-
elsif res = /^%\s(.*)/.match(s) # Pandoc Document Title
|
84
|
-
|
85
|
-
title = res[1]
|
86
|
-
|
87
|
-
if doc.title == ''
|
88
|
-
doc.title = title
|
89
|
-
Heading.reset_global_section_number
|
90
|
-
end
|
91
|
-
|
92
|
-
item = Heading.new(title, 0)
|
93
|
-
item.parent_doc = doc
|
94
|
-
doc.items.append(item)
|
95
|
-
doc.headings.append(item)
|
96
|
-
|
97
|
-
Heading.reset_global_section_number # Pandoc Document Title is not a section, so it shall not be taken into account in numbering
|
98
|
-
|
99
|
-
elsif res = /^\[(\S*)\]\s+(.*)/.match(s) # Controlled Paragraph
|
100
|
-
|
101
|
-
if temp_md_table
|
102
|
-
doc.items.append temp_md_table
|
103
|
-
temp_md_table = nil
|
104
|
-
end
|
105
|
-
if temp_md_list
|
106
|
-
doc.items.append temp_md_list
|
107
|
-
temp_md_list = nil
|
108
|
-
end
|
109
|
-
|
110
|
-
id = res[1]
|
111
|
-
text = res[2]
|
112
|
-
up_links = nil
|
113
|
-
|
114
|
-
# check if it contains the uplink (one or many)
|
115
|
-
# TODO: check this regular expression
|
116
|
-
first_pos = text.length # for trailing commas
|
117
|
-
tmp = text.scan(/(>\[(?>[^\[\]]|\g<0>)*\])/) # >[SRS-001], >[SYS-002]
|
118
|
-
if tmp.length > 0
|
119
|
-
up_links = []
|
120
|
-
tmp.each do |ul|
|
121
|
-
up_links.append(ul[0])
|
122
|
-
# try to find the real end of text
|
123
|
-
pos = text.index(ul[0])
|
124
|
-
first_pos = pos if pos < first_pos
|
125
|
-
# remove uplink from text
|
126
|
-
text = text.split(ul[0]).join('')
|
127
|
-
end
|
128
|
-
# remove trailing commas and spaces
|
129
|
-
if text.length > first_pos
|
130
|
-
first_pos -= 1
|
131
|
-
text = text[0..first_pos].strip
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
# since we already know id and text
|
136
|
-
item = ControlledParagraph.new(text, id)
|
137
|
-
|
138
|
-
if up_links
|
139
|
-
doc.items_with_uplinks_number += 1 # for statistics
|
140
|
-
up_links.each do |ul|
|
141
|
-
next unless tmp = />\[(\S*)\]$/.match(ul) # >[SRS-001]
|
142
|
-
|
143
|
-
up_link_id = tmp[1]
|
144
|
-
|
145
|
-
item.up_link_ids = [] unless item.up_link_ids
|
146
|
-
|
147
|
-
item.up_link_ids.append(up_link_id)
|
148
|
-
|
149
|
-
if tmp = /^([a-zA-Z]+)-\d+/.match(up_link_id) # SRS
|
150
|
-
doc.up_link_doc_id[tmp[1].downcase.to_s] = tmp[1].downcase # multiple documents could be up-linked
|
151
|
-
end
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
item.parent_doc = doc
|
156
|
-
item.parent_heading = doc.headings[-1]
|
157
|
-
|
158
|
-
doc.items.append(item)
|
159
|
-
# for statistics
|
160
|
-
if doc.dictionary.has_key?(id.to_s)
|
161
|
-
doc.duplicated_ids_number += 1
|
162
|
-
doc.duplicates_list.append(item)
|
163
|
-
else
|
164
|
-
doc.dictionary[id.to_s] = item # for fast search
|
165
|
-
end
|
166
|
-
doc.controlled_items.append(item) # for fast search
|
167
|
-
|
168
|
-
# for statistics
|
169
|
-
n = /\d+/.match(id)[0].to_i
|
170
|
-
if n > doc.last_used_id_number
|
171
|
-
doc.last_used_id = id
|
172
|
-
doc.last_used_id_number = n
|
173
|
-
end
|
174
|
-
|
175
|
-
elsif res = /^!\[(.*)\]\((.*)\)/.match(s) # Image
|
176
|
-
|
177
|
-
if temp_md_table
|
178
|
-
doc.items.append temp_md_table
|
179
|
-
temp_md_table = nil
|
180
|
-
end
|
181
|
-
if temp_md_list
|
182
|
-
doc.items.append temp_md_list
|
183
|
-
temp_md_list = nil
|
184
|
-
end
|
185
|
-
|
186
|
-
img_text = res[1]
|
187
|
-
img_path = res[2]
|
188
|
-
|
189
|
-
item = Image.new(img_text, img_path)
|
190
|
-
item.parent_doc = doc
|
191
|
-
item.parent_heading = doc.headings[-1]
|
192
|
-
|
193
|
-
doc.items.append(item)
|
194
|
-
|
195
|
-
elsif res = /^(\*\s+)(.*)/.match(s) # check if unordered list start
|
40
|
+
DocParser.parse(doc, file_lines)
|
196
41
|
|
197
|
-
if temp_md_table
|
198
|
-
doc.items.append temp_md_table
|
199
|
-
temp_md_table = nil
|
200
|
-
end
|
201
|
-
|
202
|
-
row = res[2]
|
203
|
-
|
204
|
-
if temp_md_list
|
205
|
-
temp_md_list.addRow(s)
|
206
|
-
else
|
207
|
-
item = MarkdownList.new(false)
|
208
|
-
item.addRow(s)
|
209
|
-
item.parent_doc = doc
|
210
|
-
temp_md_list = item
|
211
|
-
end
|
212
|
-
|
213
|
-
elsif res = /^\d[.]\s(.*)/.match(s) # check if ordered list start
|
214
|
-
|
215
|
-
if temp_md_table
|
216
|
-
doc.items.append temp_md_table
|
217
|
-
temp_md_table = nil
|
218
|
-
end
|
219
|
-
|
220
|
-
row = res[1]
|
221
|
-
|
222
|
-
if temp_md_list
|
223
|
-
temp_md_list.addRow(s)
|
224
|
-
else
|
225
|
-
item = MarkdownList.new(true)
|
226
|
-
item.addRow(s)
|
227
|
-
item.parent_doc = doc
|
228
|
-
item.parent_heading = doc.headings[-1]
|
229
|
-
temp_md_list = item
|
230
|
-
end
|
231
|
-
|
232
|
-
elsif s[0] == '|' # check if table
|
233
|
-
|
234
|
-
if temp_md_list
|
235
|
-
doc.items.append temp_md_list
|
236
|
-
temp_md_list = nil
|
237
|
-
end
|
238
|
-
|
239
|
-
if res = /^[|](-{3,})[|]/.match(s) # check if it is a separator first
|
240
|
-
|
241
|
-
if temp_md_table
|
242
|
-
# separator is found after heading - just skip it
|
243
|
-
else
|
244
|
-
# separator out of table scope consider it just as a regular paragraph
|
245
|
-
item = Paragraph.new(s)
|
246
|
-
item.parent_doc = doc
|
247
|
-
item.parent_heading = doc.headings[-1]
|
248
|
-
doc.items.append(item)
|
249
|
-
end
|
250
|
-
|
251
|
-
elsif res = /^[|](.*[|])/.match(s) # check if it looks as a table
|
252
|
-
|
253
|
-
row = res[1]
|
254
|
-
|
255
|
-
if temp_md_table
|
256
|
-
# check if it is a controlled table
|
257
|
-
unless temp_md_table.addRow(row)
|
258
|
-
temp_md_table = ControlledTable.new(temp_md_table, doc)
|
259
|
-
temp_md_table.parent_doc = doc
|
260
|
-
temp_md_table.addRow(row)
|
261
|
-
end
|
262
|
-
else
|
263
|
-
# start table from heading
|
264
|
-
temp_md_table = MarkdownTable.new(row)
|
265
|
-
temp_md_table.parent_doc = doc
|
266
|
-
end
|
267
|
-
end
|
268
|
-
|
269
|
-
elsif res = /^>(.*)/.match(s) # check if blockquote
|
270
|
-
|
271
|
-
if temp_md_table
|
272
|
-
doc.items.append temp_md_table
|
273
|
-
temp_md_table = nil
|
274
|
-
end
|
275
|
-
if temp_md_list
|
276
|
-
doc.items.append temp_md_list
|
277
|
-
temp_md_list = nil
|
278
|
-
end
|
279
|
-
|
280
|
-
item = Blockquote.new(res[1])
|
281
|
-
item.parent_doc = doc
|
282
|
-
item.parent_heading = doc.headings[-1]
|
283
|
-
doc.items.append(item)
|
284
|
-
|
285
|
-
elsif res = /^```(\w*)/.match(s) # check if code block
|
286
|
-
|
287
|
-
if temp_md_table
|
288
|
-
doc.items.append temp_md_table
|
289
|
-
temp_md_table = nil
|
290
|
-
end
|
291
|
-
if temp_md_list
|
292
|
-
doc.items.append temp_md_list
|
293
|
-
temp_md_list = nil
|
294
|
-
end
|
295
|
-
|
296
|
-
suggested_format = ''
|
297
|
-
suggested_format = res[1] if res.length == 2
|
298
|
-
|
299
|
-
if temp_code_block
|
300
|
-
# close already opened block
|
301
|
-
doc.items.append(temp_code_block)
|
302
|
-
temp_code_block = nil
|
303
|
-
else
|
304
|
-
# start code block
|
305
|
-
temp_code_block = CodeBlock.new(suggested_format)
|
306
|
-
temp_code_block.parent_doc = doc
|
307
|
-
end
|
308
|
-
|
309
|
-
elsif res = /^TODO:(.*)/.match(s) # check if TODO block
|
310
|
-
|
311
|
-
if temp_md_table
|
312
|
-
doc.items.append temp_md_table
|
313
|
-
temp_md_table = nil
|
314
|
-
end
|
315
|
-
if temp_md_list
|
316
|
-
doc.items.append temp_md_list
|
317
|
-
temp_md_list = nil
|
318
|
-
end
|
319
|
-
|
320
|
-
text = '**TODO**: ' + res[1]
|
321
|
-
|
322
|
-
item = TodoBlock.new(text)
|
323
|
-
item.parent_doc = doc
|
324
|
-
item.parent_heading = doc.headings[-1]
|
325
|
-
doc.items.append(item)
|
326
|
-
doc.todo_blocks.append(item)
|
327
|
-
|
328
|
-
else # Reqular Paragraph
|
329
|
-
if temp_md_table
|
330
|
-
doc.items.append temp_md_table
|
331
|
-
temp_md_table = nil
|
332
|
-
end
|
333
|
-
if temp_md_list
|
334
|
-
if MarkdownList.unordered_list_item?(s) || MarkdownList.ordered_list_item?(s)
|
335
|
-
temp_md_list.addRow(s)
|
336
|
-
next
|
337
|
-
else
|
338
|
-
doc.items.append temp_md_list
|
339
|
-
temp_md_list = nil
|
340
|
-
end
|
341
|
-
end
|
342
|
-
if temp_code_block
|
343
|
-
temp_code_block.code_lines.append(s)
|
344
|
-
else
|
345
|
-
item = Paragraph.new(s)
|
346
|
-
item.parent_doc = doc
|
347
|
-
item.parent_heading = doc.headings[-1]
|
348
|
-
doc.items.append(item)
|
349
|
-
end
|
350
|
-
end
|
351
|
-
elsif temp_md_list
|
352
|
-
doc.items.append temp_md_list
|
353
|
-
temp_md_list = nil # lists are separated by emty line from each other
|
354
|
-
end
|
355
|
-
end
|
356
|
-
# Finalize non-closed elements
|
357
|
-
if temp_md_table
|
358
|
-
doc.items.append temp_md_table
|
359
|
-
temp_md_table = nil
|
360
|
-
end
|
361
|
-
if temp_md_list
|
362
|
-
doc.items.append temp_md_list
|
363
|
-
temp_md_list = nil
|
364
|
-
end
|
365
|
-
if temp_code_block
|
366
|
-
doc.items.append temp_code_block
|
367
|
-
temp_code_block = nil
|
368
|
-
end
|
369
|
-
# Add footer to close opened tables if any
|
370
|
-
item = DocFooter.new
|
371
|
-
item.parent_doc = doc
|
372
|
-
doc.items.append(item)
|
373
42
|
# Build dom
|
374
43
|
doc.dom = Document.new(doc.headings) if doc.is_a?(Specification)
|
44
|
+
|
375
45
|
end
|
376
46
|
end
|
@@ -7,7 +7,9 @@ class ControlledParagraph < Paragraph
|
|
7
7
|
attr_accessor :down_links
|
8
8
|
attr_accessor :coverage_links
|
9
9
|
|
10
|
-
def initialize(text, id)
|
10
|
+
def initialize(doc, text, id)
|
11
|
+
@parent_doc = doc
|
12
|
+
@parent_heading = doc.headings[-1]
|
11
13
|
@text = text.strip
|
12
14
|
@id = id
|
13
15
|
@up_link_ids = nil
|
@@ -129,7 +129,7 @@ class ControlledTable < DocItem
|
|
129
129
|
# save uplink key but do not rewrite
|
130
130
|
if col.up_link_doc_id != nil
|
131
131
|
|
132
|
-
@parent_doc.
|
132
|
+
@parent_doc.up_link_docs[ col.up_link_doc_id.to_s ] = col.up_link_doc_id
|
133
133
|
|
134
134
|
# save reference to the test step
|
135
135
|
new_row.up_link = col.up_link
|
@@ -8,7 +8,8 @@ class Heading < Paragraph
|
|
8
8
|
|
9
9
|
@@global_section_number = ""
|
10
10
|
|
11
|
-
def initialize(text, level)
|
11
|
+
def initialize(doc, text, level)
|
12
|
+
@parent_doc = doc
|
12
13
|
@text = text
|
13
14
|
@level = level
|
14
15
|
|
@@ -51,7 +52,11 @@ class Heading < Paragraph
|
|
51
52
|
end
|
52
53
|
|
53
54
|
def get_section_info
|
54
|
-
|
55
|
+
if level == 0 # Doc Title
|
56
|
+
s = @text
|
57
|
+
else
|
58
|
+
s = @section_number + " " + @text
|
59
|
+
end
|
55
60
|
end
|
56
61
|
|
57
62
|
def get_anchor_text()
|
@@ -10,7 +10,10 @@ class MarkdownList < DocItem
|
|
10
10
|
|
11
11
|
@@lists_stack = Array.new
|
12
12
|
|
13
|
-
def initialize(is_ordered)
|
13
|
+
def initialize(doc, is_ordered)
|
14
|
+
@parent_doc = doc
|
15
|
+
@parent_heading = doc.headings[-1]
|
16
|
+
|
14
17
|
@rows = Array.new
|
15
18
|
@is_ordered = is_ordered
|
16
19
|
@current_nesting_level = 0
|
@@ -30,7 +33,7 @@ class MarkdownList < DocItem
|
|
30
33
|
|
31
34
|
prev_lists_stack_item = @@lists_stack[-1]
|
32
35
|
# the following line pushes new list to the lists_stack in the constructor!
|
33
|
-
nested_list = MarkdownList.new( MarkdownList.ordered_list_item?(raw_text) )
|
36
|
+
nested_list = MarkdownList.new( @parent_doc, MarkdownList.ordered_list_item?(raw_text) )
|
34
37
|
nested_list.current_nesting_level = @current_nesting_level + 1
|
35
38
|
nested_list.indent_position = pos
|
36
39
|
|
@@ -0,0 +1,334 @@
|
|
1
|
+
require_relative 'doc_items/text_line'
|
2
|
+
require_relative 'doc_items/doc_item'
|
3
|
+
require_relative 'doc_items/heading'
|
4
|
+
require_relative 'doc_items/paragraph'
|
5
|
+
require_relative 'doc_items/blockquote'
|
6
|
+
require_relative 'doc_items/code_block'
|
7
|
+
require_relative 'doc_items/todo_block'
|
8
|
+
require_relative 'doc_items/controlled_paragraph'
|
9
|
+
require_relative 'doc_items/markdown_table'
|
10
|
+
require_relative 'doc_items/controlled_table'
|
11
|
+
require_relative 'doc_items/image'
|
12
|
+
require_relative 'doc_items/markdown_list'
|
13
|
+
require_relative 'doc_items/doc_footer'
|
14
|
+
|
15
|
+
class DocParser
|
16
|
+
def self.parse(doc, text_lines)
|
17
|
+
temp_md_table = nil
|
18
|
+
temp_md_list = nil
|
19
|
+
temp_code_block = nil
|
20
|
+
# restart section numbering for each new document
|
21
|
+
Heading.reset_global_section_number
|
22
|
+
|
23
|
+
text_lines.each do |s|
|
24
|
+
if s.lstrip != ''
|
25
|
+
if res = /^(\#{1,})\s(.*)/.match(s) # Heading
|
26
|
+
|
27
|
+
if temp_md_table
|
28
|
+
doc.items.append temp_md_table
|
29
|
+
temp_md_table = nil
|
30
|
+
end
|
31
|
+
if temp_md_list
|
32
|
+
doc.items.append temp_md_list
|
33
|
+
temp_md_list = nil
|
34
|
+
end
|
35
|
+
|
36
|
+
level = res[1].length
|
37
|
+
value = res[2]
|
38
|
+
|
39
|
+
if level == 1 && doc.title == ''
|
40
|
+
doc.title = value
|
41
|
+
end
|
42
|
+
|
43
|
+
item = Heading.new(doc, value, level)
|
44
|
+
doc.items.append(item)
|
45
|
+
doc.headings.append(item)
|
46
|
+
|
47
|
+
elsif res = /^%\s(.*)/.match(s) # Pandoc Document Title
|
48
|
+
|
49
|
+
title = res[1]
|
50
|
+
|
51
|
+
if doc.title == ''
|
52
|
+
doc.title = title
|
53
|
+
end
|
54
|
+
|
55
|
+
item = Heading.new(doc, title, 0)
|
56
|
+
doc.items.append(item)
|
57
|
+
doc.headings.append(item)
|
58
|
+
|
59
|
+
elsif res = /^\[(\S*)\]\s+(.*)/.match(s) # Controlled Paragraph
|
60
|
+
|
61
|
+
if temp_md_table
|
62
|
+
doc.items.append temp_md_table
|
63
|
+
temp_md_table = nil
|
64
|
+
end
|
65
|
+
if temp_md_list
|
66
|
+
doc.items.append temp_md_list
|
67
|
+
temp_md_list = nil
|
68
|
+
end
|
69
|
+
|
70
|
+
id = res[1].upcase
|
71
|
+
text = res[2]
|
72
|
+
up_links = nil
|
73
|
+
|
74
|
+
# check if it contains the uplink (one or many)
|
75
|
+
# TODO: check this regular expression
|
76
|
+
first_pos = text.length # for trailing commas
|
77
|
+
tmp = text.scan(/(>\[(?>[^\[\]]|\g<0>)*\])/) # >[SRS-001], >[SYS-002]
|
78
|
+
if tmp.length > 0
|
79
|
+
up_links = []
|
80
|
+
tmp.each do |ul|
|
81
|
+
lnk = ul[0]
|
82
|
+
# do not add links for the self document
|
83
|
+
doc_id = /([a-zA-Z]+)-\d+/.match(lnk) # SRS
|
84
|
+
if (doc_id) and (doc_id[1].downcase != doc.id.downcase)
|
85
|
+
up_links << lnk.upcase
|
86
|
+
end
|
87
|
+
# try to find the real end of text
|
88
|
+
pos = text.index(lnk)
|
89
|
+
first_pos = pos if pos < first_pos
|
90
|
+
# remove uplink from text
|
91
|
+
text = text.split(lnk, 1).join('')
|
92
|
+
end
|
93
|
+
# remove trailing commas and spaces
|
94
|
+
if text.length > first_pos
|
95
|
+
first_pos -= 1
|
96
|
+
text = text[0..first_pos].strip
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# since we already know id and text
|
101
|
+
item = ControlledParagraph.new(doc, text, id)
|
102
|
+
|
103
|
+
if up_links
|
104
|
+
up_links.uniq! #remove duplicates
|
105
|
+
doc.items_with_uplinks_number += 1 # for statistics
|
106
|
+
up_links.each do |ul|
|
107
|
+
next unless tmp = />\[(\S*)\]$/.match(ul) # >[SRS-001]
|
108
|
+
|
109
|
+
up_link_id = tmp[1]
|
110
|
+
|
111
|
+
item.up_link_ids = [] unless item.up_link_ids
|
112
|
+
|
113
|
+
item.up_link_ids.append(up_link_id)
|
114
|
+
|
115
|
+
if tmp = /^([a-zA-Z]+)-\d+/.match(up_link_id) # SRS
|
116
|
+
doc.up_link_docs[tmp[1].downcase.to_s] = tmp[1].downcase # multiple documents could be up-linked
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
doc.items.append(item)
|
122
|
+
# for statistics
|
123
|
+
if doc.dictionary.has_key?(id.to_s)
|
124
|
+
doc.duplicated_ids_number += 1
|
125
|
+
doc.duplicates_list.append(item)
|
126
|
+
else
|
127
|
+
doc.dictionary[id.to_s] = item # for fast search
|
128
|
+
end
|
129
|
+
doc.controlled_items.append(item) # for fast search
|
130
|
+
|
131
|
+
# for statistics
|
132
|
+
n = /\d+/.match(id)[0].to_i
|
133
|
+
if n > doc.last_used_id_number
|
134
|
+
doc.last_used_id = id
|
135
|
+
doc.last_used_id_number = n
|
136
|
+
end
|
137
|
+
|
138
|
+
elsif res = /^!\[(.*)\]\((.*)\)/.match(s) # Image
|
139
|
+
|
140
|
+
if temp_md_table
|
141
|
+
doc.items.append temp_md_table
|
142
|
+
temp_md_table = nil
|
143
|
+
end
|
144
|
+
if temp_md_list
|
145
|
+
doc.items.append temp_md_list
|
146
|
+
temp_md_list = nil
|
147
|
+
end
|
148
|
+
|
149
|
+
img_text = res[1]
|
150
|
+
img_path = res[2]
|
151
|
+
|
152
|
+
item = Image.new(img_text, img_path)
|
153
|
+
item.parent_doc = doc
|
154
|
+
item.parent_heading = doc.headings[-1]
|
155
|
+
|
156
|
+
doc.items.append(item)
|
157
|
+
|
158
|
+
elsif res = /^(\*\s+)(.*)/.match(s) # check if unordered list start
|
159
|
+
|
160
|
+
if temp_md_table
|
161
|
+
doc.items.append temp_md_table
|
162
|
+
temp_md_table = nil
|
163
|
+
end
|
164
|
+
|
165
|
+
row = res[2]
|
166
|
+
|
167
|
+
if temp_md_list
|
168
|
+
temp_md_list.addRow(s)
|
169
|
+
else
|
170
|
+
item = MarkdownList.new(doc, false)
|
171
|
+
item.addRow(s)
|
172
|
+
temp_md_list = item
|
173
|
+
end
|
174
|
+
|
175
|
+
elsif res = /^\d[.]\s(.*)/.match(s) # check if ordered list start
|
176
|
+
|
177
|
+
if temp_md_table
|
178
|
+
doc.items.append temp_md_table
|
179
|
+
temp_md_table = nil
|
180
|
+
end
|
181
|
+
|
182
|
+
row = res[1]
|
183
|
+
|
184
|
+
if temp_md_list
|
185
|
+
temp_md_list.addRow(s)
|
186
|
+
else
|
187
|
+
item = MarkdownList.new(doc, true)
|
188
|
+
item.addRow(s)
|
189
|
+
temp_md_list = item
|
190
|
+
end
|
191
|
+
|
192
|
+
elsif s[0] == '|' # check if table
|
193
|
+
|
194
|
+
if temp_md_list
|
195
|
+
doc.items.append temp_md_list
|
196
|
+
temp_md_list = nil
|
197
|
+
end
|
198
|
+
|
199
|
+
if res = /^[|](-{3,})[|]/.match(s) # check if it is a separator first
|
200
|
+
|
201
|
+
if temp_md_table
|
202
|
+
# separator is found after heading - just skip it
|
203
|
+
else
|
204
|
+
# separator out of table scope consider it just as a regular paragraph
|
205
|
+
item = Paragraph.new(s)
|
206
|
+
item.parent_doc = doc
|
207
|
+
item.parent_heading = doc.headings[-1]
|
208
|
+
doc.items.append(item)
|
209
|
+
end
|
210
|
+
|
211
|
+
elsif res = /^[|](.*[|])/.match(s) # check if it looks as a table
|
212
|
+
|
213
|
+
row = res[1]
|
214
|
+
|
215
|
+
if temp_md_table
|
216
|
+
# check if it is a controlled table
|
217
|
+
unless temp_md_table.addRow(row)
|
218
|
+
temp_md_table = ControlledTable.new(temp_md_table, doc)
|
219
|
+
temp_md_table.parent_doc = doc
|
220
|
+
temp_md_table.addRow(row)
|
221
|
+
end
|
222
|
+
else
|
223
|
+
# start table from heading
|
224
|
+
temp_md_table = MarkdownTable.new(row)
|
225
|
+
temp_md_table.parent_doc = doc
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
elsif res = /^>(.*)/.match(s) # check if blockquote
|
230
|
+
|
231
|
+
if temp_md_table
|
232
|
+
doc.items.append temp_md_table
|
233
|
+
temp_md_table = nil
|
234
|
+
end
|
235
|
+
if temp_md_list
|
236
|
+
doc.items.append temp_md_list
|
237
|
+
temp_md_list = nil
|
238
|
+
end
|
239
|
+
|
240
|
+
item = Blockquote.new(res[1])
|
241
|
+
item.parent_doc = doc
|
242
|
+
item.parent_heading = doc.headings[-1]
|
243
|
+
doc.items.append(item)
|
244
|
+
|
245
|
+
elsif res = /^```(\w*)/.match(s) # check if code block
|
246
|
+
|
247
|
+
if temp_md_table
|
248
|
+
doc.items.append temp_md_table
|
249
|
+
temp_md_table = nil
|
250
|
+
end
|
251
|
+
if temp_md_list
|
252
|
+
doc.items.append temp_md_list
|
253
|
+
temp_md_list = nil
|
254
|
+
end
|
255
|
+
|
256
|
+
suggested_format = ''
|
257
|
+
suggested_format = res[1] if res.length == 2
|
258
|
+
|
259
|
+
if temp_code_block
|
260
|
+
# close already opened block
|
261
|
+
doc.items.append(temp_code_block)
|
262
|
+
temp_code_block = nil
|
263
|
+
else
|
264
|
+
# start code block
|
265
|
+
temp_code_block = CodeBlock.new(suggested_format)
|
266
|
+
temp_code_block.parent_doc = doc
|
267
|
+
end
|
268
|
+
|
269
|
+
elsif res = /^TODO:(.*)/.match(s) # check if TODO block
|
270
|
+
|
271
|
+
if temp_md_table
|
272
|
+
doc.items.append temp_md_table
|
273
|
+
temp_md_table = nil
|
274
|
+
end
|
275
|
+
if temp_md_list
|
276
|
+
doc.items.append temp_md_list
|
277
|
+
temp_md_list = nil
|
278
|
+
end
|
279
|
+
|
280
|
+
text = '**TODO**: ' + res[1]
|
281
|
+
|
282
|
+
item = TodoBlock.new(text)
|
283
|
+
item.parent_doc = doc
|
284
|
+
item.parent_heading = doc.headings[-1]
|
285
|
+
doc.items.append(item)
|
286
|
+
doc.todo_blocks.append(item)
|
287
|
+
|
288
|
+
else # Reqular Paragraph
|
289
|
+
if temp_md_table
|
290
|
+
doc.items.append temp_md_table
|
291
|
+
temp_md_table = nil
|
292
|
+
end
|
293
|
+
if temp_md_list
|
294
|
+
if MarkdownList.unordered_list_item?(s) || MarkdownList.ordered_list_item?(s)
|
295
|
+
temp_md_list.addRow(s)
|
296
|
+
next
|
297
|
+
else
|
298
|
+
doc.items.append temp_md_list
|
299
|
+
temp_md_list = nil
|
300
|
+
end
|
301
|
+
end
|
302
|
+
if temp_code_block
|
303
|
+
temp_code_block.code_lines.append(s)
|
304
|
+
else
|
305
|
+
item = Paragraph.new(s)
|
306
|
+
item.parent_doc = doc
|
307
|
+
item.parent_heading = doc.headings[-1]
|
308
|
+
doc.items.append(item)
|
309
|
+
end
|
310
|
+
end
|
311
|
+
elsif temp_md_list
|
312
|
+
doc.items.append temp_md_list
|
313
|
+
temp_md_list = nil # lists are separated by emty line from each other
|
314
|
+
end
|
315
|
+
end
|
316
|
+
# Finalize non-closed elements
|
317
|
+
if temp_md_table
|
318
|
+
doc.items.append temp_md_table
|
319
|
+
temp_md_table = nil
|
320
|
+
end
|
321
|
+
if temp_md_list
|
322
|
+
doc.items.append temp_md_list
|
323
|
+
temp_md_list = nil
|
324
|
+
end
|
325
|
+
if temp_code_block
|
326
|
+
doc.items.append temp_code_block
|
327
|
+
temp_code_block = nil
|
328
|
+
end
|
329
|
+
# Add footer to close opened tables if any
|
330
|
+
item = DocFooter.new
|
331
|
+
item.parent_doc = doc
|
332
|
+
doc.items.append(item)
|
333
|
+
end
|
334
|
+
end
|
@@ -1,16 +1,11 @@
|
|
1
1
|
|
2
2
|
class BaseDocument
|
3
3
|
|
4
|
-
attr_accessor :path
|
5
|
-
attr_accessor :items
|
6
|
-
attr_accessor :headings
|
7
4
|
attr_accessor :title
|
8
5
|
attr_accessor :id
|
9
6
|
attr_accessor :dom
|
10
7
|
|
11
|
-
def initialize(
|
12
|
-
|
13
|
-
@path = fele_path
|
8
|
+
def initialize()
|
14
9
|
@items = Array.new
|
15
10
|
@headings = Array.new
|
16
11
|
@title = ""
|
@@ -4,16 +4,12 @@ class Coverage < BaseDocument
|
|
4
4
|
|
5
5
|
attr_accessor :top_doc
|
6
6
|
attr_accessor :bottom_doc
|
7
|
-
attr_accessor :items
|
8
7
|
|
9
8
|
def initialize(top_doc)
|
10
|
-
|
9
|
+
super()
|
11
10
|
@top_doc = top_doc
|
12
11
|
@bottom_doc = bottom_doc
|
13
12
|
|
14
|
-
@items = Array.new
|
15
|
-
@headings = Array.new
|
16
|
-
|
17
13
|
@id = top_doc.id + "-" + "tests"
|
18
14
|
@title = "Coverage Matrix: " + @id
|
19
15
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require_relative "base_document"
|
2
|
+
|
3
|
+
class PersistentDocument < BaseDocument
|
4
|
+
|
5
|
+
attr_accessor :path
|
6
|
+
attr_accessor :items
|
7
|
+
attr_accessor :controlled_items
|
8
|
+
attr_accessor :headings
|
9
|
+
attr_accessor :up_link_docs
|
10
|
+
|
11
|
+
def initialize(fele_path)
|
12
|
+
super()
|
13
|
+
@path = fele_path
|
14
|
+
@items = []
|
15
|
+
@controlled_items = []
|
16
|
+
@headings = []
|
17
|
+
@up_link_docs = {}
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -1,22 +1,10 @@
|
|
1
|
-
require_relative "
|
1
|
+
require_relative "persistent_document"
|
2
2
|
|
3
|
-
class Protocol <
|
4
|
-
|
5
|
-
attr_accessor :up_link_doc_id
|
6
|
-
#attr_accessor :dictionary
|
7
|
-
attr_accessor :controlled_items
|
3
|
+
class Protocol < PersistentDocument
|
8
4
|
|
9
5
|
def initialize(fele_path)
|
10
|
-
|
11
|
-
@path = fele_path
|
12
|
-
@title = ""
|
13
|
-
@items = Array.new
|
14
|
-
@headings = Array.new
|
15
|
-
@controlled_items = Array.new
|
16
|
-
#@dictionary = Hash.new
|
17
|
-
|
6
|
+
super
|
18
7
|
@id = File.basename(fele_path, File.extname(fele_path)).downcase
|
19
|
-
@up_link_doc_id = Hash.new
|
20
8
|
end
|
21
9
|
|
22
10
|
def to_html(nav_pane, output_file_path)
|
@@ -1,10 +1,8 @@
|
|
1
|
-
require_relative "
|
1
|
+
require_relative "persistent_document"
|
2
2
|
|
3
|
-
class Specification <
|
3
|
+
class Specification < PersistentDocument
|
4
4
|
|
5
|
-
attr_accessor :up_link_doc_id
|
6
5
|
attr_accessor :dictionary
|
7
|
-
attr_accessor :controlled_items
|
8
6
|
attr_accessor :todo_blocks
|
9
7
|
attr_accessor :wrong_links_hash
|
10
8
|
|
@@ -18,12 +16,7 @@ class Specification < BaseDocument
|
|
18
16
|
attr_accessor :color
|
19
17
|
|
20
18
|
def initialize(fele_path)
|
21
|
-
|
22
|
-
@path = fele_path
|
23
|
-
@title = ""
|
24
|
-
@items = Array.new
|
25
|
-
@headings = Array.new
|
26
|
-
@controlled_items = Array.new
|
19
|
+
super
|
27
20
|
@dictionary = Hash.new
|
28
21
|
@duplicates_list = Array.new
|
29
22
|
@todo_blocks = Array.new
|
@@ -39,7 +32,6 @@ class Specification < BaseDocument
|
|
39
32
|
@color = 'bbb'
|
40
33
|
|
41
34
|
@id = File.basename(fele_path, File.extname(fele_path)).downcase
|
42
|
-
@up_link_doc_id = Hash.new
|
43
35
|
end
|
44
36
|
|
45
37
|
def to_console
|
@@ -9,15 +9,12 @@ class Traceability < BaseDocument
|
|
9
9
|
attr_accessor :traced_items
|
10
10
|
|
11
11
|
def initialize(top_doc, bottom_doc, is_agregated)
|
12
|
-
|
12
|
+
super()
|
13
13
|
@top_doc = top_doc
|
14
14
|
@bottom_doc = bottom_doc
|
15
15
|
@is_agregated = is_agregated
|
16
16
|
@traced_items = {}
|
17
17
|
|
18
|
-
@items = Array.new
|
19
|
-
@headings = Array.new
|
20
|
-
|
21
18
|
if @is_agregated
|
22
19
|
@id = top_doc.id + "-all"
|
23
20
|
else
|
data/lib/almirah/dom/document.rb
CHANGED
@@ -49,7 +49,7 @@ class Document
|
|
49
49
|
|
50
50
|
def section_tree_to_html
|
51
51
|
s = ''
|
52
|
-
s += "<a href=\"\#" + @root_section.heading.anchor_id.to_s + "\">" + @root_section.heading.
|
52
|
+
s += "<a href=\"\#" + @root_section.heading.anchor_id.to_s + "\">" + @root_section.heading.get_section_info + "</a>\n"
|
53
53
|
if @root_section.sections.length >0
|
54
54
|
s += "\t<ul class=\"fa-ul\" style=\"margin-top: 2px;\">\n"
|
55
55
|
@root_section.sections.each do |sub_section|
|
data/lib/almirah/project.rb
CHANGED
@@ -149,7 +149,7 @@ class Project
|
|
149
149
|
def link_all_protocols
|
150
150
|
@protocols.each do |p|
|
151
151
|
@specifications.each do |s|
|
152
|
-
if p.
|
152
|
+
if p.up_link_docs.has_key?(s.id.to_s)
|
153
153
|
link_protocol_to_spec(p,s)
|
154
154
|
end
|
155
155
|
end
|
@@ -165,7 +165,7 @@ class Project
|
|
165
165
|
end
|
166
166
|
|
167
167
|
@specifications.each do |s|
|
168
|
-
s.
|
168
|
+
s.up_link_docs.each do |key, value|
|
169
169
|
unless available_specification_ids.has_key?(key)
|
170
170
|
# now key points to the doc_id that does not exist
|
171
171
|
wrong_doc_id = key
|
@@ -189,10 +189,10 @@ class Project
|
|
189
189
|
|
190
190
|
def link_two_specifications(doc_A, doc_B)
|
191
191
|
|
192
|
-
if doc_B.
|
192
|
+
if doc_B.up_link_docs.has_key?(doc_A.id.to_s)
|
193
193
|
top_document = doc_A
|
194
194
|
bottom_document = doc_B
|
195
|
-
elsif doc_A.
|
195
|
+
elsif doc_A.up_link_docs.has_key?(doc_B.id.to_s)
|
196
196
|
top_document = doc_B
|
197
197
|
bottom_document = doc_A
|
198
198
|
else
|
@@ -21,12 +21,41 @@ class SpecificationsDb
|
|
21
21
|
"heading_url" => i.parent_heading.get_url(), \
|
22
22
|
"heading_text" => i.parent_heading.get_section_info()
|
23
23
|
}
|
24
|
-
@data.append e
|
24
|
+
@data.append e
|
25
|
+
elsif i.instance_of? MarkdownList
|
26
|
+
e = add_markdown_list_item_to_db( @data, i, i)
|
25
27
|
end
|
26
28
|
end
|
27
29
|
end
|
28
30
|
end
|
29
31
|
|
32
|
+
def add_markdown_list_item_to_db(data, item_for_reference, item_to_process)
|
33
|
+
e = nil
|
34
|
+
item_to_process.rows.each do |r|
|
35
|
+
if r.is_a?(MarkdownList)
|
36
|
+
f_text = r.text
|
37
|
+
e = { "document" => item_for_reference.parent_doc.title, \
|
38
|
+
"doc_color" => item_for_reference.parent_doc.color, \
|
39
|
+
"text" => f_text, \
|
40
|
+
"heading_url" => item_for_reference.parent_heading.get_url(), \
|
41
|
+
"heading_text" => item_for_reference.parent_heading.get_section_info()
|
42
|
+
}
|
43
|
+
data << e
|
44
|
+
add_markdown_list_item_to_db(data, item_for_reference, r)
|
45
|
+
else
|
46
|
+
f_text = r
|
47
|
+
e = { "document" => item_for_reference.parent_doc.title, \
|
48
|
+
"doc_color" => item_for_reference.parent_doc.color, \
|
49
|
+
"text" => f_text, \
|
50
|
+
"heading_url" => item_for_reference.parent_heading.get_url(), \
|
51
|
+
"heading_text" => item_for_reference.parent_heading.get_section_info()
|
52
|
+
}
|
53
|
+
data << e
|
54
|
+
end
|
55
|
+
end
|
56
|
+
return e
|
57
|
+
end
|
58
|
+
|
30
59
|
def save(path)
|
31
60
|
json = JSON.generate(@data)
|
32
61
|
|
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.2.
|
4
|
+
version: 0.2.1
|
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-06-
|
11
|
+
date: 2024-06-09 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
|
@@ -34,9 +34,11 @@ files:
|
|
34
34
|
- lib/almirah/doc_items/paragraph.rb
|
35
35
|
- lib/almirah/doc_items/text_line.rb
|
36
36
|
- lib/almirah/doc_items/todo_block.rb
|
37
|
+
- lib/almirah/doc_parser.rb
|
37
38
|
- lib/almirah/doc_types/base_document.rb
|
38
39
|
- lib/almirah/doc_types/coverage.rb
|
39
40
|
- lib/almirah/doc_types/index.rb
|
41
|
+
- lib/almirah/doc_types/persistent_document.rb
|
40
42
|
- lib/almirah/doc_types/protocol.rb
|
41
43
|
- lib/almirah/doc_types/specification.rb
|
42
44
|
- lib/almirah/doc_types/traceability.rb
|