Almirah 0.3.1 → 0.4.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: be9e792ca43617f09611a801b8e8c8efde741ec531a97295de8d65378232c0d2
4
- data.tar.gz: 492000cb9aadaf0731e077b46ec3a32b573da9c8cd2acfaff6f282dec75c394d
3
+ metadata.gz: b4a6b0c92714af081d54b235449ab825fa86842d61869f31cd331a44c702efdc
4
+ data.tar.gz: cf2074e5c3f500689359912872166c1f13c08e59bde29408c90ee7b34fbe18fe
5
5
  SHA512:
6
- metadata.gz: 51e65415ee9d0a8c0f77d19d21ab525a01cbc4c025bc5572f92f2df13bc56ceed8b04be5e18d3c0308c468c43986dd267046d9b1c125e281ad01476b08a93569
7
- data.tar.gz: b64d9b5a0da5d254ecbc6dd861db05017b8cd81e13c0f58071413816d9b20d879187cbda5b2a703d5eae9f92ec044000010fc6b1b103fa30a9de04b265562cde
6
+ metadata.gz: 21654dccede23f1828f02b4446f11f626d12ee5d7d3689b96636d6b1be0465de44fddbacd05606935326a27d4317bfaf0b5596813e907a38580ea6591bc430ca
7
+ data.tar.gz: d3821259aeb7e5ff6306c3d9ccec25720030e659e351cd2c32a7791a8520ddea0039e6cab7f083b0244c82095e7c219c14de465bcda55b326eca184d06ce3bc7
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Reporter prints concise, aligned progress lines for the processing pipeline:
4
+ #
5
+ # parsing specifications ..... 4 ok
6
+ # parsing test protocols ..... 2 ok
7
+ # parsing decisions .......... 14 ok
8
+ # traceability matrices ...... 4 ok
9
+ # coverage matrices .......... 1 ok
10
+ # implementation matrices .... 1 ok
11
+ # decision links ............. 5 ok
12
+ # rendering HTML ............. ./build/index.html
13
+ #
14
+ # ANSI colour is applied only when writing to an interactive terminal, so piped
15
+ # or captured output stays clean.
16
+ module ConsoleReporter
17
+ COLUMN = 28 # label is dot-padded out to this column, then the value follows
18
+
19
+ module_function
20
+
21
+ def count(label, number)
22
+ emit(label, "#{number} ok", 92) # green highlight
23
+ end
24
+
25
+ def result(label, value)
26
+ emit(label, value, 96) # cyan highlight
27
+ end
28
+
29
+ def warn(label, value)
30
+ emit(label, value.to_s, 91) # red highlight
31
+ end
32
+
33
+ # Colourises a detail line with the same red as warn (TTY-gated).
34
+ def warn_detail(text)
35
+ colorize(text, 91)
36
+ end
37
+
38
+ def emit(label, value, color_code)
39
+ dotted = "#{label} ".ljust(COLUMN, '.')
40
+ puts "#{dotted} #{colorize(value, color_code)}"
41
+ end
42
+
43
+ def colorize(text, color_code)
44
+ $stdout.tty? ? "\e[#{color_code}m#{text}\e[0m" : text
45
+ end
46
+ end
@@ -5,6 +5,8 @@ require_relative 'doc_types/protocol'
5
5
  require_relative 'doc_types/coverage'
6
6
  require_relative 'doc_types/implementation'
7
7
  require_relative 'doc_types/traceability'
8
+ require_relative 'doc_types/decision'
9
+ require_relative 'doc_types/decisions_overview'
8
10
  require_relative 'doc_parser'
9
11
  require_relative 'source_file_parser'
10
12
  require_relative 'dom/document'
@@ -15,12 +17,6 @@ class DocFabric
15
17
  @@spec_colors = %w[cff4d2 fbeee6 ffcad4 bce6ff e4dfd9 f9e07f cbe54e d3e7ee eab595 86e3c3
16
18
  ffdca2 ffffff ffdd94 d0e6a5 ffb284 f3dbcf c9bbc8 c6c09c]
