Almirah 0.4.5 → 0.4.6

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: e7ecb1c0f1633226eaccd34b70d7c45c6d00e6f8ec4b605231f71b7bea725dcd
4
- data.tar.gz: a223709af5754031b0efef8c443fd158fad6c2c3fde08fbba83233e82075d82a
3
+ metadata.gz: 8f66f0846c24a185b1abb415b4772edd12d7e7dfe93a0802ce8017ade9d0a249
4
+ data.tar.gz: 5f542c8b0aa5aa363310f049041a8e4f4341e49fd54ce8eaf1f26c442746d337
5
5
  SHA512:
6
- metadata.gz: 4d57afaec80f6e7370aec60e254f6650832ed2808a2b1550efc7a5271f69bd4e2bbce2e636eb2f7128b1a8ccee6e2bf978e0ca032ad275c399bbc334c12c57ab
7
- data.tar.gz: a5e6de48b94a5de8a77ab8cb7e744116b3c9ecb5b92e3f81d1231c9436e412d9f1e53e97f2db9c2dc733f3dfdda6966e305b3b7faf9963453d1abff970358985
6
+ metadata.gz: 57099abaaeb800be450638dcd8cfc8915eda501389ab4833082b8006229e7d42eb9f861c82f07bbf828c79054e2c463b3a7cf52a897f6858354d50eb5a3d4395
7
+ data.tar.gz: a75661f96e5198cc71ffdec7da16577f58f23e18ff02c2c8fcd846d01dd332ded1995c8193ccfbf1789766ce657a3fd5fb328af6a1ae6312936733f6eeec4998
@@ -103,15 +103,17 @@ class TestStepReferenceColumn < ControlledTableColumn
103
103
  s = ''
104
104
  specifications_path = @parent_row.parent_doc.specifications_path
105
105
  if @up_link_ids
106
+ cell_style = 'text-align: center;'
107
+ cell_style += ' background-color: #fcc;' if @up_link_ids.any? { |lnk| dangling?(lnk) }
106
108
  if @up_link_ids.length == 1
107
109
  if tmp = /^([a-zA-Z]+)-\d+/.match(@up_link_ids[0])
108
110
  up_link_doc_name = tmp[1].downcase
109
111
  end
110
- s += "\t\t<td class=\"item_id\" style=\"text-align: center;\">\
112
+ s += "\t\t<td class=\"item_id\" style=\"#{cell_style}\">\
111
113
  <a href=\"#{specifications_path}#{up_link_doc_name}/#{up_link_doc_name}.html##{@up_link_ids[0]}\" \
112
- class=\"external\" title=\"Linked to\">#{@up_link_ids[0]}</a></td>\n"
114
+ class=\"#{link_class(@up_link_ids[0])}\" title=\"#{link_title(@up_link_ids[0], 'Linked to')}\">#{@up_link_ids[0]}</a></td>\n"
113
115
  else
114
- s += "\t\t<td class=\"item_id\" style=\"text-align: center;\">"
116
+ s += "\t\t<td class=\"item_id\" style=\"#{cell_style}\">"
115
117
  s += "<div id=\"COV_#{@parent_row.id}\" style=\"display: block;\">"
116
118
  s += "<a href=\"#\" onclick=\"coverageLink_OnClick(this.parentElement); return false;\" \
117
119
  class=\"external\" title=\"Number of verified items\">#{@up_link_ids.length}</a>"
@@ -122,7 +124,7 @@ class TestStepReferenceColumn < ControlledTableColumn
122
124
  up_link_doc_name = tmp[1].downcase
123
125
  end
124
126
  s += "\t\t\t<a href=\"#{specifications_path}#{up_link_doc_name}/#{up_link_doc_name}.html##{lnk}\" \
125
- class=\"external\" title=\"Verifies\">#{lnk}</a>\n<br>"
127
+ class=\"#{link_class(lnk)}\" title=\"#{link_title(lnk, 'Verifies')}\">#{lnk}</a>\n<br>"
126
128
  end
127
129
  s += '</div>'
128
130
  s += "</td>\n"
@@ -131,6 +133,23 @@ class TestStepReferenceColumn < ControlledTableColumn
131
133
  "\t\t<td style=\"text-align: center;\"></td>\n\r"
132
134
  end
133
135
  end
