Almirah 0.0.9 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9e500204a8575e500989c7d86e4db4dff7a6247b14d3768904620be7a3cef356
4
- data.tar.gz: a12d76101a33fc1938c0c42d361f84ae9a8c796684becd1567e154e67f345cad
3
+ metadata.gz: 4194e03230075235a57516fed73b44215dde4a7cb42474b641bdbd7ce8a6ad55
4
+ data.tar.gz: f1a4f05ca5b4cf643cd179019c67cb08ea69c8876a235dfa368e99ec782ab21f
5
5
  SHA512:
6
- metadata.gz: eff42c3d45f0be71488484ce864740c5363e9169450d32469b9044136ea47af2989b32c4cb526c176c4d4721e60be0c5f484db8ed2245285eb042187a9c5df57
7
- data.tar.gz: 2e5c4887b584428a71db8cbd33d244242c90df9b7b02aca8804f72f97fb017dfebc4aa8ff2ae52f924ae9895f7ac1b075cac2407ba84888db55cd36d97984344
6
+ metadata.gz: 56dc9e44de93dccbaf9424d6b654c00e08591b9cdcd62b5061d3356441b68f3c5b6a61778cc9d78bcf277fceb8c25d1b6f9bf34ca6f1a0a0f0284ce361d346a2
7
+ data.tar.gz: 59790d27191f78845e8b7ca8e19f0c26858234dbb419f248de5034a1aac3451ed9afbcc26905fa062c2efc13b0613f3a60e2b9e57b590c3f6cd01ff55df83809
@@ -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,12 +99,13 @@ 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
 
88
106
  item = ControlledParagraph.new( text, id )
89
107
  item.parent_doc = doc
108
+ item.parent_heading = doc.headings[-1]
90
109
  if up_link
91
110
  item.up_link = up_link
92
111
  doc.items_with_uplinks_number += 1 #for statistics
@@ -134,7 +153,7 @@ class DocFabric
134
153
  row = res[2]
135
154
 
136
155
  if tempMdList
137
- tempMdList.addRow(row)
156
+ tempMdList.addRow(s)
138
157
  else
139
158
  item = MarkdownList.new(false)
140
159
  item.addRow(s)
@@ -152,7 +171,7 @@ class DocFabric
152
171
  row = res[1]
153
172
 
154
173
  if tempMdList
155
- tempMdList.addRow(row)
174
+ tempMdList.addRow(s)
156
175
  else
157
176
  item = MarkdownList.new(true)
158
177
  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>Text</th> <th>UL</th> <th>DL</th> <th>COV</th> </thead>\n"
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,20 @@ 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
- 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"
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\">"
47
+ s += "<div id=\"DL_#{@id}\" style=\"display: block;\">"
48
+ s += "<a href=\"#\" onclick=\"downlink_OnClick(this.parentElement); return false;\" class=\"external\">#{@down_links.length}</a>"
49
+ s += "</div>"
50
+ s += "<div id=\"DLS_#{@id}\" style=\"display: none;\">"
51
+ @down_links.each do |lnk|
52
+ s += "\t\t\t<a href=\"./../#{lnk.parent_doc.id}/#{lnk.parent_doc.id}.html##{lnk.id}\" class=\"external\">#{lnk.id}</a>\n<br>"
53
+ end
54
+ s += "</div>"
55
+ s += "</td>\n"
56
+ end
44
57
  else
45
58
  s += "\t\t<td class=\"item_id\"></td>\n"
46
59
  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
- if @parent_doc.up_link_doc_id == ""
132
- @parent_doc.up_link_doc_id = col.up_link_doc_id
133
- end
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
@@ -2,8 +2,10 @@ require_relative "text_line"
2
2
 
3
3
  class DocItem < TextLine
4
4
  attr_accessor :parent_doc
5
+ attr_accessor :parent_heading
5
6
 
6
7
  @parent_doc = nil
8
+ @parent_heading = nil
7
9
 
8
10
  @@htmlTableRenderInProgress = false
9
11
  end
@@ -4,11 +4,47 @@ class Heading < Paragraph
4
4
 
5
5
  attr_accessor :level
6
6
  attr_accessor :anchor_id
7
+ attr_accessor :section_number
8
+
9
+ @@global_section_number = ""
7
10
 
8
11
  def initialize(text, level)
9
12
  @text = text
10
13
  @level = level
11
14
  @anchor_id = getTextWithoutSpaces()