17
19
 
18
- def self.add_lazy_doc_id(path)
19
- if res = /(\w+)[.]md$/.match(path)
20
- TextLine.add_lazy_doc_id(res[1])
21
- end
22
- end
23
-
24
20
  def self.create_specification(path)
25
21
  color = @@spec_colors[@@color_index]
26
22
  @@color_index += 1
@@ -64,6 +60,19 @@ class DocFabric
64
60
  doc
65
61
  end
66
62
 
63
+ def self.create_decision(path)
64
+ doc = Decision.new path
65
+ DocFabric.parse_document doc
66
+ doc.extract_current_status
67
+ doc.extract_start_date
68
+ doc.extract_target_release_version
69
+ doc
70
+ end
71
+
72
+ def self.create_decisions_overview(project)
73
+ DecisionsOverview.new project
74
+ end
75
+
67
76
  def self.create_source_file(repository_path, path, repository_name)
68
77
  doc = SourceFile.new repository_path, path, repository_name
69
78
  DocFabric.parse_source_file doc
@@ -78,7 +87,7 @@ class DocFabric
78
87
  DocParser.parse(doc, file_lines)
79
88
 
80
89
  # Build dom
81
- doc.dom = Document.new(doc.headings) if doc.is_a?(Specification) || doc.is_a?(Protocol)
90
+ doc.dom = Document.new(doc.headings) if doc.is_a?(Specification) || doc.is_a?(Protocol) || doc.is_a?(Decision)
82
91
  end
83
92
 
84
93
  def self.parse_source_file(doc)
@@ -2,7 +2,7 @@ require_relative 'paragraph'
2
2
 
3
3
  # <REQ> Implementa a controlled paragraph as a subclass of the DocItem >[SRS-001] </REQ>
4
4
  class ControlledParagraph < Paragraph
5
- attr_accessor :id, :up_link_ids, :down_links, :coverage_links, :source_code_links
5
+ attr_accessor :id, :up_link_ids, :down_links, :coverage_links, :source_code_links, :decision_record_links
6
6
 
7
7
  def initialize(doc, text, id)
8
8
  super(doc, text)
@@ -12,6 +12,7 @@ class ControlledParagraph < Paragraph
12
12
  @down_links = nil
13
13
  @coverage_links = nil
14
14
  @source_code_links = nil
15
+ @decision_record_links = nil
15
16
  end
16
17
 
17
18
  def to_html
@@ -19,7 +20,7 @@ class ControlledParagraph < Paragraph
19
20
  unless @@html_table_render_in_progress
20
21
  s += "<table class=\"controlled\">\n"
21
22
  s += "\t<thead> <th>#</th> <th></th> <th title=\"Up-links\">UL</th> <th title=\"Down-links\">DL</th> \
22
- <th title=\"Test Coverage\">COV</th> </thead>\n"
23
+ <th title=\"Test Coverage\">COV</th> <th title=\"Decision Record\">DR</th> </thead>\n"
23
24
  @@html_table_render_in_progress = true # rubocop:disable Style/ClassVars
24
25
  end
25
26
  f_text = format_string(@text)
@@ -108,6 +109,31 @@ class ControlledParagraph < Paragraph
108
109
  else
109
110
  s += "\t\t<td class=\"item_id\"></td>\n"
110
111
  end
