Almirah 0.2.4 → 0.2.5
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_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")
|