Almirah 0.2.4 → 0.2.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/almirah/doc_items/doc_item.rb +16 -14
- data/lib/almirah/doc_items/frontmatter.rb +9 -0
- data/lib/almirah/doc_items/markdown_list.rb +1 -3
- data/lib/almirah/doc_items/markdown_table.rb +1 -3
- data/lib/almirah/doc_items/paragraph.rb +18 -20
- data/lib/almirah/doc_parser.rb +71 -23
- data/lib/almirah/doc_types/base_document.rb +56 -62
- data/lib/almirah/doc_types/coverage.rb +65 -66
- data/lib/almirah/doc_types/index.rb +167 -163
- data/lib/almirah/doc_types/persistent_document.rb +14 -17
- data/lib/almirah/dom/document.rb +6 -0
- data/lib/almirah/project.rb +1 -20
- data/lib/almirah/project_template.rb +298 -0
- data/lib/almirah/search/specifications_db.rb +66 -70
- data/lib/almirah.rb +32 -23
- metadata +27 -5
@@ -1,169 +1,173 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
end
|
60
|
-
s += "</div>"
|
61
|
-
s += "</td>\n"
|
62
|
-
else
|
63
|
-
s += "\t\t<td class=\"item_id\" style='width: 7%;'>#{doc.duplicated_ids_number.to_s}</td>\n"
|
64
|
-
end
|
65
|
-
|
66
|
-
if doc.wrong_links_hash.length >0
|
67
|
-
s += "\t\t<td class=\"item_id\" style='width: 7%; background-color: #fcc;'>"
|
68
|
-
s += "<div id=\"DL_#{doc.id}wl\" style=\"display: block;\">"
|
69
|
-
s += "<a href=\"#\" onclick=\"downlink_OnClick(this.parentElement); return false;\" class=\"external\" title=\"Number of Controlled Paragraphs that link to non-existing items\">#{doc.wrong_links_hash.length.to_s}</a>"
|
70
|
-
s += "</div>"
|
71
|
-
s += "<div id=\"DLS_#{doc.id}wl\" style=\"display: none;\">"
|
72
|
-
doc.wrong_links_hash.each do |wrong_lnk, item|
|
73
|
-
s += "\t\t\t<a href=\"./specifications/#{doc.id}/#{doc.id}.html##{item.id}\" class=\"external\" title=\"Controlled Paragraphs that link to non-existing items\">#{wrong_lnk}</a>\n<br>"
|
74
|
-
end
|
75
|
-
s += "</div>"
|
76
|
-
s += "</td>\n"
|
77
|
-
else
|
78
|
-
s += "\t\t<td class=\"item_id\" style='width: 7%;'>#{doc.wrong_links_hash.length.to_s}</td>\n"
|
79
|
-
end
|
80
|
-
|
81
|
-
if doc.todo_blocks.length >0
|
82
|
-
color = "background-color: #fcc;"
|
83
|
-
else
|
84
|
-
color = ""
|
85
|
-
end
|
86
|
-
s += "\t\t<td class=\"item_id\" style='width: 7%; #{color}'>#{doc.todo_blocks.length.to_s}</td>\n"
|
87
|
-
s += "\t\t<td class=\"item_id\" style='width: 7%;'>#{doc.last_used_id.to_s}</td>\n"
|
88
|
-
s += "</tr>\n"
|
89
|
-
html_rows.append s
|
90
|
-
end
|
91
|
-
html_rows.append "</table>\n"
|
92
|
-
|
93
|
-
# Traceability Matrices
|
94
|
-
s = "<h2>Traceability Matrices</h2>\n"
|
95
|
-
s += "<table class=\"controlled\">\n"
|
96
|
-
s += "\t<thead>\n"
|
97
|
-
s += "\t\t<th title=\"Traceability Matrix Title\">Title</th>\n"
|
98
|
-
s += "\t\t<th title=\"The ratio of Controlled Paragraphs mentioned in other documents and not-mentioned ones\">Coverage</th>\n"
|
99
|
-
s += "\t\t<th title=\"Document, that contains Cotroled Paragraphs to be referenced in Bottom document(s)\">Top Document</th>\n"
|
100
|
-
s += "\t\t<th title=\"Document(s), that contains references to Controlled Paragraphs from the Top Document\">Bottom Document</th>\n"
|
101
|
-
s += "</thead>\n"
|
102
|
-
html_rows.append s
|
103
|
-
|
104
|
-
sorted_items = @project.traceability_matrices.sort_by { |w| w.id }
|
105
|
-
# buble-up design inputs
|
106
|
-
design_inputs = []
|
107
|
-
others = []
|
108
|
-
sorted_items.each do |doc|
|
109
|
-
if doc.bottom_doc
|
110
|
-
others.append doc
|
111
|
-
else
|
112
|
-
design_inputs.append doc
|
113
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'base_document'
|
4
|
+
|
5
|
+
class Index < BaseDocument # rubocop:disable Metrics/ClassLength,Style/Documentation
|
6
|
+
attr_accessor :project
|
7
|
+
|
8
|
+
def initialize(project)
|
9
|
+
super()
|
10
|
+
@project = project
|
11
|
+
@title = 'Document Index'
|
12
|
+
@id = 'index'
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_console
|
16
|
+
puts "\e[36mIndex: #{@id}\e[0m"
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_html(output_file_path) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
|
20
|
+
html_rows = []
|
21
|
+
|
22
|
+
html_rows.append('')
|
23
|
+
s = "<h1>#{@title}</h1>\n"
|
24
|
+
|
25
|
+
# Specifications
|
26
|
+
s = "<h2>Specifications</h2>\n"
|
27
|
+
s += "<table class=\"controlled\">\n"
|
28
|
+
s += "\t<thead>\n"
|
29
|
+
s += "\t\t<th title=\"Document title\">Title</th>\n"
|
30
|
+
s += "\t\t<th title=\"Number of Controlled Paragraphs\">Items</th>\n"
|
31
|
+
s += "\t\t<th title=\"Number of Controlled Paragraphs with up-links\">Items<br>w/ Up-links</th>\n"
|
32
|
+
s += "\t\t<th title=\"Number of references from other documents\">Items<br>w/ Down-links</th>\n"
|
33
|
+
s += "\t\t<th title=\"Number of Controlled Paragraphs mentioned in Test Cases\">Covered <br>by Tests</th>\n"
|
34
|
+
s += "\t\t<th title=\"Number of Controlled Paragraphs that have the same ID\">Duplicated<br>IDs</th>\n"
|
35
|
+
s += "\t\t<th title=\"Number of Controlled Paragraphs that link to non-existing items\">Wrong<br>links</th>\n"
|
36
|
+
s += "\t\t<th title=\"Number of 'TODO:' blocks in document\">TODOs</th>\n"
|
37
|
+
s += "\t\t<th title=\"The last Controlled Paragraph sequence number (ID) used in the document\">Last Used<br>ID</th>\n"
|
38
|
+
s += "</thead>\n"
|
39
|
+
html_rows.append s
|
40
|
+
|
41
|
+
sorted_items = @project.specifications.sort_by(&:id)
|
42
|
+
|
43
|
+
sorted_items.each do |doc| # rubocop:disable Metrics/BlockLength
|
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\"><i class=\"fa fa-file-text-o\" style='background-color: ##{doc.color};'> </i> #{doc.title}</a></td>\n"
|
46
|
+
s += "\t\t<td class=\"item_id\" style='width: 7%;'>#{doc.controlled_items.length}</td>\n"
|
47
|
+
s += "\t\t<td class=\"item_id\" style='width: 7%;'>#{doc.items_with_uplinks_number}</td>\n"
|
48
|
+
s += "\t\t<td class=\"item_id\" style='width: 7%;'>#{doc.items_with_downlinks_number}</td>\n"
|
49
|
+
s += "\t\t<td class=\"item_id\" style='width: 7%;'>#{doc.items_with_coverage_number}</td>\n"
|
50
|
+
|
51
|
+
if doc.duplicated_ids_number.positive?
|
52
|
+
s += "\t\t<td class=\"item_id\" style='width: 7%; background-color: #fcc;'>"
|
53
|
+
s += "<div id=\"DL_#{doc.id}\" style=\"display: block;\">"
|
54
|
+
s += "<a href=\"#\" onclick=\"downlink_OnClick(this.parentElement); return false;\" class=\"external\" title=\"Number of Controlled Paragraphs that have the same ID\">#{doc.duplicated_ids_number}</a>"
|
55
|
+
s += '</div>'
|
56
|
+
s += "<div id=\"DLS_#{doc.id}\" style=\"display: none;\">"
|
57
|
+
doc.duplicates_list.each do |lnk|
|
58
|
+
s += "\t\t\t<a href=\"./specifications/#{doc.id}/#{doc.id}.html##{lnk.id}\" class=\"external\" title=\"Controlled Paragraph with duplicated ID\">#{lnk.id}</a>\n<br>"
|
114
59
|
end
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
html_rows.append s
|
60
|
+
s += '</div>'
|
61
|
+
s += "</td>\n"
|
62
|
+
else
|
63
|
+
s += "\t\t<td class=\"item_id\" style='width: 7%;'>#{doc.duplicated_ids_number}</td>\n"
|
64
|
+
end
|
65
|
+
|
66
|
+
if !doc.wrong_links_hash.empty?
|
67
|
+
s += "\t\t<td class=\"item_id\" style='width: 7%; background-color: #fcc;'>"
|
68
|
+
s += "<div id=\"DL_#{doc.id}wl\" style=\"display: block;\">"
|
69
|
+
s += "<a href=\"#\" onclick=\"downlink_OnClick(this.parentElement); return false;\" class=\"external\" title=\"Number of Controlled Paragraphs that link to non-existing items\">#{doc.wrong_links_hash.length}</a>"
|
70
|
+
s += '</div>'
|
71
|
+
s += "<div id=\"DLS_#{doc.id}wl\" style=\"display: none;\">"
|
72
|
+
doc.wrong_links_hash.each do |wrong_lnk, item|
|
73
|
+
s += "\t\t\t<a href=\"./specifications/#{doc.id}/#{doc.id}.html##{item.id}\" class=\"external\" title=\"Controlled Paragraphs that link to non-existing items\">#{wrong_lnk}</a>\n<br>"
|
130
74
|
end
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
75
|
+
s += '</div>'
|
76
|
+
s += "</td>\n"
|
77
|
+
else
|
78
|
+
s += "\t\t<td class=\"item_id\" style='width: 7%;'>#{doc.wrong_links_hash.length}</td>\n"
|
79
|
+
end
|
80
|
+
|
81
|
+
color = if !doc.todo_blocks.empty?
|
82
|
+
'background-color: #fcc;'
|
83
|
+
else
|
84
|
+
''
|
85
|
+
end
|
86
|
+
s += "\t\t<td class=\"item_id\" style='width: 7%; #{color}'>#{doc.todo_blocks.length}</td>\n"
|
87
|
+
s += "\t\t<td class=\"item_id\" style='width: 7%;'>#{doc.last_used_id}</td>\n"
|
88
|
+
s += "</tr>\n"
|
89
|
+
html_rows.append s
|
90
|
+
end
|
91
|
+
html_rows.append "</table>\n"
|
92
|
+
|
93
|
+
# Traceability Matrices
|
94
|
+
s = "<h2>Traceability Matrices</h2>\n"
|
95
|
+
s += "<table class=\"controlled\">\n"
|
96
|
+
s += "\t<thead>\n"
|
97
|
+
s += "\t\t<th title=\"Traceability Matrix Title\">Title</th>\n"
|
98
|
+
s += "\t\t<th title=\"The ratio of Controlled Paragraphs mentioned in other documents and not-mentioned ones\">Coverage</th>\n"
|
99
|
+
s += "\t\t<th title=\"Document, that contains Cotroled Paragraphs to be referenced in Bottom document(s)\">Top Document</th>\n"
|
100
|
+
s += "\t\t<th title=\"Document(s), that contains references to Controlled Paragraphs from the Top Document\">Bottom Document</th>\n"
|
101
|
+
s += "</thead>\n"
|
102
|
+
html_rows.append s
|
103
|
+
|
104
|
+
sorted_items = @project.traceability_matrices.sort_by(&:id)
|
105
|
+
# buble-up design inputs
|
106
|
+
design_inputs = []
|
107
|
+
others = []
|
108
|
+
sorted_items.each do |doc|
|
109
|
+
if doc.bottom_doc
|
110
|
+
others.append doc
|
111
|
+
else
|
112
|
+
design_inputs.append doc
|
113
|
+
end
|
114
|
+
end
|
115
|
+
sorted_items = design_inputs + others
|
116
|
+
|
117
|
+
sorted_items.each do |doc|
|
118
|
+
s = "\t<tr>\n"
|
119
|
+
coverage = doc.traced_items.length.to_f / doc.top_doc.controlled_items.length * 100.0
|
120
|
+
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"
|
121
|
+
s += "\t\t<td class=\"item_id\" style='width: 7%;'>#{'%.2f' % coverage}%</td>\n"
|
122
|
+
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"
|
123
|
+
if doc.bottom_doc
|
124
|
+
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"
|
125
|
+
else
|
126
|
+
s += "\t\t<td class=\"item_text\" style='width: 25%; padding: 5px;'><i class=\"fa fa-circle-o\"'> </i> All References</td>\n"
|
127
|
+
end
|
128
|
+
s += "</tr>\n"
|
129
|
+
html_rows.append s
|
130
|
+
end
|
131
|
+
html_rows.append "</table>\n"
|
132
|
+
|
133
|
+
# Coverage Matrices
|
134
|
+
unless @project.coverage_matrices.empty?
|
135
|
+
s = "<h2>Coverage Matrices</h2>\n"
|
136
|
+
s += "<table class=\"controlled\">\n"
|
137
|
+
s += "\t<thead>\n"
|
138
|
+
s += "\t\t<th>Title</th>\n"
|
139
|
+
s += "\t\t<th title=\"The ratio of Controlled Paragraphs mentioned in test protocols and total number of Controlled Paragraphs\">Coverage</th>\n"
|
140
|
+
s += "\t\t<th title=\"Numbers of passed and failed test steps\">Test Results</th>\n"
|
141
|
+
s += "\t\t<th>Specification Covered</th>\n"
|
142
|
+
s += "</thead>\n"
|
143
|
+
html_rows.append s
|
144
|
+
|
145
|
+
sorted_items = @project.coverage_matrices.sort_by(&:id)
|
146
|
+
|
147
|
+
sorted_items.each do |doc|
|
148
|
+
s = "\t<tr>\n"
|
149
|
+
coverage = doc.covered_items.length.to_f / doc.top_doc.controlled_items.length * 100.0
|
150
|
+
|
151
|
+
test_step_color = if doc.failed_steps_number.positive?
|
152
|
+
'background-color: #fcc;'
|
153
|
+
elsif !doc.failed_steps_number.positive? && doc.passed_steps_number.positive?
|
154
|
+
'background-color: #cfc;'
|
155
|
+
else
|
156
|
+
'background-color: #ffffee;'
|
157
|
+
end
|
158
|
+
|
159
|
+
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"
|
160
|
+
s += "\t\t<td class=\"item_id\" style='width: 7%;'>#{'%.2f' % coverage}%</td>\n" # rubocop:disable Style/FormatString
|
161
|
+
s += "\t\t<td class=\"item_id\" style='width: 7%; #{test_step_color}' title='pass/fail'> #{doc.passed_steps_number}/#{doc.failed_steps_number} </td>\n"
|
162
|
+
s += "\t\t<td class=\"item_text\" style='width: 25%; padding: 5px;'>\
|
155
163
|
<i class=\"fa fa-file-text-o\" style='background-color: ##{doc.top_doc.color};'> </i>\
|
156
164
|
#{doc.top_doc.title}</td>\n"
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
end
|
162
|
-
|
163
|
-
self.save_html_to_file(html_rows, nil, output_file_path)
|
164
|
-
|
165
|
+
s += "</tr>\n"
|
166
|
+
html_rows.append s
|
167
|
+
end
|
168
|
+
html_rows.append "</table>\n"
|
165
169
|
end
|
166
170
|
|
167
|
-
|
168
|
-
|
169
|
-
end
|
171
|
+
save_html_to_file(html_rows, nil, output_file_path)
|
172
|
+
end
|
173
|
+
end
|
@@ -1,20 +1,17 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require_relative 'base_document'
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
attr_accessor :controlled_items
|
8
|
-
attr_accessor :headings
|
9
|
-
attr_accessor :up_link_docs
|
5
|
+
class PersistentDocument < BaseDocument # rubocop:disable Style/Documentation
|
6
|
+
attr_accessor :path, :items, :controlled_items, :headings, :up_link_docs, :frontmatter
|
10
7
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
end
|
8
|
+
def initialize(fele_path)
|
9
|
+
super()
|
10
|
+
@path = fele_path
|
11
|
+
@items = []
|
12
|
+
@controlled_items = []
|
13
|
+
@headings = []
|
14
|
+
@up_link_docs = {}
|
15
|
+
@frontmatter = nil
|
16
|
+
end
|
17
|
+
end
|
data/lib/almirah/dom/document.rb
CHANGED
@@ -32,6 +32,8 @@ class Document
|
|
32
32
|
s.parent_section = sections_stack[-1].parent_section
|
33
33
|
sections_stack[-1].parent_section.sections.append(s)
|
34
34
|
sections_stack[-1] = s
|
35
|
+
# for search engine
|
36
|
+
s.heading.parent_heading = s.parent_section.heading
|
35
37
|
|
36
38
|
elsif h.level > sections_stack[-1].heading.level
|
37
39
|
|
@@ -39,6 +41,8 @@ class Document
|
|
39
41
|
s.parent_section = sections_stack[-1]
|
40
42
|
sections_stack[-1].sections.append(s)
|
41
43
|
sections_stack.push s
|
44
|
+
# for search engine
|
45
|
+
s.heading.parent_heading = s.parent_section.heading
|
42
46
|
|
43
47
|
else
|
44
48
|
sections_stack.pop while h.level < sections_stack[-1].heading.level
|
@@ -52,6 +56,8 @@ class Document
|
|
52
56
|
sections_stack[-1].sections.append(s)
|
53
57
|
end
|
54
58
|
sections_stack[-1] = s
|
59
|
+
# for search engine
|
60
|
+
s.heading.parent_heading = s.parent_section.heading
|
55
61
|
end
|
56
62
|
end
|
57
63
|
end
|
data/lib/almirah/project.rb
CHANGED
@@ -69,25 +69,6 @@ class Project # rubocop:disable Metrics/ClassLength,Style/Documentation
|
|
69
69
|
create_search_data
|
70
70
|
end
|
71
71
|
|
72
|
-
def transform(file_extension)
|
73
|
-
transform_all_specifications file_extension
|
74
|
-
end
|
75
|
-
|
76
|
-
def transform_all_specifications(_file_extension)
|
77
|
-
path = @configuration.project_root_directory
|
78
|
-
|
79
|
-
# find all specifications
|
80
|
-
Dir.glob("#{path}/specifications/**/*.md").each do |f|
|
81
|
-
puts f
|
82
|
-
# make a copy with another extention to preserve the content
|
83
|
-
f_directory = File.dirname(f)
|
84
|
-
f_name = File.basename(f, File.extname(f)).downcase + '._md'
|
85
|
-
FileUtils.copy_file(f, "#{f_directory}/#{f_name}")
|
86
|
-
# transform the original one
|
87
|
-
# but do nothing for now - TODO
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
72
|
def parse_all_specifications
|
92
73
|
path = @configuration.project_root_directory
|
93
74
|
# do a lasy pass first to get the list of documents id
|
@@ -250,7 +231,7 @@ class Project # rubocop:disable Metrics/ClassLength,Style/Documentation
|
|
250
231
|
@index = Index.new(@project)
|
251
232
|
end
|
252
233
|
|
253
|
-
def render_all_specifications(spec_list) # rubocop:disable Metrics/
|
234
|
+
def render_all_specifications(spec_list) # rubocop:disable Metrics/MethodLength
|
254
235
|
path = @configuration.project_root_directory
|
255
236
|
|
256
237
|
FileUtils.mkdir_p("#{path}/build/specifications")
|