112
+
113
+ if @decision_record_links
114
+ if @decision_record_links.length == 1
115
+ dr_doc = @decision_record_links[0].parent_doc
116
+ s += "\t\t<td class=\"item_id\">\
117
+ <a href=\"./../../decisions/#{dr_doc.html_rel_path}\" \
118
+ class=\"external\" title=\"Decision Record\">#{dr_doc.id.upcase}</a></td>\n"
119
+ else
120
+ s += "\t\t<td class=\"item_id\">"
121
+ s += "<div id=\"DR_#{@id}\" style=\"display: block;\">"
122
+ s += "<a href=\"#\" onclick=\"decisionLink_OnClick(this.parentElement); return false;\" \
123
+ class=\"external\" title=\"Number of decision records\">#{@decision_record_links.length}</a>"
124
+ s += '</div>'
125
+ s += "<div id=\"DRS_#{@id}\" style=\"display: none;\">"
126
+ @decision_record_links.each do |lnk|
127
+ dr_doc = lnk.parent_doc
128
+ s += "\t\t\t<a href=\"./../../decisions/#{dr_doc.html_rel_path}\" \
129
+ class=\"external\" title=\"Referenced in\">#{dr_doc.id.upcase}</a>\n<br>"
130
+ end
131
+ s += '</div>'
132
+ s += "</td>\n"
133
+ end
134
+ else
135
+ s += "\t\t<td class=\"item_id\"></td>\n"
136
+ end
111
137
  s += "\t</tr>\n"
112
138
  s
113
139
  end
@@ -101,13 +101,14 @@ class TestStepReferenceColumn < ControlledTableColumn # rubocop:disable Style/Do
101
101
 
102
102
  def to_html # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
103
103
  s = ''
104
+ specifications_path = @parent_row.parent_doc.specifications_path
104
105
  if @up_link_ids
105
106
  if @up_link_ids.length == 1
106
107
  if tmp = /^([a-zA-Z]+)-\d+/.match(@up_link_ids[0])
107
108
  up_link_doc_name = tmp[1].downcase
108
109
  end
109
110
  s += "\t\t<td class=\"item_id\" style=\"text-align: center;\">\
110
- <a href=\"./../../../specifications/#{up_link_doc_name}/#{up_link_doc_name}.html##{@up_link_ids[0]}\" \
111
+ <a href=\"#{specifications_path}#{up_link_doc_name}/#{up_link_doc_name}.html##{@up_link_ids[0]}\" \
111
112
  class=\"external\" title=\"Linked to\">#{@up_link_ids[0]}</a></td>\n"
112
113
  else
113
114
  s += "\t\t<td class=\"item_id\" style=\"text-align: center;\">"
@@ -120,7 +121,7 @@ class TestStepReferenceColumn < ControlledTableColumn # rubocop:disable Style/Do
120
121
  if tmp = /^([a-zA-Z]+)-\d+/.match(lnk)
121
122
  up_link_doc_name = tmp[1].downcase
122
123
  end
123
- s += "\t\t\t<a href=\"./../../../specifications/#{up_link_doc_name}/#{up_link_doc_name}.html##{lnk}\" \
124
+ s += "\t\t\t<a href=\"#{specifications_path}#{up_link_doc_name}/#{up_link_doc_name}.html##{lnk}\" \
124
125
  class=\"external\" title=\"Verifies\">#{lnk}</a>\n<br>"
125
126
  end
126
127
  s += '</div>'
@@ -150,7 +151,7 @@ class ControlledTable < DocItem # rubocop:disable Style/Documentation
150
151
  end
151
152
 
152
153
  def add_row(row)
153
- columns = row.split('|')
154
+ columns = split_table_cells(row)
154
155
 
155
156
  @rows.append(format_columns(columns))
156
157
 
@@ -184,7 +185,7 @@ class ControlledTable < DocItem # rubocop:disable Style/Documentation
184
185
  end
185
186
  end
186
187
 
187
- elsif index + 2 == columns.length # it is expected that test step result is placed to the pre-last column only
188
+ elsif (index + 2 == columns.length) && @parent_doc.instance_of?(Protocol) # test step result column applies only to Protocols
188
189
 
189
190
  col = TestStepResultColumn.new element
190
191
  new_row.columns.append col
@@ -19,4 +19,16 @@ class DocItem < TextLine # rubocop:disable Style/Documentation
19
19
  def get_url
20
20
  ''
21
21
  end
