Almirah 0.0.9 → 0.1.0
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 +22 -4
- data/lib/almirah/doc_items/controlled_paragraph.rb +6 -2
- data/lib/almirah/doc_items/controlled_table.rb +3 -3
- data/lib/almirah/doc_items/image.rb +1 -1
- data/lib/almirah/doc_items/markdown_list.rb +12 -5
- data/lib/almirah/doc_items/text_line.rb +65 -51
- data/lib/almirah/doc_types/base_document.rb +5 -1
- data/lib/almirah/doc_types/index.rb +107 -0
- data/lib/almirah/doc_types/protocol.rb +1 -1
- data/lib/almirah/doc_types/specification.rb +2 -2
- data/lib/almirah/doc_types/traceability.rb +46 -14
- data/lib/almirah/project.rb +74 -19
- data/lib/almirah/templates/page.html +3 -2
- data/lib/almirah.rb +11 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4bc6867a502188fb11b4632e9ab695d6fda2af0d1bfef94d3976d069acfb409f
|
4
|
+
data.tar.gz: 7d993b275d67bf0fa9cc6f40bfb3c43c2d16f6bb8cab5b76135866b5d81b59b9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '087e3aa7b1792ef031d42945fa29d05e5d2231b3e6b83177bfd529e3e7de646a24ac091a0be6e175575c814f87154641aad2036aa9ea7bd8f9247e6e50bd5aca'
|
7
|
+
data.tar.gz: 223acb70d369cdb753635b67b424815cee057ce0309d379a9547ec7769aa9ec78385a178a4862b859444cdd0a187e37c9eaf9771860a2756f1dfea68439133d5
|
data/lib/almirah/doc_fabric.rb
CHANGED
@@ -3,6 +3,7 @@ require_relative "doc_types/base_document"
|
|
3
3
|
require_relative "doc_types/specification"
|
4
4
|
require_relative "doc_types/protocol"
|
5
5
|
#
|
6
|
+
require_relative "doc_items/text_line"
|
6
7
|
require_relative "doc_items/doc_item"
|
7
8
|
require_relative "doc_items/heading"
|
8
9
|
require_relative "doc_items/paragraph"
|
@@ -15,6 +16,12 @@ require_relative "doc_items/markdown_list"
|
|
15
16
|
|
16
17
|
class DocFabric
|
17
18
|
|
19
|
+
def self.add_lazy_doc_id(path)
|
20
|
+
if res = /(\w+)[.]md$/.match(path)
|
21
|
+
TextLine.add_lazy_doc_id(res[1])
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
18
25
|
def self.create_specification(path)
|
19
26
|
doc = Specification.new path
|
20
27
|
DocFabric.parse_document doc
|
@@ -59,7 +66,18 @@ class DocFabric
|
|
59
66
|
if level == 1 && doc.title == ""
|
60
67
|
doc.title = value
|
61
68
|
end
|
62
|
-
|
69
|
+
elsif res = /^\%\s(.*)/.match(s) # Pandoc Document Title
|
70
|
+
|
71
|
+
title = res[1]
|
72
|
+
item = Heading.new(title, 1)
|
73
|
+
item.parent_doc = doc
|
74
|
+
doc.items.append(item)
|
75
|
+
doc.headings.append(item)
|
76
|
+
|
77
|
+
if doc.title == ""
|
78
|
+
doc.title = title
|
79
|
+
end
|
80
|
+
|
63
81
|
elsif res = /^\[(\S*)\]\s+(.*)/.match(s) # Controlled Paragraph
|
64
82
|
|
65
83
|
if tempMdTable
|
@@ -81,7 +99,7 @@ class DocFabric
|
|
81
99
|
up_link = tmp[2]
|
82
100
|
|
83
101
|
if tmp = /^([a-zA-Z]+)[-]\d+/.match(up_link) # SRS
|
84
|
-
doc.up_link_doc_id = tmp[1].downcase
|
102
|
+
doc.up_link_doc_id[ tmp[1].downcase.to_s ] = tmp[1].downcase # multiple documents could be up-linked
|
85
103
|
end
|
86
104
|
end
|
87
105
|
|
@@ -134,7 +152,7 @@ class DocFabric
|
|
134
152
|
row = res[2]
|
135
153
|
|
136
154
|
if tempMdList
|
137
|
-
tempMdList.addRow(
|
155
|
+
tempMdList.addRow(s)
|
138
156
|
else
|
139
157
|
item = MarkdownList.new(false)
|
140
158
|
item.addRow(s)
|
@@ -152,7 +170,7 @@ class DocFabric
|
|
152
170
|
row = res[1]
|
153
171
|
|
154
172
|
if tempMdList
|
155
|
-
tempMdList.addRow(
|
173
|
+
tempMdList.addRow(s)
|
156
174
|
else
|
157
175
|
item = MarkdownList.new(true)
|
158
176
|
item.addRow(s)
|
@@ -19,7 +19,7 @@ class ControlledParagraph < Paragraph
|
|
19
19
|
s = ''
|
20
20
|
unless @@htmlTableRenderInProgress
|
21
21
|
s += "<table class=\"controlled\">\n"
|
22
|
-
s += "\t<thead> <th>#</th> <th
|
22
|
+
s += "\t<thead> <th>#</th> <th></th> <th>UL</th> <th>DL</th> <th>COV</th> </thead>\n"
|
23
23
|
@@htmlTableRenderInProgress = true
|
24
24
|
end
|
25
25
|
f_text = format_string(@text)
|
@@ -40,7 +40,11 @@ class ControlledParagraph < Paragraph
|
|
40
40
|
if tmp = /^([a-zA-Z]+)[-]\d+/.match(@down_links[0].id) # guessing that all the links refer to one document
|
41
41
|
down_link_doc_name = tmp[1].downcase
|
42
42
|
end
|
43
|
-
|
43
|
+
if @down_links.length == 1
|
44
|
+
s += "\t\t<td class=\"item_id\"><a href=\"./../#{down_link_doc_name}/#{down_link_doc_name}.html##{@down_links[0].id}\" class=\"external\">#{@down_links[0].id}</a></td>\n"
|
45
|
+
else
|
46
|
+
s += "\t\t<td class=\"item_id\"><a href=\"./../#{down_link_doc_name}/#{down_link_doc_name}.html\" class=\"external\">#{@down_links.length}</a></td>\n"
|
47
|
+
end
|
44
48
|
else
|
45
49
|
s += "\t\t<td class=\"item_id\"></td>\n"
|
46
50
|
end
|
@@ -128,9 +128,9 @@ class ControlledTable < DocItem
|
|
128
128
|
new_row.columns.append col
|
129
129
|
# save uplink key but do not rewrite
|
130
130
|
if col.up_link_doc_id != nil
|
131
|
-
|
132
|
-
|
133
|
-
|
131
|
+
|
132
|
+
@parent_doc.up_link_doc_id[ col.up_link_doc_id.to_s ] = col.up_link_doc_id
|
133
|
+
|
134
134
|
# save reference to the test step
|
135
135
|
new_row.up_link = col.up_link
|
136
136
|
@parent_doc.controlled_items.append new_row
|
@@ -21,7 +21,6 @@ class MarkdownList < DocItem
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def addRow(raw_text)
|
24
|
-
puts raw_text
|
25
24
|
pos = calculate_text_position(raw_text)
|
26
25
|
row = raw_text[pos..-1]
|
27
26
|
|
@@ -40,7 +39,7 @@ class MarkdownList < DocItem
|
|
40
39
|
#cannot be there
|
41
40
|
else
|
42
41
|
nested_list.text = prev_row
|
43
|
-
puts "Length: " + prev_lists_stack_item.rows.length.to_s
|
42
|
+
#puts "Length: " + prev_lists_stack_item.rows.length.to_s
|
44
43
|
prev_lists_stack_item.rows[-1] = nested_list
|
45
44
|
end
|
46
45
|
|
@@ -58,9 +57,10 @@ class MarkdownList < DocItem
|
|
58
57
|
end
|
59
58
|
|
60
59
|
def calculate_indent_position(s)
|
60
|
+
s.downcase
|
61
61
|
pos = 0
|
62
62
|
s.each_char do |c|
|
63
|
-
if
|
63
|
+
if c != ' ' && c != '\t'
|
64
64
|
break
|
65
65
|
end
|
66
66
|
pos += 1
|
@@ -68,10 +68,16 @@ class MarkdownList < DocItem
|
|
68
68
|
return pos
|
69
69
|
end
|
70
70
|
def calculate_text_position(s)
|
71
|
+
s.downcase
|
71
72
|
pos = 0
|
73
|
+
space_detected = false
|
72
74
|
s.each_char do |c|
|
73
|
-
if
|
74
|
-
|
75
|
+
if space_detected
|
76
|
+
if c != ' ' && c != '\t' && c != '*' && c != '.' && !numeric?(c)
|
77
|
+
break
|
78
|
+
end
|
79
|
+
elsif c == ' ' || c == '\t'
|
80
|
+
space_detected = true
|
75
81
|
end
|
76
82
|
pos += 1
|
77
83
|
end
|
@@ -127,6 +133,7 @@ class MarkdownList < DocItem
|
|
127
133
|
s += "</li>\n"
|
128
134
|
else
|
129
135
|
f_text = format_string(r)
|
136
|
+
#puts f_text
|
130
137
|
s += "\t<li>#{f_text}</li>\n"
|
131
138
|
end
|
132
139
|
end
|
@@ -1,5 +1,12 @@
|
|
1
1
|
class TextLine
|
2
2
|
|
3
|
+
@@lazy_doc_id_dict = Hash.new
|
4
|
+
|
5
|
+
def self.add_lazy_doc_id(id)
|
6
|
+
doc_id = id.to_s.downcase
|
7
|
+
@@lazy_doc_id_dict[doc_id] = doc_id
|
8
|
+
end
|
9
|
+
|
3
10
|
def format_string(str)
|
4
11
|
state = 'default'
|
5
12
|
prev_state = 'default'
|
@@ -11,134 +18,111 @@ class TextLine
|
|
11
18
|
str.each_char do |c|
|
12
19
|
if c == '*'
|
13
20
|
if state == 'default'
|
14
|
-
prev_state = state
|
15
|
-
state = 'first_asterisk_detected'
|
21
|
+
prev_state, state = change_state(c, state, 'first_asterisk_detected')
|
16
22
|
|
17
23
|
elsif state == 'first_asterisk_detected'
|
18
|
-
prev_state = state
|
19
|
-
state = 'second_asterisk_detected'
|
24
|
+
prev_state, state = change_state(c, state, 'second_asterisk_detected')
|
20
25
|
|
21
26
|
elsif state == 'second_asterisk_detected'
|
22
|
-
prev_state = state
|
23
|
-
state = 'third_asterisk_detected'
|
27
|
+
prev_state, state = change_state(c, state, 'third_asterisk_detected')
|
24
28
|
|
25
29
|
elsif state == 'second_asterisk_detected'
|
26
|
-
prev_state = state
|
27
|
-
state = 'third_asterisk_detected'
|
30
|
+
prev_state, state = change_state(c, state, 'third_asterisk_detected')
|
28
31
|
|
29
32
|
elsif state == 'italic_started'
|
30
|
-
prev_state = state
|
31
|
-
state = 'default'
|
33
|
+
prev_state, state = change_state(c, state, 'default')
|
32
34
|
result += italic(stack)
|
33
35
|
|
34
36
|
elsif state == 'bold_started'
|
35
|
-
prev_state = state
|
36
|
-
state = 'first_asterisk_after_bold_detected'
|
37
|
+
prev_state, state = change_state(c, state, 'first_asterisk_after_bold_detected')
|
37
38
|
|
38
39
|
elsif state == 'first_asterisk_after_bold_detected'
|
39
|
-
prev_state = state
|
40
|
-
state = 'default'
|
40
|
+
prev_state, state = change_state(c, state, 'default')
|
41
41
|
result += bold(stack)
|
42
42
|
|
43
43
|
elsif state == 'bold_and_italic_started'
|
44
|
-
prev_state = state
|
45
|
-
state = 'first_asterisk_after_bold_and_italic_detected'
|
44
|
+
prev_state, state = change_state(c, state, 'first_asterisk_after_bold_and_italic_detected')
|
46
45
|
|
47
46
|
elsif state == 'first_asterisk_after_bold_and_italic_detected'
|
48
|
-
prev_state = state
|
49
|
-
state = 'second_asterisk_after_bold_and_italic_detected'
|
47
|
+
prev_state, state = change_state(c, state, 'second_asterisk_after_bold_and_italic_detected')
|
50
48
|
|
51
49
|
elsif state == 'second_asterisk_after_bold_and_italic_detected'
|
52
|
-
prev_state = state
|
53
|
-
state = 'default'
|
50
|
+
prev_state, state = change_state(c, state, 'default')
|
54
51
|
result += bold_and_italic(stack)
|
55
52
|
|
56
53
|
else
|
57
54
|
end
|
58
55
|
elsif c == '['
|
59
56
|
if state == 'default'
|
60
|
-
prev_state = state
|
61
|
-
state = 'square_bracket_left_detected'
|
57
|
+
prev_state, state = change_state(c, state, 'square_bracket_left_detected')
|
62
58
|
else
|
63
59
|
end
|
64
60
|
elsif c == ']'
|
65
61
|
if state == 'square_bracket_left_detected'
|
66
|
-
prev_state = state
|
67
|
-
state = 'default'
|
62
|
+
prev_state, state = change_state(c, state, 'default')
|
68
63
|
result += '[]'
|
69
64
|
|
70
65
|
elsif state == 'link_text_started'
|
71
|
-
prev_state = state
|
72
|
-
state = 'square_bracket_right_detected'
|
66
|
+
prev_state, state = change_state(c, state, 'square_bracket_right_detected')
|
73
67
|
link_text = stack
|
74
68
|
|
75
69
|
else
|
76
70
|
end
|
77
71
|
elsif c == '('
|
78
72
|
if state == 'square_bracket_right_detected'
|
79
|
-
prev_state = state
|
80
|
-
state = 'brace_left_detected'
|
73
|
+
prev_state, state = change_state(c, state, 'brace_left_detected')
|
81
74
|
else
|
75
|
+
result += c
|
82
76
|
end
|
83
77
|
elsif c == ')'
|
84
78
|
if state == 'brace_left_detected'
|
85
|
-
prev_state = state
|
86
|
-
state = 'default'
|
79
|
+
prev_state, state = change_state(c, state, 'default')
|
87
80
|
result += '()'
|
88
81
|
|
89
82
|
elsif state == 'link_url_started'
|
90
|
-
prev_state = state
|
91
|
-
state = 'default'
|
83
|
+
prev_state, state = change_state(c, state, 'default')
|
92
84
|
link_url = stack
|
93
85
|
result += link(link_text, link_url)
|
94
86
|
|
95
87
|
else
|
88
|
+
result += c
|
96
89
|
end
|
97
90
|
else
|
98
91
|
if state == 'default'
|
99
92
|
result += c
|
100
93
|
else
|
101
94
|
if state == 'first_asterisk_detected'
|
102
|
-
prev_state = state
|
103
|
-
state = 'italic_started'
|
95
|
+
prev_state, state = change_state(c, state, 'italic_started')
|
104
96
|
stack = ''
|
105
97
|
|
106
98
|
elsif state == 'second_asterisk_detected'
|
107
|
-
prev_state = state
|
108
|
-
state = 'bold_started'
|
99
|
+
prev_state, state = change_state(c, state, 'bold_started')
|
109
100
|
stack = ''
|
110
101
|
|
111
102
|
elsif state == 'third_asterisk_detected'
|
112
|
-
prev_state = state
|
113
|
-
state = 'bold_and_italic_started'
|
103
|
+
prev_state, state = change_state(c, state, 'bold_and_italic_started')
|
114
104
|
stack = ''
|
115
105
|
|
116
106
|
elsif state == 'first_asterisk_after_bold_detected'
|
117
|
-
prev_state = state
|
118
|
-
state = 'bold_started'
|
107
|
+
prev_state, state = change_state(c, state, 'bold_started')
|
119
108
|
|
120
109
|
elsif state == 'first_asterisk_after_bold_and_italic_detected'
|
121
|
-
prev_state = state
|
122
|
-
state = 'bold_and_italic_started'
|
110
|
+
prev_state, state = change_state(c, state, 'bold_and_italic_started')
|
123
111
|
|
124
112
|
elsif state == 'second_asterisk_after_bold_and_italic_detected'
|
125
|
-
prev_state = state
|
126
|
-
state = 'bold_and_italic_started'
|
113
|
+
prev_state, state = change_state(c, state, 'bold_and_italic_started')
|
127
114
|
|
128
115
|
elsif state == 'square_bracket_left_detected'
|
129
|
-
prev_state = state
|
130
|
-
state = 'link_text_started'
|
116
|
+
prev_state, state = change_state(c, state, 'link_text_started')
|
131
117
|
stack = ''
|
132
118
|
|
133
119
|
elsif state == 'square_bracket_right_detected'
|
134
|
-
prev_state = state
|
135
|
-
state = 'default'
|
120
|
+
prev_state, state = change_state(c, state, 'default')
|
136
121
|
result += stack + c
|
137
122
|
c = ''
|
138
123
|
|
139
124
|
elsif state == 'brace_left_detected'
|
140
|
-
prev_state = state
|
141
|
-
state = 'link_url_started'
|
125
|
+
prev_state, state = change_state(c, state, 'link_url_started')
|
142
126
|
stack = ''
|
143
127
|
|
144
128
|
else
|
@@ -151,6 +135,11 @@ class TextLine
|
|
151
135
|
return result
|
152
136
|
end
|
153
137
|
|
138
|
+
def change_state(c, cur_state, new_state)
|
139
|
+
# puts "[#{c}] Transition: #{cur_state} --> #{new_state}"
|
140
|
+
return cur_state, new_state
|
141
|
+
end
|
142
|
+
|
154
143
|
def italic(str)
|
155
144
|
"<i>#{str}</i>"
|
156
145
|
end
|
@@ -164,6 +153,31 @@ class TextLine
|
|
164
153
|
end
|
165
154
|
|
166
155
|
def link(link_text, link_url)
|
167
|
-
|
156
|
+
|
157
|
+
# define default result first
|
158
|
+
result = "<a href=\"#{link_url}\" class=\"external\">#{link_text}</a>"
|
159
|
+
|
160
|
+
lazy_doc_id, anchor = nil, nil
|
161
|
+
|
162
|
+
if res = /(\w+)[.]md$/.match(link_url) #link
|
163
|
+
lazy_doc_id = res[1].to_s.downcase
|
164
|
+
|
165
|
+
elsif res = /(\w*)[.]md(#.*)$/.match(link_url) # link with anchor
|
166
|
+
if res && res.length > 2
|
167
|
+
lazy_doc_id = res[1]
|
168
|
+
anchor = res[2]
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
if lazy_doc_id
|
173
|
+
if @@lazy_doc_id_dict.has_key?(lazy_doc_id)
|
174
|
+
if anchor
|
175
|
+
result = "<a href=\".\\..\\#{lazy_doc_id}\\#{lazy_doc_id}.html#{anchor}\" class=\"external\">#{link_text}</a>"
|
176
|
+
else
|
177
|
+
result = "<a href=\".\\..\\#{lazy_doc_id}\\#{lazy_doc_id}.html\" class=\"external\">#{link_text}</a>"
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
return result
|
168
182
|
end
|
169
183
|
end
|
@@ -25,7 +25,11 @@ class BaseDocument
|
|
25
25
|
file_data = file.readlines
|
26
26
|
file.close
|
27
27
|
|
28
|
-
|
28
|
+
if @id == 'index'
|
29
|
+
output_file_path += "#{@id}.html"
|
30
|
+
else
|
31
|
+
output_file_path += "#{@id}/#{@id}.html"
|
32
|
+
end
|
29
33
|
file = File.open( output_file_path, "w" )
|
30
34
|
file_data.each do |s|
|
31
35
|
if s.include?('{{CONTENT}}')
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require_relative "base_document"
|
2
|
+
|
3
|
+
class Index < BaseDocument
|
4
|
+
|
5
|
+
attr_accessor :items
|
6
|
+
attr_accessor :project
|
7
|
+
|
8
|
+
def initialize(project)
|
9
|
+
@items = Array.new
|
10
|
+
@project = project
|
11
|
+
|
12
|
+
@title = "Document Index"
|
13
|
+
@id = "index"
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_console
|
17
|
+
puts "\e[36m" + "Index: " + @id + "\e[0m"
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_html(output_file_path)
|
21
|
+
|
22
|
+
html_rows = Array.new
|
23
|
+
|
24
|
+
html_rows.append('')
|
25
|
+
s = "<h1>#{@title}</h1>\n"
|
26
|
+
|
27
|
+
# Specifications
|
28
|
+
s = "<h2>Specifications</h2>\n"
|
29
|
+
s += "<table class=\"controlled\">\n"
|
30
|
+
s += "\t<thead>\n"
|
31
|
+
s += "\t\t<th>Title</th>\n"
|
32
|
+
s += "\t\t<th>Items</th>\n"
|
33
|
+
s += "\t\t<th>Items<br>w/ Uplinks</th>\n"
|
34
|
+
s += "\t\t<th>Items<br>w/ Downlinks</th>\n"
|
35
|
+
s += "\t\t<th>Covered<br>by Tests</th>\n"
|
36
|
+
s += "\t\t<th>Duplicated<br>ids</th>\n"
|
37
|
+
s += "\t\t<th>Last Used<br>id</th>\n"
|
38
|
+
s += "</thead>\n"
|
39
|
+
html_rows.append s
|
40
|
+
|
41
|
+
sorted_items = @project.specifications.sort_by { |w| w.id }
|
42
|
+
|
43
|
+
sorted_items.each do |doc|
|
44
|
+
s = "\t<tr>\n"
|
45
|
+
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"
|
46
|
+
s += "\t\t<td class=\"item_id\" style='width: 7%;'>#{doc.controlled_items.length.to_s}</td>\n"
|
47
|
+
s += "\t\t<td class=\"item_id\" style='width: 7%;'>#{doc.items_with_uplinks_number.to_s}</td>\n"
|
48
|
+
s += "\t\t<td class=\"item_id\" style='width: 7%;'>#{doc.items_with_downlinks_number.to_s}</td>\n"
|
49
|
+
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
|
+
s += "\t\t<td class=\"item_id\" style='width: 7%;'>#{doc.last_used_id.to_s}</td>\n"
|
52
|
+
s += "</tr>\n"
|
53
|
+
html_rows.append s
|
54
|
+
end
|
55
|
+
html_rows.append "</table>\n"
|
56
|
+
|
57
|
+
# Traceability Matrices
|
58
|
+
s = "<h2>Traceability Matrices</h2>\n"
|
59
|
+
s += "<table class=\"controlled\">\n"
|
60
|
+
s += "\t<thead>\n"
|
61
|
+
s += "\t\t<th>Title</th>\n"
|
62
|
+
s += "\t\t<th>Top Document</th>\n"
|
63
|
+
s += "\t\t<th>Bottom Document</th>\n"
|
64
|
+
s += "</thead>\n"
|
65
|
+
html_rows.append s
|
66
|
+
|
67
|
+
sorted_items = @project.traceability_matrices.sort_by { |w| w.id }
|
68
|
+
|
69
|
+
sorted_items.each do |doc|
|
70
|
+
s = "\t<tr>\n"
|
71
|
+
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"
|
72
|
+
s += "\t\t<td class=\"item_text\" style='width: 25%; padding: 5px;'>#{doc.top_doc.title}</td>\n"
|
73
|
+
s += "\t\t<td class=\"item_text\" style='width: 25%; padding: 5px;'>#{doc.bottom_doc.title}</td>\n"
|
74
|
+
s += "</tr>\n"
|
75
|
+
html_rows.append s
|
76
|
+
end
|
77
|
+
html_rows.append "</table>\n"
|
78
|
+
|
79
|
+
# Coverage Matrices
|
80
|
+
if @project.coverage_matrices.length > 0
|
81
|
+
s = "<h2>Coverage Matrices</h2>\n"
|
82
|
+
s += "<table class=\"controlled\">\n"
|
83
|
+
s += "\t<thead>\n"
|
84
|
+
s += "\t\t<th>Title</th>\n"
|
85
|
+
s += "\t\t<th>Specification Covered</th>\n"
|
86
|
+
s += "</thead>\n"
|
87
|
+
html_rows.append s
|
88
|
+
|
89
|
+
sorted_items = @project.coverage_matrices.sort_by { |w| w.id }
|
90
|
+
|
91
|
+
sorted_items.each do |doc|
|
92
|
+
s = "\t<tr>\n"
|
93
|
+
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"
|
94
|
+
s += "\t\t<td class=\"item_text\" style='width: 25%; padding: 5px;'>#{doc.top_doc.title}</td>\n"
|
95
|
+
s += "</tr>\n"
|
96
|
+
html_rows.append s
|
97
|
+
end
|
98
|
+
html_rows.append "</table>\n"
|
99
|
+
end
|
100
|
+
|
101
|
+
self.save_html_to_file(html_rows, nil, output_file_path)
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
|
107
|
+
end
|
@@ -30,7 +30,7 @@ class Specification < BaseDocument
|
|
30
30
|
@last_used_id_number = 0
|
31
31
|
|
32
32
|
@id = File.basename(fele_path, File.extname(fele_path)).downcase
|
33
|
-
@up_link_doc_id =
|
33
|
+
@up_link_doc_id = Hash.new
|
34
34
|
end
|
35
35
|
|
36
36
|
def to_console
|
@@ -67,7 +67,7 @@ class Specification < BaseDocument
|
|
67
67
|
|
68
68
|
@items.each do |item|
|
69
69
|
a = item.to_html
|
70
|
-
a = adjust_internal_links(a, nav_pane.specifications)
|
70
|
+
#a = adjust_internal_links(a, nav_pane.specifications)
|
71
71
|
html_rows.append a
|
72
72
|
end
|
73
73
|
|
@@ -5,16 +5,23 @@ class Traceability < BaseDocument
|
|
5
5
|
attr_accessor :top_doc
|
6
6
|
attr_accessor :bottom_doc
|
7
7
|
attr_accessor :items
|
8
|
+
attr_accessor :is_agregated
|
8
9
|
|
9
|
-
def initialize(top_doc, bottom_doc)
|
10
|
+
def initialize(top_doc, bottom_doc, is_agregated)
|
10
11
|
|
11
12
|
@top_doc = top_doc
|
12
13
|
@bottom_doc = bottom_doc
|
14
|
+
@is_agregated = is_agregated
|
13
15
|
|
14
16
|
@items = Array.new
|
15
17
|
@headings = Array.new
|
16
18
|
|
17
|
-
@
|
19
|
+
if @is_agregated
|
20
|
+
@id = top_doc.id + "-all"
|
21
|
+
else
|
22
|
+
@id = top_doc.id + "-" + bottom_doc.id
|
23
|
+
end
|
24
|
+
|
18
25
|
@title = "Traceability Matrix: " + @id
|
19
26
|
end
|
20
27
|
|
@@ -46,24 +53,49 @@ class Traceability < BaseDocument
|
|
46
53
|
|
47
54
|
def render_table_row(top_item)
|
48
55
|
s = ""
|
56
|
+
top_f_text = top_item.format_string( top_item.text )
|
57
|
+
|
49
58
|
if top_item.down_links
|
50
|
-
|
51
|
-
|
59
|
+
|
60
|
+
if @is_agregated
|
61
|
+
|
62
|
+
if top_item.down_links.length > 1
|
63
|
+
id_color = "style='background-color: #fff8c5;'"
|
64
|
+
else
|
65
|
+
id_color = ""
|
66
|
+
end
|
67
|
+
|
68
|
+
top_item.down_links.each do |bottom_item|
|
69
|
+
bottom_f_text = bottom_item.format_string( bottom_item.text )
|
70
|
+
s += "\t<tr>\n"
|
71
|
+
s += "\t\t<td class=\"item_id\" #{id_color}><a href=\"./../#{top_item.parent_doc.id}/#{top_item.parent_doc.id}.html##{top_item.id}\" class=\"external\">#{top_item.id}</a></td>\n"
|
72
|
+
s += "\t\t<td class=\"item_text\" style='width: 42%;'>#{top_f_text}</td>\n"
|
73
|
+
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"
|
74
|
+
s += "\t\t<td class=\"item_text\" style='width: 42%;'>#{bottom_f_text}</td>\n"
|
75
|
+
s += "\t</tr>\n"
|
76
|
+
end
|
77
|
+
|
52
78
|
else
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
79
|
+
top_item.down_links.each do |bottom_item|
|
80
|
+
|
81
|
+
id_color = ""
|
82
|
+
|
83
|
+
if bottom_item.parent_doc.id == @bottom_doc.id
|
84
|
+
|
85
|
+
bottom_f_text = bottom_item.format_string( bottom_item.text )
|
86
|
+
s += "\t<tr>\n"
|
87
|
+
s += "\t\t<td class=\"item_id\" #{id_color}><a href=\"./../#{top_item.parent_doc.id}/#{top_item.parent_doc.id}.html##{top_item.id}\" class=\"external\">#{top_item.id}</a></td>\n"
|
88
|
+
s += "\t\t<td class=\"item_text\" style='width: 42%;'>#{top_f_text}</td>\n"
|
89
|
+
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"
|
90
|
+
s += "\t\t<td class=\"item_text\" style='width: 42%;'>#{bottom_f_text}</td>\n"
|
91
|
+
s += "\t</tr>\n"
|
92
|
+
end
|
93
|
+
end
|
62
94
|
end
|
63
95
|
else
|
64
96
|
s += "\t<tr>\n"
|
65
97
|
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"
|
66
|
-
s += "\t\t<td class=\"item_text\" style='width: 42%;'>#{
|
98
|
+
s += "\t\t<td class=\"item_text\" style='width: 42%;'>#{top_f_text}</td>\n"
|
67
99
|
s += "\t\t<td class=\"item_id\"></td>\n"
|
68
100
|
s += "\t\t<td class=\"item_text\" style='width: 42%;'></td>\n"
|
69
101
|
s += "\t</tr>\n"
|
data/lib/almirah/project.rb
CHANGED
@@ -3,20 +3,29 @@ require_relative "doc_fabric"
|
|
3
3
|
require_relative "navigation_pane"
|
4
4
|
require_relative "doc_types/traceability"
|
5
5
|
require_relative "doc_types/coverage"
|
6
|
+
require_relative "doc_types/index"
|
6
7
|
|
7
8
|
class Project
|
8
9
|
|
9
10
|
attr_accessor :specifications
|
10
11
|
attr_accessor :protocols
|
12
|
+
attr_accessor :traceability_matrices
|
13
|
+
attr_accessor :coverage_matrices
|
11
14
|
attr_accessor :project_root_directory
|
12
15
|
attr_accessor :specifications_dictionary
|
16
|
+
attr_accessor :index
|
17
|
+
attr_accessor :project
|
13
18
|
|
14
19
|
def initialize(path)
|
15
20
|
@project_root_directory = path
|
16
21
|
@specifications = Array.new
|
17
22
|
@protocols = Array.new
|
23
|
+
@traceability_matrices = Array.new
|
24
|
+
@coverage_matrices = Array.new
|
18
25
|
@specifications_dictionary = Hash.new
|
19
|
-
|
26
|
+
@index = nil
|
27
|
+
@project = self
|
28
|
+
|
20
29
|
FileUtils.remove_dir(@project_root_directory + "/build", true)
|
21
30
|
end
|
22
31
|
|
@@ -26,8 +35,12 @@ class Project
|
|
26
35
|
parse_all_protocols
|
27
36
|
link_all_specifications
|
28
37
|
link_all_protocols
|
29
|
-
|
38
|
+
create_index
|
39
|
+
render_all_specifications(@specifications)
|
40
|
+
render_all_specifications(@traceability_matrices)
|
41
|
+
render_all_specifications(@coverage_matrices)
|
30
42
|
render_all_protocols
|
43
|
+
render_index
|
31
44
|
end
|
32
45
|
|
33
46
|
def specifications_and_results( test_run )
|
@@ -36,13 +49,41 @@ class Project
|
|
36
49
|
parse_test_run test_run
|
37
50
|
link_all_specifications
|
38
51
|
link_all_protocols
|
39
|
-
|
52
|
+
create_index
|
53
|
+
render_all_specifications(@specifications)
|
54
|
+
render_all_specifications(@traceability_matrices)
|
55
|
+
render_all_specifications(@coverage_matrices)
|
40
56
|
render_all_protocols
|
57
|
+
render_index
|
58
|
+
end
|
59
|
+
|
60
|
+
def transform( file_extension )
|
61
|
+
transform_all_specifications file_extension
|
62
|
+
end
|
63
|
+
|
64
|
+
def transform_all_specifications( file_extension )
|
65
|
+
|
66
|
+
path = @project_root_directory
|
67
|
+
|
68
|
+
# find all specifications
|
69
|
+
Dir.glob( "#{@project_root_directory}/specifications/**/*.md" ).each do |f|
|
70
|
+
puts f
|
71
|
+
# make a copy with another extention to preserve the content
|
72
|
+
f_directory = File.dirname(f)
|
73
|
+
f_name = File.basename(f, File.extname(f)).downcase + "._md"
|
74
|
+
FileUtils.copy_file( f, "#{f_directory}/#{f_name}")
|
75
|
+
# transform the original one
|
76
|
+
# but do nothing for now - TODO
|
77
|
+
end
|
41
78
|
end
|
42
79
|
|
43
|
-
def parse_all_specifications
|
80
|
+
def parse_all_specifications
|
81
|
+
# do a lasy pass first to get the list of documents id
|
82
|
+
Dir.glob( "#{@project_root_directory}/specifications/**/*.md" ).each do |f|
|
83
|
+
DocFabric.add_lazy_doc_id(f)
|
84
|
+
end
|
85
|
+
# parse documents in the second pass
|
44
86
|
Dir.glob( "#{@project_root_directory}/specifications/**/*.md" ).each do |f|
|
45
|
-
puts "Spec: " + f
|
46
87
|
doc = DocFabric.create_specification(f)
|
47
88
|
@specifications.append(doc)
|
48
89
|
end
|
@@ -68,13 +109,14 @@ class Project
|
|
68
109
|
combList = @specifications.combination(2)
|
69
110
|
combList.each do |c|
|
70
111
|
link_two_specifications(c[0], c[1])
|
112
|
+
# puts "Link: #{c[0].id} - #{c[1].id}"
|
71
113
|
end
|
72
114
|
end
|
73
115
|
|
74
116
|
def link_all_protocols
|
75
117
|
@protocols.each do |p|
|
76
118
|
@specifications.each do |s|
|
77
|
-
if s.id
|
119
|
+
if p.up_link_doc_id.has_key?(s.id.to_s)
|
78
120
|
link_protocol_to_spec(p,s)
|
79
121
|
end
|
80
122
|
end
|
@@ -83,17 +125,16 @@ class Project
|
|
83
125
|
|
84
126
|
def link_two_specifications(doc_A, doc_B)
|
85
127
|
|
86
|
-
if doc_A.id
|
128
|
+
if doc_B.up_link_doc_id.has_key?(doc_A.id.to_s)
|
87
129
|
top_document = doc_A
|
88
130
|
bottom_document = doc_B
|
89
|
-
elsif doc_B.id
|
131
|
+
elsif doc_A.up_link_doc_id.has_key?(doc_B.id.to_s)
|
90
132
|
top_document = doc_B
|
91
133
|
bottom_document = doc_A
|
92
134
|
else
|
93
|
-
puts "No Links"
|
94
135
|
return # no links
|
95
136
|
end
|
96
|
-
|
137
|
+
#puts "Link: #{doc_A.id} - #{doc_B.id}"
|
97
138
|
bottom_document.controlled_items.each do |item|
|
98
139
|
|
99
140
|
if top_document.dictionary.has_key?(item.up_link.to_s)
|
@@ -108,8 +149,8 @@ class Project
|
|
108
149
|
end
|
109
150
|
end
|
110
151
|
# create treceability document
|
111
|
-
trx = Traceability.new top_document, bottom_document
|
112
|
-
@
|
152
|
+
trx = Traceability.new top_document, bottom_document, false
|
153
|
+
@traceability_matrices.append trx
|
113
154
|
end
|
114
155
|
|
115
156
|
def link_protocol_to_spec(protocol, specification)
|
@@ -132,19 +173,23 @@ class Project
|
|
132
173
|
end
|
133
174
|
# create coverage document
|
134
175
|
trx = Coverage.new top_document
|
135
|
-
@
|
176
|
+
@coverage_matrices.append trx
|
177
|
+
end
|
178
|
+
|
179
|
+
def create_index
|
180
|
+
@index = Index.new( @project )
|
136
181
|
end
|
137
182
|
|
138
|
-
def render_all_specifications
|
183
|
+
def render_all_specifications(spec_list)
|
139
184
|
|
140
185
|
# create a sidebar first
|
141
|
-
nav_pane = NavigationPane.new(@specifications)
|
186
|
+
# nav_pane = NavigationPane.new(@specifications)
|
142
187
|
|
143
188
|
pass = @project_root_directory
|
144
189
|
|
145
190
|
FileUtils.mkdir_p(pass + "/build/specifications")
|
146
191
|
|
147
|
-
|
192
|
+
spec_list.each do |doc|
|
148
193
|
|
149
194
|
doc.to_console
|
150
195
|
|
@@ -157,14 +202,14 @@ class Project
|
|
157
202
|
FileUtils.copy_entry( img_src_dir, img_dst_dir )
|
158
203
|
end
|
159
204
|
|
160
|
-
doc.to_html(
|
205
|
+
doc.to_html( nil, "#{pass}/build/specifications/" )
|
161
206
|
end
|
162
207
|
end
|
163
208
|
|
164
209
|
def render_all_protocols
|
165
210
|
|
166
211
|
# create a sidebar first
|
167
|
-
nav_pane = NavigationPane.new(@specifications)
|
212
|
+
# nav_pane = NavigationPane.new(@specifications)
|
168
213
|
|
169
214
|
pass = @project_root_directory
|
170
215
|
|
@@ -182,7 +227,17 @@ class Project
|
|
182
227
|
FileUtils.copy_entry( img_src_dir, img_dst_dir )
|
183
228
|
end
|
184
229
|
|
185
|
-
doc.to_html(
|
230
|
+
doc.to_html( nil, "#{pass}/build/tests/protocols/" )
|
186
231
|
end
|
187
232
|
end
|
233
|
+
|
234
|
+
def render_index
|
235
|
+
|
236
|
+
path = @project_root_directory
|
237
|
+
|
238
|
+
doc = @index
|
239
|
+
doc.to_console
|
240
|
+
|
241
|
+
doc.to_html("#{path}/build/")
|
242
|
+
end
|
188
243
|
end
|
@@ -93,6 +93,7 @@
|
|
93
93
|
border: 1px solid #bbb;
|
94
94
|
}
|
95
95
|
table.controlled td {
|
96
|
+
padding: 4px;
|
96
97
|
text-align:center;
|
97
98
|
vertical-align:middle;
|
98
99
|
padding-right:10px;
|
@@ -197,8 +198,8 @@ function closeNav() {
|
|
197
198
|
</head>
|
198
199
|
<body>
|
199
200
|
<div id="top_nav">
|
200
|
-
<a href="
|
201
|
-
|
201
|
+
<a href="./../../index.html"><span><i class="fa fa-home" aria-hidden="true"></i></span> Home</a>
|
202
|
+
<!--a href="javascript:void(0)"> About</a-->
|
202
203
|
</div>
|
203
204
|
<div id="main">
|
204
205
|
<div id="nav_pane">
|
data/lib/almirah.rb
CHANGED
@@ -2,8 +2,8 @@ require "thor"
|
|
2
2
|
require_relative "almirah/project"
|
3
3
|
|
4
4
|
class CLI < Thor
|
5
|
-
desc "please <project_folder>", "say <project_folder>"
|
6
5
|
option :results
|
6
|
+
desc "please <project_folder>", "say <project_folder>"
|
7
7
|
def please(project_folder)
|
8
8
|
a = Almirah.new project_folder
|
9
9
|
if options[:results]
|
@@ -12,6 +12,12 @@ class CLI < Thor
|
|
12
12
|
a.default
|
13
13
|
end
|
14
14
|
end
|
15
|
+
|
16
|
+
desc "transform <project_folder>", "say <project_folder>"
|
17
|
+
def transform(project_folder)
|
18
|
+
a = Almirah.new project_folder
|
19
|
+
a.transform "docx"
|
20
|
+
end
|
15
21
|
end
|
16
22
|
|
17
23
|
class Almirah
|
@@ -30,6 +36,10 @@ class Almirah
|
|
30
36
|
@project.specifications_and_results test_run
|
31
37
|
end
|
32
38
|
|
39
|
+
def transform( file_extension )
|
40
|
+
@project.transform file_extension
|
41
|
+
end
|
42
|
+
|
33
43
|
def default()
|
34
44
|
@project.specifications_and_protocols
|
35
45
|
end
|
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.0
|
4
|
+
version: 0.1.0
|
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-
|
11
|
+
date: 2024-03-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
|
@@ -33,6 +33,7 @@ files:
|
|
33
33
|
- lib/almirah/doc_items/text_line.rb
|
34
34
|
- lib/almirah/doc_types/base_document.rb
|
35
35
|
- lib/almirah/doc_types/coverage.rb
|
36
|
+
- lib/almirah/doc_types/index.rb
|
36
37
|
- lib/almirah/doc_types/protocol.rb
|
37
38
|
- lib/almirah/doc_types/specification.rb
|
38
39
|
- lib/almirah/doc_types/traceability.rb
|