15
+
16
+ if @@global_section_number = ""
17
+ @@global_section_number = "1"
18
+ for n in 1..(level-1) do
19
+ @@global_section_number += ".1"
20
+ end
21
+ else
22
+ previous_level = @@global_section_number.split(".").length
23
+
24
+ if previous_level == level
25
+
26
+ a = @@global_section_number.split(".")
27
+ a[-1] = (a[-1].to_i() +1).to_s
28
+ @@global_section_number = a.join(".")
29
+
30
+ elsif previous_level < level
31
+
32
+ a = @@global_section_number.split(".")
33
+ a.push("1")
34
+ @@global_section_number = a.join(".")
35
+
36
+ else # previous_level > level
37
+
38
+ a = @@global_section_number.split(".")
39
+ a.pop
40
+ @@global_section_number = a.join(".")
41
+ end
42
+ end
43
+ @section_number = @@global_section_number
44
+ end
45
+
46
+ def get_section_info
47
+ s = @section_number + " " + @text
12
48
  end
13
49
 
14
50
  def to_html
@@ -21,7 +21,7 @@ class Image < DocItem
21
21
  @@htmlTableRenderInProgress = false
22
22
  end
23
23
 
24
- s += "<img src=\"#{@path}\" alt=\"#{@text}\">"
24
+ s += "<p style=\"margin-top: 15px;\"><img src=\"#{@path}\" alt=\"#{@text}\">"
25
25
  return s
26
26
  end
27
27
  end
@@ -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 non_blank?(c)
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 letter?(c)
74
- break
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
- "<a href=\"#{link_url}\" class=\"external\">#{link_text}</a>"
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
- output_file_path += "#{@id}/#{@id}.html"
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}}')
@@ -36,6 +40,8 @@ class BaseDocument
36
40
  if nav_pane
37
41
  file.puts nav_pane.to_html
38
42
  end
43
+ elsif s.include?('{{DOCUMENT_TITLE}}')
44
+ file.puts s.gsub! '{{DOCUMENT_TITLE}}', @title
39
45
  else
40
46
  file.puts s
41
47
  end
@@ -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
@@ -16,7 +16,7 @@ class Protocol < BaseDocument
16
16
  #@dictionary = Hash.new
17
17
 
18
18
  @id = File.basename(fele_path, File.extname(fele_path)).downcase
19
- @up_link_doc_id = ""
19
+ @up_link_doc_id = Hash.new
20
20
  end
21
21
 
22
22
  def to_html(nav_pane, output_file_path)
@@ -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
- @id = top_doc.id + "-" + bottom_doc.id
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
 
@@ -29,7 +36,10 @@ class Traceability < BaseDocument
29
36
  html_rows.append('')
30
37
  s = "<h1>#{@title}</h1>\n"
31
38
  s += "<table class=\"controlled\">\n"
32
- s += "\t<thead> <th>#</th> <th style='font-weight: bold;'>#{@top_doc.title}</th> <th>#</th> <th style='font-weight: bold;'>#{@bottom_doc.title}</th> </thead>\n"
39
+ s += "\t<thead> <th>#</th> <th style='font-weight: bold;'>#{@top_doc.title}</th> "
40
+ s += "<th>#</th> <th style='font-weight: bold;'>#{@bottom_doc.title}</th> "
41
+ s += "<th style='font-weight: bold;'>Document Section</th>"
42
+ s += "</thead>\n"
33
43
  html_rows.append s
34
44
 
35
45
  sorted_items = @top_doc.controlled_items.sort_by { |w| w.id }
@@ -46,26 +56,57 @@ class Traceability < BaseDocument
46
56
 
47
57
  def render_table_row(top_item)
48
58
  s = ""
59
+ top_f_text = top_item.format_string( top_item.text )
60
+
49
61
  if top_item.down_links
50
- if top_item.down_links.length > 1
51
- id_color = "style='background-color: #fff8c5;'"
62
+
63
+ if @is_agregated
64
+
65
+ if top_item.down_links.length > 1
66
+ id_color = "style='background-color: #fff8c5;'"
67
+ else
68
+ id_color = ""
69
+ end
70
+
71
+ top_item.down_links.each do |bottom_item|
72
+ bottom_f_text = bottom_item.format_string( bottom_item.text )
73
+ document_section = bottom_item.parent_heading.get_section_info
74
+ s += "\t<tr>\n"
75
+ 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"
76
+ 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"
78
+ s += "\t\t<td class=\"item_text\" style='width: 34%;'>#{bottom_f_text}</td>\n"
79
+ s += "\t\t<td class=\"item_text\" style='width: 16%;'>#{document_section}</td>\n"
80
+ s += "\t</tr>\n"
81
+ end
82
+
52
83
  else
