Almirah 0.1.7 → 0.1.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 +359 -366
- data/lib/almirah/doc_types/index.rb +21 -3
- data/lib/almirah/doc_types/specification.rb +3 -0
- data/lib/almirah/doc_types/traceability.rb +26 -10
- data/lib/almirah/project.rb +27 -3
- data/lib/almirah/templates/page.html +1 -1
- data/lib/almirah.rb +4 -17
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c88fa681954a14b92b114aec73d996c30678749d13cfb049a25b216b83f726cb
|
4
|
+
data.tar.gz: 94c51c141e22015250c776e547994462f7ff878967938c0fd43b4bdff698fa84
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0c793599f7119665dc724c4fe66102dab3168e3d9ef34a1efb77f928f521a58689945111a22acc5a1d358a85a4575700b8f8675a39f561cc8a54f8c214adba92
|
7
|
+
data.tar.gz: 3e95fd1f182d88233f244d59fd7ed36ca1924f1cb1e0594065e35511da739e58aa77b17d5a8b974499378ef430fb41eb6770b067f28e402ceb076828fdf186cb
|
data/lib/almirah/doc_fabric.rb
CHANGED
@@ -1,377 +1,370 @@
|
|
1
|
-
|
2
|
-
require_relative
|
3
|
-
require_relative
|
4
|
-
require_relative
|
5
|
-
|
6
|
-
require_relative
|
7
|
-
require_relative
|
8
|
-
require_relative
|
9
|
-
require_relative
|
10
|
-
require_relative
|
11
|
-
require_relative
|
12
|
-
require_relative
|
13
|
-
require_relative
|
14
|
-
require_relative
|
15
|
-
require_relative
|
16
|
-
require_relative
|
17
|
-
|
18
|
-
require_relative
|
19
|
-
|
20
|
-
require_relative "dom/document"
|
1
|
+
require_relative 'doc_types/base_document'
|
2
|
+
require_relative 'doc_types/specification'
|
3
|
+
require_relative 'doc_types/protocol'
|
4
|
+
require_relative 'doc_items/text_line'
|
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
|
+
|
18
|
+
require_relative 'dom/document'
|
21
19
|
|
22
20
|
class DocFabric
|
21
|
+
@@color_index = 0
|
22
|
+
@@spec_colors = %w[cff4d2 fbeee6 ffcad4 bce6ff e4dfd9 f9e07f cbe54e d3e7ee eab595 86e3c3
|
23
|
+
ffdca2 ffffff ffdd94 d0e6a5 ffb284 f3dbcf c9bbc8 c6c09c]
|
23
24
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
end
|
25
|
+
def self.add_lazy_doc_id(path)
|
26
|
+
if res = /(\w+)[.]md$/.match(path)
|
27
|
+
TextLine.add_lazy_doc_id(res[1])
|
28
28
|
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.create_specification(path)
|
32
|
+
color = @@spec_colors[@@color_index]
|
33
|
+
@@color_index += 1
|
34
|
+
@@color_index = 0 if @@color_index >= @@spec_colors.length
|
35
|
+
doc = Specification.new path
|
36
|
+
DocFabric.parse_document doc
|
37
|
+
doc.color = color
|
38
|
+
doc
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.create_protocol(path)
|
42
|
+
doc = Protocol.new path
|
43
|
+
DocFabric.parse_document doc
|
44
|
+
doc
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.parse_document(doc)
|
48
|
+
temp_md_table = nil
|
49
|
+
temp_md_list = nil
|
50
|
+
temp_code_block = nil
|
51
|
+
|
52
|
+
file = File.open(doc.path)
|
53
|
+
file_lines = file.readlines
|
54
|
+
file.close
|
55
|
+
|
56
|
+
file_lines.each do |s|
|
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
|
29
134
|
|
30
|
-
|
31
|
-
|
32
|
-
DocFabric.parse_document doc
|
33
|
-
return doc
|
34
|
-
end
|
135
|
+
# since we already know id and text
|
136
|
+
item = ControlledParagraph.new(text, id)
|
35
137
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
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]
|
41
144
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
up_links.each do |ul|
|
139
|
-
if tmp = />\[(\S*)\]$/.match(ul) # >[SRS-001]
|
140
|
-
up_link_id = tmp[1]
|
141
|
-
|
142
|
-
unless item.up_link_ids
|
143
|
-
item.up_link_ids = Array.new
|
144
|
-
end
|
145
|
-
|
146
|
-
item.up_link_ids.append(up_link_id)
|
147
|
-
|
148
|
-
if tmp = /^([a-zA-Z]+)[-]\d+/.match(up_link_id) # SRS
|
149
|
-
doc.up_link_doc_id[ tmp[1].downcase.to_s ] = tmp[1].downcase # multiple documents could be up-linked
|
150
|
-
end
|
151
|
-
end
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
|
156
|
-
item.parent_doc = doc
|
157
|
-
item.parent_heading = doc.headings[-1]
|
158
|
-
|
159
|
-
doc.items.append(item)
|
160
|
-
#for statistics
|
161
|
-
if doc.dictionary.has_key?( id.to_s )
|
162
|
-
doc.duplicated_ids_number += 1
|
163
|
-
doc.duplicates_list.append(item)
|
164
|
-
else
|
165
|
-
doc.dictionary[ id.to_s ] = item #for fast search
|
166
|
-
end
|
167
|
-
doc.controlled_items.append(item) #for fast search
|
168
|
-
|
169
|
-
#for statistics
|
170
|
-
n = /\d+/.match(id)[0].to_i
|
171
|
-
if n > doc.last_used_id_number
|
172
|
-
doc.last_used_id = id
|
173
|
-
doc.last_used_id_number = n
|
174
|
-
end
|
175
|
-
|
176
|
-
elsif res = /^[!]\[(.*)\]\((.*)\)/.match(s) # Image
|
177
|
-
|
178
|
-
if tempMdTable
|
179
|
-
doc.items.append tempMdTable
|
180
|
-
tempMdTable = nil
|
181
|
-
end
|
182
|
-
if tempMdList
|
183
|
-
doc.items.append tempMdList
|
184
|
-
tempMdList = nil
|
185
|
-
end
|
186
|
-
|
187
|
-
img_text = res[1]
|
188
|
-
img_path = res[2]
|
189
|
-
|
190
|
-
item = Image.new( img_text, img_path )
|
191
|
-
item.parent_doc = doc
|
192
|
-
|
193
|
-
doc.items.append(item)
|
194
|
-
|
195
|
-
elsif res = /^(\*\s+)(.*)/.match(s) #check if unordered list start
|
196
|
-
|
197
|
-
if tempMdTable
|
198
|
-
doc.items.append tempMdTable
|
199
|
-
tempMdTable = nil
|
200
|
-
end
|
201
|
-
|
202
|
-
row = res[2]
|
203
|
-
|
204
|
-
if tempMdList
|
205
|
-
tempMdList.addRow(s)
|
206
|
-
else
|
207
|
-
item = MarkdownList.new(false)
|
208
|
-
item.addRow(s)
|
209
|
-
item.parent_doc = doc
|
210
|
-
tempMdList = item
|
211
|
-
end
|
212
|
-
|
213
|
-
elsif res = /^\d[.]\s(.*)/.match(s) #check if ordered list start
|
214
|
-
|
215
|
-
if tempMdTable
|
216
|
-
doc.items.append tempMdTable
|
217
|
-
tempMdTable = nil
|
218
|
-
end
|
219
|
-
|
220
|
-
row = res[1]
|
221
|
-
|
222
|
-
if tempMdList
|
223
|
-
tempMdList.addRow(s)
|
224
|
-
else
|
225
|
-
item = MarkdownList.new(true)
|
226
|
-
item.addRow(s)
|
227
|
-
item.parent_doc = doc
|
228
|
-
tempMdList = item
|
229
|
-
end
|
230
|
-
|
231
|
-
elsif s[0] == '|' #check if table
|
232
|
-
|
233
|
-
if tempMdList
|
234
|
-
doc.items.append tempMdList
|
235
|
-
tempMdList = nil
|
236
|
-
end
|
237
|
-
|
238
|
-
if res = /^[|](-{3,})[|]/.match(s) #check if it is a separator first
|
239
|
-
|
240
|
-
if tempMdTable
|
241
|
-
#separator is found after heading - just skip it
|
242
|
-
else
|
243
|
-
#separator out of table scope consider it just as a regular paragraph
|
244
|
-
item = Paragraph.new(s)
|
245
|
-
item.parent_doc = doc
|
246
|
-
doc.items.append(item)
|
247
|
-
end
|
248
|
-
|
249
|
-
elsif res = /^[|](.*[|])/.match(s) #check if it looks as a table
|
250
|
-
|
251
|
-
row = res[1]
|
252
|
-
|
253
|
-
if tempMdTable
|
254
|
-
# check if it is a controlled table
|
255
|
-
unless tempMdTable.addRow(row)
|
256
|
-
tempMdTable = ControlledTable.new(tempMdTable, doc)
|
257
|
-
tempMdTable.parent_doc = doc
|
258
|
-
tempMdTable.addRow(row)
|
259
|
-
end
|
260
|
-
else
|
261
|
-
#start table from heading
|
262
|
-
tempMdTable = MarkdownTable.new(row)
|
263
|
-
tempMdTable.parent_doc = doc
|
264
|
-
end
|
265
|
-
end
|
266
|
-
|
267
|
-
elsif res = /^[>](.*)/.match(s) #check if blockquote
|
268
|
-
|
269
|
-
if tempMdTable
|
270
|
-
doc.items.append tempMdTable
|
271
|
-
tempMdTable = nil
|
272
|
-
end
|
273
|
-
if tempMdList
|
274
|
-
doc.items.append tempMdList
|
275
|
-
tempMdList = nil
|
276
|
-
end
|
277
|
-
|
278
|
-
item = Blockquote.new(res[1])
|
279
|
-
item.parent_doc = doc
|
280
|
-
doc.items.append(item)
|
281
|
-
|
282
|
-
elsif res = /^```(\w*)/.match(s) #check if code block
|
283
|
-
|
284
|
-
if tempMdTable
|
285
|
-
doc.items.append tempMdTable
|
286
|
-
tempMdTable = nil
|
287
|
-
end
|
288
|
-
if tempMdList
|
289
|
-
doc.items.append tempMdList
|
290
|
-
tempMdList = nil
|
291
|
-
end
|
292
|
-
|
293
|
-
suggested_format = ""
|
294
|
-
if res.length == 2
|
295
|
-
suggested_format = res[1]
|
296
|
-
end
|
297
|
-
|
298
|
-
if tempCodeBlock
|
299
|
-
# close already opened block
|
300
|
-
doc.items.append(tempCodeBlock)
|
301
|
-
tempCodeBlock = nil
|
302
|
-
else
|
303
|
-
#start code block
|
304
|
-
tempCodeBlock = CodeBlock.new(suggested_format)
|
305
|
-
tempCodeBlock.parent_doc = doc
|
306
|
-
end
|
307
|
-
|
308
|
-
elsif res = /^TODO\:(.*)/.match(s) #check if TODO block
|
309
|
-
|
310
|
-
if tempMdTable
|
311
|
-
doc.items.append tempMdTable
|
312
|
-
tempMdTable = nil
|
313
|
-
end
|
314
|
-
if tempMdList
|
315
|
-
doc.items.append tempMdList
|
316
|
-
tempMdList = nil
|
317
|
-
end
|
318
|
-
|
319
|
-
text = "**TODO**: " + res[1]
|
320
|
-
|
321
|
-
item = TodoBlock.new(text)
|
322
|
-
item.parent_doc = doc
|
323
|
-
doc.items.append(item)
|
324
|
-
doc.todo_blocks.append(item)
|
325
|
-
|
326
|
-
else # Reqular Paragraph
|
327
|
-
if tempMdTable
|
328
|
-
doc.items.append tempMdTable
|
329
|
-
tempMdTable = nil
|
330
|
-
end
|
331
|
-
if tempMdList
|
332
|
-
if MarkdownList.unordered_list_item?(s) || MarkdownList.ordered_list_item?(s)
|
333
|
-
tempMdList.addRow(s)
|
334
|
-
next
|
335
|
-
else
|
336
|
-
doc.items.append tempMdList
|
337
|
-
tempMdList = nil
|
338
|
-
end
|
339
|
-
end
|
340
|
-
if tempCodeBlock
|
341
|
-
tempCodeBlock.code_lines.append(s)
|
342
|
-
else
|
343
|
-
item = Paragraph.new(s)
|
344
|
-
item.parent_doc = doc
|
345
|
-
doc.items.append(item)
|
346
|
-
end
|
347
|
-
end
|
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
|
+
|
192
|
+
doc.items.append(item)
|
193
|
+
|
194
|
+
elsif res = /^(\*\s+)(.*)/.match(s) # check if unordered list start
|
195
|
+
|
196
|
+
if temp_md_table
|
197
|
+
doc.items.append temp_md_table
|
198
|
+
temp_md_table = nil
|
199
|
+
end
|
200
|
+
|
201
|
+
row = res[2]
|
202
|
+
|
203
|
+
if temp_md_list
|
204
|
+
temp_md_list.addRow(s)
|
205
|
+
else
|
206
|
+
item = MarkdownList.new(false)
|
207
|
+
item.addRow(s)
|
208
|
+
item.parent_doc = doc
|
209
|
+
temp_md_list = item
|
210
|
+
end
|
211
|
+
|
212
|
+
elsif res = /^\d[.]\s(.*)/.match(s) # check if ordered list start
|
213
|
+
|
214
|
+
if temp_md_table
|
215
|
+
doc.items.append temp_md_table
|
216
|
+
temp_md_table = nil
|
217
|
+
end
|
218
|
+
|
219
|
+
row = res[1]
|
220
|
+
|
221
|
+
if temp_md_list
|
222
|
+
temp_md_list.addRow(s)
|
223
|
+
else
|
224
|
+
item = MarkdownList.new(true)
|
225
|
+
item.addRow(s)
|
226
|
+
item.parent_doc = doc
|
227
|
+
temp_md_list = item
|
228
|
+
end
|
229
|
+
|
230
|
+
elsif s[0] == '|' # check if table
|
231
|
+
|
232
|
+
if temp_md_list
|
233
|
+
doc.items.append temp_md_list
|
234
|
+
temp_md_list = nil
|
235
|
+
end
|
236
|
+
|
237
|
+
if res = /^[|](-{3,})[|]/.match(s) # check if it is a separator first
|
238
|
+
|
239
|
+
if temp_md_table
|
240
|
+
# separator is found after heading - just skip it
|
348
241
|
else
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
242
|
+
# separator out of table scope consider it just as a regular paragraph
|
243
|
+
item = Paragraph.new(s)
|
244
|
+
item.parent_doc = doc
|
245
|
+
doc.items.append(item)
|
353
246
|
end
|
247
|
+
|
248
|
+
elsif res = /^[|](.*[|])/.match(s) # check if it looks as a table
|
249
|
+
|
250
|
+
row = res[1]
|
251
|
+
|
252
|
+
if temp_md_table
|
253
|
+
# check if it is a controlled table
|
254
|
+
unless temp_md_table.addRow(row)
|
255
|
+
temp_md_table = ControlledTable.new(temp_md_table, doc)
|
256
|
+
temp_md_table.parent_doc = doc
|
257
|
+
temp_md_table.addRow(row)
|
258
|
+
end
|
259
|
+
else
|
260
|
+
# start table from heading
|
261
|
+
temp_md_table = MarkdownTable.new(row)
|
262
|
+
temp_md_table.parent_doc = doc
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
elsif res = /^>(.*)/.match(s) # check if blockquote
|
267
|
+
|
268
|
+
if temp_md_table
|
269
|
+
doc.items.append temp_md_table
|
270
|
+
temp_md_table = nil
|
271
|
+
end
|
272
|
+
if temp_md_list
|
273
|
+
doc.items.append temp_md_list
|
274
|
+
temp_md_list = nil
|
275
|
+
end
|
276
|
+
|
277
|
+
item = Blockquote.new(res[1])
|
278
|
+
item.parent_doc = doc
|
279
|
+
doc.items.append(item)
|
280
|
+
|
281
|
+
elsif res = /^```(\w*)/.match(s) # check if code block
|
282
|
+
|
283
|
+
if temp_md_table
|
284
|
+
doc.items.append temp_md_table
|
285
|
+
temp_md_table = nil
|
286
|
+
end
|
287
|
+
if temp_md_list
|
288
|
+
doc.items.append temp_md_list
|
289
|
+
temp_md_list = nil
|
290
|
+
end
|
291
|
+
|
292
|
+
suggested_format = ''
|
293
|
+
suggested_format = res[1] if res.length == 2
|
294
|
+
|
295
|
+
if temp_code_block
|
296
|
+
# close already opened block
|
297
|
+
doc.items.append(temp_code_block)
|
298
|
+
temp_code_block = nil
|
299
|
+
else
|
300
|
+
# start code block
|
301
|
+
temp_code_block = CodeBlock.new(suggested_format)
|
302
|
+
temp_code_block.parent_doc = doc
|
303
|
+
end
|
304
|
+
|
305
|
+
elsif res = /^TODO:(.*)/.match(s) # check if TODO block
|
306
|
+
|
307
|
+
if temp_md_table
|
308
|
+
doc.items.append temp_md_table
|
309
|
+
temp_md_table = nil
|
310
|
+
end
|
311
|
+
if temp_md_list
|
312
|
+
doc.items.append temp_md_list
|
313
|
+
temp_md_list = nil
|
314
|
+
end
|
315
|
+
|
316
|
+
text = '**TODO**: ' + res[1]
|
317
|
+
|
318
|
+
item = TodoBlock.new(text)
|
319
|
+
item.parent_doc = doc
|
320
|
+
doc.items.append(item)
|
321
|
+
doc.todo_blocks.append(item)
|
322
|
+
|
323
|
+
else # Reqular Paragraph
|
324
|
+
if temp_md_table
|
325
|
+
doc.items.append temp_md_table
|
326
|
+
temp_md_table = nil
|
327
|
+
end
|
328
|
+
if temp_md_list
|
329
|
+
if MarkdownList.unordered_list_item?(s) || MarkdownList.ordered_list_item?(s)
|
330
|
+
temp_md_list.addRow(s)
|
331
|
+
next
|
332
|
+
else
|
333
|
+
doc.items.append temp_md_list
|
334
|
+
temp_md_list = nil
|
335
|
+
end
|
336
|
+
end
|
337
|
+
if temp_code_block
|
338
|
+
temp_code_block.code_lines.append(s)
|
339
|
+
else
|
340
|
+
item = Paragraph.new(s)
|
341
|
+
item.parent_doc = doc
|
342
|
+
doc.items.append(item)
|
343
|
+
end
|
354
344
|
end
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
# Build dom
|
373
|
-
if doc.is_a?(Specification)
|
374
|
-
doc.dom = Document.new(doc.headings)
|
375
|
-
end
|
345
|
+
elsif temp_md_list
|
346
|
+
doc.items.append temp_md_list
|
347
|
+
temp_md_list = nil # lists are separated by emty line from each other
|
348
|
+
end
|
349
|
+
end
|
350
|
+
# Finalize non-closed elements
|
351
|
+
if temp_md_table
|
352
|
+
doc.items.append temp_md_table
|
353
|
+
temp_md_table = nil
|
354
|
+
end
|
355
|
+
if temp_md_list
|
356
|
+
doc.items.append temp_md_list
|
357
|
+
temp_md_list = nil
|
358
|
+
end
|
359
|
+
if temp_code_block
|
360
|
+
doc.items.append temp_code_block
|
361
|
+
temp_code_block = nil
|
376
362
|
end
|
377
|
-
|
363
|
+
# Add footer to close opened tables if any
|
364
|
+
item = DocFooter.new
|
365
|
+
item.parent_doc = doc
|
366
|
+
doc.items.append(item)
|
367
|
+
# Build dom
|
368
|
+
doc.dom = Document.new(doc.headings) if doc.is_a?(Specification)
|
369
|
+
end
|
370
|
+
end
|
@@ -44,7 +44,7 @@ class Index < BaseDocument
|
|
44
44
|
|
45
45
|
sorted_items.each do |doc|
|
46
46
|
s = "\t<tr>\n"
|
47
|
-
s += "\t\t<td class=\"item_text\" style='padding: 5px;'><a href=\"./specifications/#{doc.id}/#{doc.id}.html\" class=\"external\"
|
47
|
+
s += "\t\t<td class=\"item_text\" style='padding: 5px;'><a href=\"./specifications/#{doc.id}/#{doc.id}.html\" class=\"external\"><i class=\"fa fa-file-text-o\" style='background-color: ##{doc.color};'> </i> #{doc.title}</a></td>\n"
|
48
48
|
s += "\t\t<td class=\"item_id\" style='width: 7%;'>#{doc.controlled_items.length.to_s}</td>\n"
|
49
49
|
s += "\t\t<td class=\"item_id\" style='width: 7%;'>#{doc.items_with_uplinks_number.to_s}</td>\n"
|
50
50
|
s += "\t\t<td class=\"item_id\" style='width: 7%;'>#{doc.items_with_downlinks_number.to_s}</td>\n"
|
@@ -97,18 +97,36 @@ class Index < BaseDocument
|
|
97
97
|
s += "<table class=\"controlled\">\n"
|
98
98
|
s += "\t<thead>\n"
|
99
99
|
s += "\t\t<th>Title</th>\n"
|
100
|
+
s += "\t\t<th>Coverage</th>\n"
|
100
101
|
s += "\t\t<th>Top Document</th>\n"
|
101
102
|
s += "\t\t<th>Bottom Document</th>\n"
|
102
103
|
s += "</thead>\n"
|
103
104
|
html_rows.append s
|
104
105
|
|
105
106
|
sorted_items = @project.traceability_matrices.sort_by { |w| w.id }
|
107
|
+
# buble-up design inputs
|
108
|
+
design_inputs = []
|
109
|
+
others = []
|
110
|
+
sorted_items.each do |doc|
|
111
|
+
if doc.bottom_doc
|
112
|
+
others.append doc
|
113
|
+
else
|
114
|
+
design_inputs.append doc
|
115
|
+
end
|
116
|
+
end
|
117
|
+
sorted_items = design_inputs + others
|
106
118
|
|
107
119
|
sorted_items.each do |doc|
|
108
120
|
s = "\t<tr>\n"
|
121
|
+
coverage = doc.traced_items.length.to_f / doc.top_doc.controlled_items.length.to_f * 100.0
|
109
122
|
s += "\t\t<td class=\"item_text\" style='padding: 5px;'><a href=\"./specifications/#{doc.id}/#{doc.id}.html\" class=\"external\">#{doc.title}</a></td>\n"
|
110
|
-
s += "\t\t<td class=\"
|
111
|
-
s += "\t\t<td class=\"item_text\" style='width: 25%; padding: 5px;'
|
123
|
+
s += "\t\t<td class=\"item_id\" style='width: 7%;'>#{'%.2f' % coverage}%</td>\n"
|
124
|
+
s += "\t\t<td class=\"item_text\" style='width: 25%; padding: 5px;'><i class=\"fa fa-file-text-o\" style='background-color: ##{doc.top_doc.color};'> </i> #{doc.top_doc.title}</td>\n"
|
125
|
+
if doc.bottom_doc
|
126
|
+
s += "\t\t<td class=\"item_text\" style='width: 25%; padding: 5px;'><i class=\"fa fa-file-text-o\" style='background-color: ##{doc.bottom_doc.color};'> </i> #{doc.bottom_doc.title}</td>\n"
|
127
|
+
else
|
128
|
+
s += "\t\t<td class=\"item_text\" style='width: 25%; padding: 5px;'><i class=\"fa fa-circle-o\"'> </i> All References</td>\n"
|
129
|
+
end
|
112
130
|
s += "</tr>\n"
|
113
131
|
html_rows.append s
|
114
132
|
end
|
@@ -15,6 +15,7 @@ class Specification < BaseDocument
|
|
15
15
|
attr_accessor :duplicates_list
|
16
16
|
attr_accessor :last_used_id
|
17
17
|
attr_accessor :last_used_id_number
|
18
|
+
attr_accessor :color
|
18
19
|
|
19
20
|
def initialize(fele_path)
|
20
21
|
|
@@ -35,6 +36,8 @@ class Specification < BaseDocument
|
|
35
36
|
@last_used_id = ""
|
36
37
|
@last_used_id_number = 0
|
37
38
|
|
39
|
+
@color = 'bbb'
|
40
|
+
|
38
41
|
@id = File.basename(fele_path, File.extname(fele_path)).downcase
|
39
42
|
@up_link_doc_id = Hash.new
|
40
43
|
end
|
@@ -6,12 +6,14 @@ class Traceability < BaseDocument
|
|
6
6
|
attr_accessor :bottom_doc
|
7
7
|
attr_accessor :items
|
8
8
|
attr_accessor :is_agregated
|
9
|
+
attr_accessor :traced_items
|
9
10
|
|
10
11
|
def initialize(top_doc, bottom_doc, is_agregated)
|
11
12
|
|
12
13
|
@top_doc = top_doc
|
13
14
|
@bottom_doc = bottom_doc
|
14
15
|
@is_agregated = is_agregated
|
16
|
+
@traced_items = {}
|
15
17
|
|
16
18
|
@items = Array.new
|
17
19
|
@headings = Array.new
|
@@ -37,7 +39,11 @@ class Traceability < BaseDocument
|
|
37
39
|
s = "<h1>#{@title}</h1>\n"
|
38
40
|
s += "<table class=\"controlled\">\n"
|
39
41
|
s += "\t<thead> <th>#</th> <th style='font-weight: bold;'>#{@top_doc.title}</th> "
|
40
|
-
|
42
|
+
if @bottom_doc
|
43
|
+
s += "<th>#</th> <th style='font-weight: bold;'>#{@bottom_doc.title}</th> "
|
44
|
+
else
|
45
|
+
s += "<th>#</th> <th style='font-weight: bold;'>All References</th> "
|
46
|
+
end
|
41
47
|
s += "<th style='font-weight: bold;'>Document Section</th>"
|
42
48
|
s += "</thead>\n"
|
43
49
|
html_rows.append s
|
@@ -57,27 +63,36 @@ class Traceability < BaseDocument
|
|
57
63
|
def render_table_row(top_item)
|
58
64
|
s = ""
|
59
65
|
top_f_text = top_item.format_string( top_item.text )
|
60
|
-
|
66
|
+
id_color = ""
|
67
|
+
|
61
68
|
if top_item.down_links
|
62
69
|
|
63
70
|
if @is_agregated
|
64
|
-
|
65
|
-
|
66
|
-
id_color = "style='background-color: #fff8c5;'"
|
67
|
-
else
|
68
|
-
id_color = ""
|
69
|
-
end
|
71
|
+
|
72
|
+
top_item_rendered = false
|
70
73
|
|
71
74
|
top_item.down_links.each do |bottom_item|
|
75
|
+
id_color = "style='background-color: ##{bottom_item.parent_doc.color};'"
|
72
76
|
bottom_f_text = bottom_item.format_string( bottom_item.text )
|
73
77
|
document_section = bottom_item.parent_heading.get_section_info
|
74
78
|
s += "\t<tr>\n"
|
75
|
-
s += "\t\t<td class=\"item_id\"
|
79
|
+
s += "\t\t<td class=\"item_id\"><a href=\"./../#{top_item.parent_doc.id}/#{top_item.parent_doc.id}.html##{top_item.id}\" class=\"external\">#{top_item.id}</a></td>\n"
|
76
80
|
s += "\t\t<td class=\"item_text\" style='width: 34%;'>#{top_f_text}</td>\n"
|
77
|
-
s += "\t\t<td class=\"item_id\"><a href=\"./../#{bottom_item.parent_doc.id}/#{bottom_item.parent_doc.id}.html##{bottom_item.id}\" class=\"external\">#{bottom_item.id}</a></td>\n"
|
81
|
+
s += "\t\t<td class=\"item_id\" #{id_color}><a href=\"./../#{bottom_item.parent_doc.id}/#{bottom_item.parent_doc.id}.html##{bottom_item.id}\" class=\"external\">#{bottom_item.id}</a></td>\n"
|
78
82
|
s += "\t\t<td class=\"item_text\" style='width: 34%;'>#{bottom_f_text}</td>\n"
|
79
83
|
s += "\t\t<td class=\"item_text\" style='width: 16%;'>#{document_section}</td>\n"
|
80
84
|
s += "\t</tr>\n"
|
85
|
+
top_item_rendered = true
|
86
|
+
@traced_items[top_item.id.to_s.downcase] = top_item
|
87
|
+
end
|
88
|
+
unless top_item_rendered
|
89
|
+
s += "\t<tr>\n"
|
90
|
+
s += "\t\t<td class=\"item_id\"><a href=\"./../#{top_item.parent_doc.id}/#{top_item.parent_doc.id}.html##{top_item.id}\" class=\"external\">#{top_item.id}</a></td>\n"
|
91
|
+
s += "\t\t<td class=\"item_text\" style='width: 34%;'>#{top_f_text}</td>\n"
|
92
|
+
s += "\t\t<td class=\"item_id\"></td>\n"
|
93
|
+
s += "\t\t<td class=\"item_text\" style='width: 34%;'></td>\n"
|
94
|
+
s += "\t\t<td class=\"item_text\" style='width: 16%;'></td>\n"
|
95
|
+
s += "\t</tr>\n"
|
81
96
|
end
|
82
97
|
|
83
98
|
else
|
@@ -99,6 +114,7 @@ class Traceability < BaseDocument
|
|
99
114
|
s += "\t\t<td class=\"item_text\" style='width: 16%;'>#{document_section}</td>\n"
|
100
115
|
s += "\t</tr>\n"
|
101
116
|
top_item_rendered = true
|
117
|
+
@traced_items[top_item.id.to_s.downcase] = top_item
|
102
118
|
end
|
103
119
|
end
|
104
120
|
unless top_item_rendered
|
data/lib/almirah/project.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'fileutils'
|
2
|
+
require 'yaml'
|
2
3
|
require_relative "doc_fabric"
|
3
4
|
require_relative "navigation_pane"
|
4
5
|
require_relative "doc_types/traceability"
|
@@ -15,7 +16,7 @@ class Project
|
|
15
16
|
attr_accessor :specifications_dictionary
|
16
17
|
attr_accessor :index
|
17
18
|
attr_accessor :project
|
18
|
-
attr_accessor :
|
19
|
+
attr_accessor :project_configuration
|
19
20
|
|
20
21
|
def initialize(path)
|
21
22
|
@project_root_directory = path
|
@@ -26,9 +27,19 @@ class Project
|
|
26
27
|
@specifications_dictionary = Hash.new
|
27
28
|
@index = nil
|
28
29
|
@project = self
|
29
|
-
@
|
30
|
+
@project_configuration = {}
|
31
|
+
load_project_file()
|
32
|
+
FileUtils.remove_dir(@project_root_directory + "/build", true)
|
33
|
+
end
|
30
34
|
|
31
|
-
|
35
|
+
def load_project_file
|
36
|
+
begin
|
37
|
+
@project_configuration = YAML.load_file(@project_root_directory + '/project.yml')
|
38
|
+
rescue Psych::SyntaxError => e
|
39
|
+
puts "YAML syntax error: #{e.message}"
|
40
|
+
rescue Errno::ENOENT
|
41
|
+
puts "Project file not found: project.yml"
|
42
|
+
end
|
32
43
|
end
|
33
44
|
|
34
45
|
def specifications_and_protocols
|
@@ -90,6 +101,7 @@ class Project
|
|
90
101
|
Dir.glob( "#{@project_root_directory}/specifications/**/*.md" ).each do |f|
|
91
102
|
doc = DocFabric.create_specification(f)
|
92
103
|
@specifications.append(doc)
|
104
|
+
@specifications_dictionary[doc.id.to_s.downcase] = doc
|
93
105
|
end
|
94
106
|
end
|
95
107
|
|
@@ -115,6 +127,18 @@ class Project
|
|
115
127
|
link_two_specifications(c[0], c[1])
|
116
128
|
# puts "Link: #{c[0].id} - #{c[1].id}"
|
117
129
|
end
|
130
|
+
# separatelly create design inputs treceability
|
131
|
+
if (@project_configuration.key? 'specifications') and (@project_configuration['specifications'].key? 'input')
|
132
|
+
@project_configuration['specifications']['input'].each do |i|
|
133
|
+
if @specifications_dictionary.has_key? i.to_s.downcase
|
134
|
+
document = @specifications_dictionary[i.to_s.downcase]
|
135
|
+
if document
|
136
|
+
trx = Traceability.new document, nil, true
|
137
|
+
@traceability_matrices.append trx
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
118
142
|
end
|
119
143
|
|
120
144
|
def link_all_protocols
|
@@ -378,7 +378,7 @@ function modal_close_OnClick(clicked){
|
|
378
378
|
</div><!-- content -->
|
379
379
|
</div><!-- main -->
|
380
380
|
<div id="footer">
|
381
|
-
Powered by <a target="_blank" rel="noopener" href="https://www.almirah.site/">Almirah Framework</a>
|
381
|
+
Powered by <a target="_blank" rel="noopener" href="https://www.almirah.site/">Almirah Framework (0.1.8)</a>
|
382
382
|
</div><!-- footer -->
|
383
383
|
<!-- The modal window for image zoom -->
|
384
384
|
<div id="image_modal_div" class="modal">
|
data/lib/almirah.rb
CHANGED
@@ -7,9 +7,9 @@ class CLI < Thor
|
|
7
7
|
def please(project_folder)
|
8
8
|
a = Almirah.new project_folder
|
9
9
|
if options[:results]
|
10
|
-
a.results( options[:results]
|
10
|
+
a.results( options[:results] )
|
11
11
|
else
|
12
|
-
a.default(
|
12
|
+
a.default()
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
@@ -18,17 +18,6 @@ class CLI < Thor
|
|
18
18
|
a = Almirah.new project_folder
|
19
19
|
a.transform "docx"
|
20
20
|
end
|
21
|
-
|
22
|
-
option :results
|
23
|
-
desc "server <project_folder>", "say <project_folder>"
|
24
|
-
def server(project_folder)
|
25
|
-
a = Almirah.new project_folder
|
26
|
-
if options[:results]
|
27
|
-
a.results( options[:results], true )
|
28
|
-
else
|
29
|
-
a.default(true)
|
30
|
-
end
|
31
|
-
end
|
32
21
|
end
|
33
22
|
|
34
23
|
class Almirah
|
@@ -43,8 +32,7 @@ class Almirah
|
|
43
32
|
File.expand_path './..', File.dirname(__FILE__)
|
44
33
|
end
|
45
34
|
|
46
|
-
def results( test_run
|
47
|
-
@project.on_server = on_server
|
35
|
+
def results( test_run )
|
48
36
|
@project.specifications_and_results test_run
|
49
37
|
end
|
50
38
|
|
@@ -52,8 +40,7 @@ class Almirah
|
|
52
40
|
@project.transform file_extension
|
53
41
|
end
|
54
42
|
|
55
|
-
def default(
|
56
|
-
@project.on_server = on_server
|
43
|
+
def default()
|
57
44
|
@project.specifications_and_protocols
|
58
45
|
end
|
59
46
|
|
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.
|
4
|
+
version: 0.1.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-05-
|
11
|
+
date: 2024-05-19 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
|