136
+
137
+ # An uplink to a paragraph missing from an existing specification, per the
138
+ # owning document's wrong-links collection (ENH-225). The cell renders it
139
+ # with the wrong-links red background and the broken-link style, keeping
140
+ # the link to the target document clickable.
141
+ def dangling?(link_id)
142
+ doc = @parent_row.parent_doc
143
+ doc.respond_to?(:wrong_links_hash) && doc.wrong_links_hash.key?(link_id)
144
+ end
145
+
146
+ def link_class(link_id)
147
+ dangling?(link_id) ? 'external broken_link' : 'external'
148
+ end
149
+
150
+ def link_title(link_id, resolved_title)
151
+ dangling?(link_id) ? 'Linked item does not exist' : resolved_title
152
+ end
134
153
  end
135
154
 
136
155
  class ControlledTable < DocItem
@@ -6,7 +6,7 @@ class BaseDocument
6
6
  attr_accessor :title, :id, :dom, :headings, :output_rel_path
7
7
 
8
8
  class << self
9
- attr_accessor :show_decisions_link, :show_risks_link
9
+ attr_accessor :show_decisions_link, :show_risks_link, :font_size
10
10
  end
11
11
 
12
12
  def initialize
@@ -55,6 +55,7 @@ class BaseDocument
55
55
  file.puts s.gsub! '{{DOCUMENT_TITLE}}', @title
56
56
  elsif s.include?('{{STYLES_AND_SCRIPTS}}')
57
57
  file.puts "<link rel=\"stylesheet\" href=\"#{rel_to('css/main.css')}\">"
58
+ file.puts font_size_style if BaseDocument.font_size
58
59
  file.puts "<script src=\"#{rel_to('scripts/main.js')}\"></script>"
59
60
  if @id == 'index'
60
61
  file.puts "<script type=\"module\" src=\"#{rel_to('scripts/orama_search.js')}\"></script>"
@@ -63,11 +64,7 @@ class BaseDocument
63
64
  file.puts '<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>'
64
65
  end
65
66
  elsif s.include?('{{HOME_BUTTON}}')
66
- if @id == 'index'
67
- file.puts home_link(rel_to('index.html'))
68
- else
69
- file.puts index_link(rel_to('index.html'))
70
- end
67
+ file.puts index_link(rel_to('index.html'))
71
68
  file.puts decisions_link(rel_to('decisions/overview.html')) if BaseDocument.show_decisions_link
72
69
  file.puts risks_link(rel_to('risks/overview.html')) if BaseDocument.show_risks_link
73
70
  elsif s.include?('{{GEM_VERSION}}')