53
- id_color = ""
54
- end
55
- top_item.down_links.each do |bottom_item|
56
- s += "\t<tr>\n"
57
- 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"
58
- s += "\t\t<td class=\"item_text\" style='width: 42%;'>#{top_item.text}</td>\n"
59
- 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"
60
- s += "\t\t<td class=\"item_text\" style='width: 42%;'>#{bottom_item.text}</td>\n"
61
- s += "\t</tr>\n"
84
+ top_item.down_links.each do |bottom_item|
85
+
86
+ id_color = ""
87
+
88
+ if bottom_item.parent_doc.id == @bottom_doc.id
89
+
90
+ bottom_f_text = bottom_item.format_string( bottom_item.text )
91
+ document_section = bottom_item.parent_heading.get_section_info
92
+
93
+ s += "\t<tr>\n"
94
+ 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"
95
+ s += "\t\t<td class=\"item_text\" style='width: 34%;'>#{top_f_text}</td>\n"
96
+ 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"
97
+ s += "\t\t<td class=\"item_text\" style='width: 34%;'>#{bottom_f_text}</td>\n"
98
+ s += "\t\t<td class=\"item_text\" style='width: 16%;'>#{document_section}</td>\n"
99
+ s += "\t</tr>\n"
100
+ end
101
+ end
62
102
  end
63
103
  else
64
104
  s += "\t<tr>\n"
65
105
  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%;'>#{top_item.text}</td>\n"
106
+ s += "\t\t<td class=\"item_text\" style='width: 34%;'>#{top_f_text}</td>\n"
67
107
  s += "\t\t<td class=\"item_id\"></td>\n"
68
- s += "\t\t<td class=\"item_text\" style='width: 42%;'></td>\n"
108
+ s += "\t\t<td class=\"item_text\" style='width: 34%;'></td>\n"
109
+ s += "\t\t<td class=\"item_text\" style='width: 16%;'></td>\n"
69
110
  s += "\t</tr>\n"
70
111
  end
71
112
  return s
@@ -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
- render_all_specifications
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
- render_all_specifications
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 == p.up_link_doc_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 == doc_B.up_link_doc_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 == doc_A.up_link_doc_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
- @specifications.append trx
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
- @specifications.append trx
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
- @specifications.each do |doc|
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( nav_pane, "#{pass}/build/specifications/" )
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( nav_pane, "#{pass}/build/tests/protocols/" )
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;
@@ -173,6 +174,15 @@
173
174
  font-size: 1.5em;
174
175
  font-family: "Trebuchet MS", Verdana, sans-serif;
175
176
  }
177
+ #top_nav a.split {
178
+ float: right;
179
+ color: white;
180
+ text-align: center;
181
+ padding: 4px 6px;
182
+ text-decoration: none;
183
+ font-size: 1.5em;
184
+ font-family: "Trebuchet MS", Verdana, sans-serif;
185
+ }
176
186
  #top_nav a:hover {
177
187
  background-color: black;
178
188
  color: white;
@@ -193,12 +203,31 @@ function closeNav() {
193
203
  document.getElementById("nav_pane").style.visibility = "hidden";
194
204
  console.log("Mouse Out");
195
205
  }
206
+
207
+ window.onload = (event) => {
208
+ for (var i = 0, n = document.images.length; i < n; i++)
209
+ {
210
+ elem = document.images[i];
211
+ if (elem.width > 640)
212
+ {
213
+ elem.style.width = "640px";
214
+ }
215
+ }
216
+ };
217
+
218
+ function downlink_OnClick(clicked){
219
+ clicked.style.display = 'none';
220
+ id_parts = clicked.id.split("_");
221
+ required_id = "DLS_" + id_parts[1];
222
+ document.getElementById(required_id).style.display = 'block';
223
+ }
196
224
  </script>
197
225
  </head>
198
226
  <body>
199
227
  <div id="top_nav">
200
- <a href="javascript:void(0)" onclick="openNav()"><span><i class="fa fa-bars" aria-hidden="true"></i></span>&nbsp;Navigation</a>
201
- <a href="javascript:void(0)"> About</a>
228
+ <a href="./../../index.html"><span><i class="fa fa-home" aria-hidden="true"></i></span>&nbsp;Home</a>
229
+ <!--a href="javascript:void(0)"> About</a-->
230
+ <a class="split">{{DOCUMENT_TITLE}}</a>
202
231
  </div>
203
232
  <div id="main">
204
233
  <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.9
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Oleksandr Ivanov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-03-03 00:00:00.000000000 Z
11
+ date: 2024-03-13 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