22
+
23
+ # Splits a Markdown table row into its cell strings, treating a backslash-escaped
24
+ # pipe (\|) as a literal character within a cell rather than a column separator
25
+ # (e.g. a "|" inside an inline code span such as `[[target\|alias]]`). The escaping
26
+ # backslash is dropped so the cell renders the intended literal pipe.
27
+ def split_table_cells(row)
28
+ row.split(/(?<!\\)\|/).map { |cell| cell.gsub('\\|', '|') }
29
+ end
30
+
31
+ def owner_document
32
+ @parent_doc
33
+ end
22
34
  end
@@ -73,7 +73,7 @@ class MarkdownList < DocItem
73
73
  s.each_char do |c|
74
74
  case state
75
75
  when 'looking_for_list_item_marker'
76
- if c == '*'
76
+ if c == '*' || c == '-'
77
77
  state = 'looking_for_space'
78
78
  elsif numeric?(c)
79
79
  state = 'looking_for_dot'
@@ -106,7 +106,7 @@ class MarkdownList < DocItem
106
106
  end
107
107
 
108
108
  def self.unordered_list_item?(raw_text)
109
- res = /(\*\s?)(.*)/.match(raw_text)
109
+ res = /^\s*([*\-]\s+)(.*)/.match(raw_text)
110
110
  return true if res
111
111
 
112
112
  false
@@ -3,21 +3,23 @@
3
3
  require_relative 'doc_item'
4
4
 
5
5
  class MarkdownTable < DocItem
6
- attr_accessor :column_names, :rows, :heading_row, :is_separator_detected, :column_aligns
6
+ attr_accessor :column_names, :rows, :heading_row, :is_separator_detected, :column_aligns,
7
+ :is_decision_status_table
7
8
 
8
- def initialize(doc, heading_row)
9
+ def initialize(doc, heading_row) # rubocop:disable Metrics/MethodLength
9
10
  super(doc)
10
11
  @heading_row = heading_row
11
12
 
12
13
  res = /^[|](.*[|])/.match(heading_row)
13
14
  @column_names = if res
14
- res[1].split('|')
15
+ split_table_cells(res[1])
15
16
  else
16
17
  ['# ERROR# ']
17
18
  end
18
19
  @rows = []
19
20
  @is_separator_detected = false
20
21
  @column_aligns = []
22
+ @is_decision_status_table = false
21
23
  end
22
24
 
23
25
  def add_separator(line)
@@ -47,7 +49,7 @@ class MarkdownTable < DocItem
47
49
  end
48
50
 
49
51
  def add_row(row)
50
- columns = row.split('|')
52
+ columns = split_table_cells(row)
51
53
  @rows.append(columns.map!(&:strip))
52
54
  true
53
55
  end
@@ -69,10 +71,17 @@ class MarkdownTable < DocItem
69
71
  s += " </thead>\n"
70
72
 
71
73
  @rows.each do |row|
72
- s += "\t<tr>\n"
74
+ tr_class = if @is_decision_status_table && row[0].to_s.strip == '*'
75
+ ' class="current_status"'
76
+ else
77
+ ''
78
+ end
79
+ s += "\t<tr#{tr_class}>\n"
73
80
  row.each_with_index do |col, index|
74
- if col.to_i.positive? && col.to_i.to_s == col # autoalign cells with numbers
75
- s += "\t\t<td style=\"text-align: center;\">#{col}</td>\n"
81
+ cell = col
82
+ cell = '▶' if @is_decision_status_table && index.zero? && col.strip == '*'
83
+ if cell.to_i.positive? && cell.to_i.to_s == cell # autoalign cells with numbers
84
+ s += "\t\t<td style=\"text-align: center;\">#{cell}</td>\n"
76
85
  else
77
86
  align = ''
78
87
  case @column_aligns[index]
@@ -83,7 +92,7 @@ class MarkdownTable < DocItem
83
92
  when 'center'
84
93
  align = 'style="text-align: center;"'
85
94
  end
86
- f_text = format_string(col)
95
+ f_text = format_string(cell)
87
96
  s += "\t\t<td #{align}>#{f_text}</td>\n"
88
97
  end
89
98
  end