@@ -89,14 +86,19 @@ class BaseDocument
89
86
  %(<a id="risks_menu_item" href="#{href}">#{icon}&nbsp;Risks</a>)
90
87
  end
91
88
 
89
+ # The Documents item (ADR-223): the same link on every page, the Index page
90
+ # included, where it self-links — no Home variant. The element id stays
91
+ # index_menu_item; the label is presentation, the id is an interface.
92
92
  def index_link(href)
93
- icon = '<span><i class="fa fa-info" aria-hidden="true"></i></span>'
94
- %(<a id="index_menu_item" href="#{href}">#{icon}&nbsp;Index</a>)
93
+ icon = '<span><i class="fa fa-home" aria-hidden="true"></i></span>'
94
+ %(<a id="index_menu_item" href="#{href}">#{icon}&nbsp;Documents</a>)
95
95
  end
96
96
 
97
- def home_link(href)
98
- icon = '<span><i class="fa fa-home" aria-hidden="true"></i></span>'
99
- %(<a id="home_menu_item" href="#{href}">#{icon}&nbsp;Home</a>)
97
+ # The inline override carrying the project.yml font_size (ADR-224). Emitted
98
+ # after the main.css link only when the setting exists, so unconfigured
99
+ # projects render exactly as before.
100
+ def font_size_style
101
+ "<style>:root { --almirah-font-size: #{BaseDocument.font_size}px; }</style>"
100
102
  end
101
103
 
102
104
  # Relative URL from this page to a target path under the build root.
@@ -1,12 +1,15 @@
1
1
  require_relative 'persistent_document'
2
2
 
3
3
  class Protocol < PersistentDocument
4
- attr_accessor :specifications_path
4
+ attr_accessor :specifications_path, :wrong_links_hash
5
5
 
6
6
  def initialize(fele_path)
7
7
  super
8
8
  @id = File.basename(fele_path, File.extname(fele_path)).downcase
9
9
  @specifications_path = './../../../specifications/'
10
+ # The linker records dangling Req-IDs here as for every other linked
11
+ # document type (ISSUE-226); without it a dangling reference crashed the build.
12
+ @wrong_links_hash = {}
10
13
  end
11
14
 
12
15
  def to_html(nav_pane, output_file_path)
@@ -61,8 +61,8 @@ class RisksOverview < BaseDocument
61
61
  s += "\t\t<td class=\"item_text\" style='padding: 5px;'>\
62
62
  <a name=\"#{name}\" id=\"#{name}\" href=\"./#{name}/overview.html\" class=\"external\" \
63
63
  title=\"Risk Registry\">#{registry_title(name)}</a></td>\n"
64
- s += "\t\t<td class=\"item_rpn\">#{records.length}</td>\n"
65
- s += "\t\t<td class=\"item_rpn\">#{open_count(records)}</td>\n"
64
+ s += "\t\t<td class=\"item_rpn\" style='width: 7%;'>#{records.length}</td>\n"
65
+ s += "\t\t<td class=\"item_rpn\" style='width: 7%;'>#{open_count(records)}</td>\n"
66
66
  s += render_highest_cell(values, group)
67
67
  s += render_average_cell(values)
68
68
  s + "\t</tr>\n"
@@ -86,17 +86,17 @@ title=\"Risk Registry\">#{registry_title(name)}</a></td>\n"
86
86
  # The worst risk's verdict carries up: the cell keeps the leading group's
87
87
  # threshold colouring. Blank without a group or computable values.
88
88
  def render_highest_cell(values, group)
89
- return "\t\t<td class=\"item_rpn\"></td>\n" if values.empty?
89
+ return "\t\t<td class=\"item_rpn\" style='width: 7%;'></td>\n" if values.empty?
90
90
 
91
91
  highest = values.max
92
92
  classes = ['item_rpn', rpn_threshold_class(highest, group)].compact.join(' ')
93
- "\t\t<td class=\"#{classes}\">#{format_rpn(highest)}</td>\n"
93
+ "\t\t<td class=\"#{classes}\" style='width: 7%;'>#{format_rpn(highest)}</td>\n"
94
94
  end
95
95
 
96
96
  def render_average_cell(values)
97
- return "\t\t<td class=\"item_rpn\"></td>\n" if values.empty?
97
+ return "\t\t<td class=\"item_rpn\" style='width: 7%;'></td>\n" if values.empty?
98
98
 
99
99
  average = (values.sum.to_f / values.length).round(1)
100
- "\t\t<td class=\"item_rpn\">#{format_rpn(average)}</td>\n"
100
+ "\t\t<td class=\"item_rpn\" style='width: 7%;'>#{format_rpn(average)}</td>\n"
101
101
  end
102
102
  end
@@ -94,9 +94,10 @@ class SourceFile < PersistentDocument
94
94
  file.puts s.gsub! '{{DOCUMENT_TITLE}}', @title
95
95
  elsif s.include?('{{STYLES_AND_SCRIPTS}}')
96
96
  file.puts "<link rel=\"stylesheet\" href=\"#{css_path}\">"
97
+ file.puts font_size_style if BaseDocument.font_size
97
98
  file.puts "<script src=\"#{js_path}\"></script>"
98
99
  elsif s.include?('{{HOME_BUTTON}}')
99
- file.puts "<a id=\"index_menu_item\" href=\"#{index_path}\"><span><i class=\"fa fa-info\" aria-hidden=\"true\"></i></span>&nbsp;Index</a>"
100
+ file.puts "<a id=\"index_menu_item\" href=\"#{index_path}\"><span><i class=\"fa fa-home\" aria-hidden=\"true\"></i></span>&nbsp;Documents</a>"
100
101
  elsif s.include?('{{GEM_VERSION}}')
101
102
  file.puts "(#{Gem.loaded_specs['Almirah'].version.version})"
102
103
  else
@@ -18,6 +18,7 @@ class Project
18
18
  def initialize(configuration)
19
19
  @configuration = configuration
20
20
  @project_data = ProjectData.new
21
+ BaseDocument.font_size = @configuration.get_font_size
21
22
 
22
23
  @index = nil
23
24
  @project = self
@@ -59,6 +60,7 @@ class Project
59
60
  render_all_protocols
60
61
  render_all_source_files
61
62
  render_all_specifications(@project_data.implementation_matrices) # intentionally after source file rendering
63
+ copy_decision_and_risk_images
62
64
  render_decisions_overview
63
65
  render_all_decisions
64
66
  render_all_risk_records
@@ -90,6 +92,7 @@ class Project
90
92
  render_all_protocols
91
93
  render_all_source_files
92
94
  render_all_specifications(@project_data.implementation_matrices) # intentionally after source file rendering
95
+ copy_decision_and_risk_images
93
96
  render_decisions_overview
94
97
  render_all_decisions
95
98
  render_all_risk_records
@@ -473,6 +476,25 @@ class Project
473
476
  end
474
477
  end
475
478
 
479
+ # Every folder named img under decisions/ and risks/ is copied to the same
480
+ # relative location under build/ (ADR-227, SRS-176), so relative image
481
+ # references in decision records, risk records, and registry prefaces
482
+ # resolve in the rendered HTML. Folder-based rather than doc-id-based like
483
+ # the specification and protocol copies, because these records share their
484
+ # release and registry folders.
485
+ def copy_decision_and_risk_images
486
+ root = @configuration.project_root_directory
487
+ %w[decisions risks].each do |subroot|
488
+ Dir.glob("#{root}/#{subroot}/**/img").each do |src|
489
+ next unless File.directory?(src)
490
+
491
+ dst = "#{root}/build/#{src.sub("#{root}/", '')}"
492
+ FileUtils.mkdir_p(File.dirname(dst))
493
+ FileUtils.copy_entry(src, dst)
494
+ end
495
+ end
496
+ end
497
+
476
498
  def render_all_source_files
477
499
  path = @configuration.project_root_directory
478
500
  FileUtils.mkdir_p("#{path}/build/source_files")
@@ -29,6 +29,13 @@ class ProjectConfiguration
29
29
  []
30
30
  end
31
31
 
32
+ # The optional base text size in pixels (ADR-224), from the top-level
33
+ # font_size: number. nil when absent or not a positive number.
34
+ def get_font_size
35
+ value = @parameters.is_a?(Hash) ? @parameters['font_size'] : nil
36
+ value.is_a?(Numeric) && value.positive? ? value : nil
37
+ end
38
+
32
39
  # The ordered register-column list for a risk registry folder (ADR-216),
33
40
  # read from the risks: root — a list of { folder:, columns: } entries.
34
41
  # nil when the registry carries no configuration; such a registry renders
@@ -5,7 +5,10 @@ html {
5
5
  }
6
6
  body {
7
7
  font-family: Verdana, sans-serif;
8
- font-size: 12px;
8
+ /* Base text size, overridable per project via font_size in project.yml
9
+ (ADR-224). Headings, top menu and footer are pinned in px below so the
10
+ setting scales only the reading text and the navigation pane. */
11
+ font-size: var(--almirah-font-size, 12px);
9
12
  color: #333;
10
13
  margin: 0;
11
14
  padding: 0;
@@ -30,24 +33,24 @@ body {
30
33
  margin: 0 0 10px 0;
31
34
  }
32
35
  h1 {
33
- font-size: 2em;
36
+ font-size: 24px;
34
37
  }
35
38
  h2 {
36
- font-size: 1.8em;
39
+ font-size: 21.6px;
37
40
  }
38
41
  h3 {
39
- font-size: 1.5em;
42
+ font-size: 18px;
40
43
  }
41
44
  h4 {
42
- font-size: 1.2em;
45
+ font-size: 14.4px;
43
46
  border: none;
44
47
  font-weight: bold;
45
48
  }
46
49
  h5 {
47
- font-size: 1em;
50
+ font-size: 12px;
48
51
  }
49
52
  h6 {
50
- font-size: 1em; color: #8e8e8e;
53
+ font-size: 12px; color: #8e8e8e;
51
54
  }
52
55
  a.heading_anchor {
53
56
  display: none;
@@ -260,7 +263,7 @@ img{
260
263
  text-align: center;
261
264
  padding: 4px 6px;
262
265
  text-decoration: none;
263
- font-size: 1.5em;
266
+ font-size: 18px;
264
267
  font-family: "Trebuchet MS", Verdana, sans-serif;
265
268
  }
266
269
  #top_nav a.split {
@@ -269,7 +272,7 @@ img{
269
272
  text-align: center;
270
273
  padding: 4px 6px;
271
274
  text-decoration: none;
272
- font-size: 1.5em;
275
+ font-size: 18px;
273
276
  font-family: "Trebuchet MS", Verdana, sans-serif;
274
277
  }
275
278
  #top_nav a:hover {
@@ -343,7 +346,7 @@ img{
343
346
  #footer {
344
347
  clear: both;
345
348
  border-top: 1px solid #bbb;
346
- font-size: 0.9em;
349
+ font-size: 10.8px;
347
350
  color: #aaa;
348
351
  padding: 5px;
349
352
  text-align:center;
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: Almirah
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.5
4
+ version: 0.4.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Oleksandr Ivanov