Almirah 0.4.1 → 0.4.3
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/bin/almirah +2 -2
- data/lib/almirah/doc_fabric.rb +8 -0
- data/lib/almirah/doc_items/blockquote.rb +15 -16
- data/lib/almirah/doc_items/code_block.rb +19 -21
- data/lib/almirah/doc_items/controlled_paragraph.rb +2 -2
- data/lib/almirah/doc_items/controlled_table.rb +11 -11
- data/lib/almirah/doc_items/controlled_table_row.rb +15 -18
- data/lib/almirah/doc_items/doc_footer.rb +10 -13
- data/lib/almirah/doc_items/doc_item.rb +2 -2
- data/lib/almirah/doc_items/heading.rb +21 -3
- data/lib/almirah/doc_items/image.rb +25 -20
- data/lib/almirah/doc_items/markdown_list.rb +2 -2
- data/lib/almirah/doc_items/markdown_table.rb +10 -3
- data/lib/almirah/doc_items/scope_table.rb +188 -0
- data/lib/almirah/doc_items/text_line.rb +52 -27
- data/lib/almirah/doc_items/todo_block.rb +15 -16
- data/lib/almirah/doc_items/work_item.rb +129 -0
- data/lib/almirah/doc_parser.rb +14 -8
- data/lib/almirah/doc_types/base_document.rb +21 -5
- data/lib/almirah/doc_types/coverage.rb +3 -3
- data/lib/almirah/doc_types/critical_chain_page.rb +218 -0
- data/lib/almirah/doc_types/decision.rb +158 -7
- data/lib/almirah/doc_types/decision_grouping.rb +17 -0
- data/lib/almirah/doc_types/decisions_overview.rb +593 -32
- data/lib/almirah/doc_types/implementation.rb +98 -98
- data/lib/almirah/doc_types/index.rb +11 -12
- data/lib/almirah/doc_types/persistent_document.rb +1 -1
- data/lib/almirah/doc_types/planning_dates.rb +17 -0
- data/lib/almirah/doc_types/protocol.rb +16 -20
- data/lib/almirah/doc_types/source_file.rb +1 -1
- data/lib/almirah/doc_types/traceability.rb +124 -133
- data/lib/almirah/dom/doc_section.rb +2 -2
- data/lib/almirah/dom/document.rb +1 -1
- data/lib/almirah/html_safe.rb +39 -0
- data/lib/almirah/link_registry.rb +21 -6
- data/lib/almirah/navigation_pane.rb +9 -13
- data/lib/almirah/project/critical_chain.rb +117 -0
- data/lib/almirah/project/doc_linker.rb +4 -4
- data/lib/almirah/project/fever_chart.rb +94 -0
- data/lib/almirah/project/project_data.rb +8 -2
- data/lib/almirah/project/work_item_scheduler.rb +166 -0
- data/lib/almirah/project/working_calendar.rb +112 -0
- data/lib/almirah/project.rb +146 -9
- data/lib/almirah/project_configuration.rb +126 -29
- data/lib/almirah/project_template.rb +6 -6
- data/lib/almirah/project_utility.rb +3 -5
- data/lib/almirah/search/specifications_db.rb +2 -2
- data/lib/almirah/source_file_parser.rb +2 -3
- data/lib/almirah/templates/css/main.css +168 -1
- data/lib/almirah/templates/scripts/main.js +7 -2
- data/lib/almirah/templates/scripts/orama_search.js +17 -4
- data/lib/almirah.rb +1 -2
- metadata +12 -2
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
html {
|
|
2
|
+
/* Leave room for the fixed #top_nav so in-page anchor links
|
|
3
|
+
are not hidden behind it when navigating to them. */
|
|
4
|
+
scroll-padding-top: 40px;
|
|
5
|
+
}
|
|
1
6
|
body {
|
|
2
7
|
font-family: Verdana, sans-serif;
|
|
3
8
|
font-size: 12px;
|
|
@@ -72,6 +77,9 @@ table.markdown_table td{
|
|
|
72
77
|
table.markdown_table tr.current_status td {
|
|
73
78
|
background-color: #ffffee;
|
|
74
79
|
}
|
|
80
|
+
table.markdown_table td.scope_date {
|
|
81
|
+
white-space: nowrap;
|
|
82
|
+
}
|
|
75
83
|
table.controlled{
|
|
76
84
|
border: 1px solid #e4e4e4;
|
|
77
85
|
border-collapse: collapse;
|
|
@@ -139,6 +147,163 @@ table.controlled td.item_text{
|
|
|
139
147
|
max-width: 100%;
|
|
140
148
|
max-height: 300px;
|
|
141
149
|
}
|
|
150
|
+
.workitem_gantt {
|
|
151
|
+
--gantt-owner-width: 120px;
|
|
152
|
+
--gantt-day-width: 26px;
|
|
153
|
+
--gantt-month-h: 18px;
|
|
154
|
+
overflow: auto;
|
|
155
|
+
max-height: 420px;
|
|
156
|
+
margin-bottom: 16px;
|
|
157
|
+
border: 1px solid #e1e4e8;
|
|
158
|
+
}
|
|
159
|
+
.workitem_gantt .gantt_grid {
|
|
160
|
+
display: grid;
|
|
161
|
+
gap: 0;
|
|
162
|
+
width: max-content;
|
|
163
|
+
padding: 4px;
|
|
164
|
+
}
|
|
165
|
+
.workitem_gantt .gantt_corner,
|
|
166
|
+
.workitem_gantt .gantt_owner,
|
|
167
|
+
.workitem_gantt .gantt_owner_tracking,
|
|
168
|
+
.workitem_gantt .gantt_band_corner,
|
|
169
|
+
.workitem_gantt .gantt_buffer {
|
|
170
|
+
position: sticky;
|
|
171
|
+
left: 0;
|
|
172
|
+
background: #fff;
|
|
173
|
+
padding: 2px 8px;
|
|
174
|
+
font-weight: 600;
|
|
175
|
+
white-space: nowrap;
|
|
176
|
+
border-right: 1px solid #e1e4e8;
|
|
177
|
+
z-index: 2;
|
|
178
|
+
}
|
|
179
|
+
.workitem_gantt .gantt_corner {
|
|
180
|
+
top: 0;
|
|
181
|
+
border-bottom: 1px solid #bbb;
|
|
182
|
+
z-index: 3;
|
|
183
|
+
}
|
|
184
|
+
.workitem_gantt .gantt_month_head {
|
|
185
|
+
position: sticky;
|
|
186
|
+
top: 0;
|
|
187
|
+
background: #fff;
|
|
188
|
+
text-align: center;
|
|
189
|
+
font-size: 11px;
|
|
190
|
+
font-weight: 600;
|
|
191
|
+
color: #57606a;
|
|
192
|
+
border-bottom: 1px solid #e1e4e8;
|
|
193
|
+
border-left: 1px solid #d0d7de;
|
|
194
|
+
white-space: nowrap;
|
|
195
|
+
overflow: hidden;
|
|
196
|
+
z-index: 1;
|
|
197
|
+
}
|
|
198
|
+
.workitem_gantt .gantt_day_head {
|
|
199
|
+
position: sticky;
|
|
200
|
+
top: var(--gantt-month-h);
|
|
201
|
+
background: #fff;
|
|
202
|
+
text-align: center;
|
|
203
|
+
font-size: 11px;
|
|
204
|
+
color: #57606a;
|
|
205
|
+
border-bottom: 1px solid #bbb;
|
|
206
|
+
z-index: 1;
|
|
207
|
+
}
|
|
208
|
+
/* Weekday-holiday highlight in the Chart.js palette red (ADR-205 amendment):
|
|
209
|
+
the column carries the buffer bar's diagonal stripe texture, in red; the
|
|
210
|
+
header stays a solid tint so the day number reads. */
|
|
211
|
+
.workitem_gantt .gantt_day_head.gantt_nonworking { background: rgba(255, 99, 132, 0.22); color: #b23a52; }
|
|
212
|
+
.workitem_gantt .gantt_day_head.gantt_friday { background: rgb(225, 241, 250); }
|
|
213
|
+
.workitem_gantt .gantt_nonworking_col {
|
|
214
|
+
background: repeating-linear-gradient(45deg,
|
|
215
|
+
rgba(255, 99, 132, 0.20), rgba(255, 99, 132, 0.20) 5px,
|
|
216
|
+
rgba(255, 99, 132, 0.07) 5px, rgba(255, 99, 132, 0.07) 10px);
|
|
217
|
+
}
|
|
218
|
+
.workitem_gantt .gantt_friday_col { background: rgb(225, 241, 250); }
|
|
219
|
+
.workitem_gantt .gantt_bar,
|
|
220
|
+
.workitem_gantt .gantt_track_bar {
|
|
221
|
+
font-size: 11px;
|
|
222
|
+
line-height: 1.5;
|
|
223
|
+
margin: 1px;
|
|
224
|
+
padding: 1px 5px;
|
|
225
|
+
border-radius: 3px;
|
|
226
|
+
overflow: hidden;
|
|
227
|
+
white-space: nowrap;
|
|
228
|
+
text-overflow: ellipsis;
|
|
229
|
+
color: #fff;
|
|
230
|
+
cursor: default;
|
|
231
|
+
}
|
|
232
|
+
.workitem_gantt .gantt_todo { background: #9aa5b1; }
|
|
233
|
+
.workitem_gantt .gantt_inprogress { background: #ffffdd; color: #333; box-shadow: inset 0 0 0 1px #bbb; }
|
|
234
|
+
.workitem_gantt .gantt_done { background: #cfc; color: #57606a; box-shadow: inset 0 0 0 1px #e1e4e8; }
|
|
235
|
+
.workitem_gantt .gantt_blocked { box-shadow: inset 0 0 0 1px #bbb; }
|
|
236
|
+
.workitem_gantt .gantt_critical { outline: 1px solid #9a6700; outline-offset: -1px; } /* buffer-bar amber (dark) */
|
|
237
|
+
.workitem_gantt .gantt_release_band {
|
|
238
|
+
text-align: center;
|
|
239
|
+
font-size: 11px;
|
|
240
|
+
font-weight: 600;
|
|
241
|
+
color: #57606a;
|
|
242
|
+
background: #eef1f4;
|
|
243
|
+
border-bottom: 1px solid #e1e4e8;
|
|
244
|
+
border-left: 1px solid #d0d7de;
|
|
245
|
+
padding: 2px 4px;
|
|
246
|
+
white-space: nowrap;
|
|
247
|
+
overflow: hidden;
|
|
248
|
+
text-overflow: ellipsis;
|
|
249
|
+
}
|
|
250
|
+
.workitem_gantt .gantt_buffer { color: #9a6700; }
|
|
251
|
+
.critical_chain { margin-bottom: 16px; }
|
|
252
|
+
.critical_chain h2 { font-size: 1.1em; margin-bottom: 6px; }
|
|
253
|
+
.critical_chain .cc_group { margin: 8px 0; }
|
|
254
|
+
.critical_chain .cc_group h3 { font-size: 0.95em; margin: 4px 0; }
|
|
255
|
+
.critical_chain table.cc_chain { border-collapse: collapse; margin: 4px 0; }
|
|
256
|
+
.critical_chain table.cc_chain th,
|
|
257
|
+
.critical_chain table.cc_chain td { border: 1px solid #e1e4e8; padding: 2px 8px; text-align: left; font-size: 12px; }
|
|
258
|
+
.critical_chain .cc_buffer,
|
|
259
|
+
.critical_chain .cc_consumed,
|
|
260
|
+
.critical_chain .cc_projected,
|
|
261
|
+
.critical_chain .cc_finish { margin: 2px 0; font-size: 12px; }
|
|
262
|
+
.critical_chain .cc_consumed { color: #57606a; }
|
|
263
|
+
.critical_chain .cc_finish { font-weight: 600; }
|
|
264
|
+
.critical_chain .cc_unestimated { color: #9a6700; font-style: italic; font-size: 12px; }
|
|
265
|
+
.critical_chain .cc_group_body { display: flex; flex-wrap: wrap; gap: 24px; align-items: flex-start; }
|
|
266
|
+
.critical_chain .cc_plan { flex: 1 1 320px; }
|
|
267
|
+
.critical_chain .cc_fever { flex: 1 1 360px; max-width: 480px; height: 320px; position: relative; }
|
|
268
|
+
.critical_chain .cc_fever .fever_canvas { width: 100%; height: 100%; }
|
|
269
|
+
.workitem_gantt .gantt_buffer_bar {
|
|
270
|
+
font-size: 11px;
|
|
271
|
+
line-height: 1.5;
|
|
272
|
+
margin: 1px;
|
|
273
|
+
padding: 1px 5px;
|
|
274
|
+
border-radius: 3px;
|
|
275
|
+
text-align: center;
|
|
276
|
+
overflow: hidden;
|
|
277
|
+
white-space: nowrap;
|
|
278
|
+
text-overflow: ellipsis;
|
|
279
|
+
color: #9a6700;
|
|
280
|
+
background: repeating-linear-gradient(45deg, #ffe9b3, #ffe9b3 5px, #fff3d4 5px, #fff3d4 10px);
|
|
281
|
+
box-shadow: inset 0 0 0 1px #e0c068;
|
|
282
|
+
cursor: default;
|
|
283
|
+
}
|
|
284
|
+
.workitem_gantt .gantt_today { border-left: 2px solid #d33; z-index: 5; pointer-events: none; }
|
|
285
|
+
/* Plan-vs-actual tracking lanes (ADR-213): hidden until the toolbar toggle adds
|
|
286
|
+
show-actuals; a hidden lane's grid tracks collapse to zero height. */
|
|
287
|
+
.workitem_gantt .gantt_tracking_lane { display: none; }
|
|
288
|
+
.workitem_gantt.show-actuals .gantt_tracking_lane { display: block; }
|
|
289
|
+
.workitem_gantt .gantt_owner_tracking { font-weight: 400; font-style: italic; color: #57606a; }
|
|
290
|
+
.workitem_gantt .gantt_track_committed { background: #b0b6bd; }
|
|
291
|
+
.workitem_gantt .gantt_track_logged { background: #36a2eb; }
|
|
292
|
+
.gantt_container .gantt_toolbar {
|
|
293
|
+
display: flex;
|
|
294
|
+
justify-content: flex-end;
|
|
295
|
+
gap: 6px;
|
|
296
|
+
padding: 4px 0;
|
|
297
|
+
}
|
|
298
|
+
.gantt_container .gantt_actuals_toggle {
|
|
299
|
+
font-size: 12px;
|
|
300
|
+
padding: 3px 10px;
|
|
301
|
+
border: 1px solid #d0d7de;
|
|
302
|
+
border-radius: 4px;
|
|
303
|
+
background: #f6f8fa;
|
|
304
|
+
cursor: pointer;
|
|
305
|
+
}
|
|
306
|
+
.gantt_container .gantt_actuals_toggle:hover { background: #eef1f4; }
|
|
142
307
|
table.controlled:not(.odd-even) tbody tr:nth-child(odd) { background-color:#f6f7f8; }
|
|
143
308
|
table.controlled:not(.odd-even) tbody tr:nth-child(even) { background-color: #fff; }
|
|
144
309
|
table.controlled:not(.odd-even) tbody tr:nth-child(odd):hover,
|
|
@@ -224,7 +389,9 @@ img{
|
|
|
224
389
|
background: #EEEEEE;
|
|
225
390
|
border: 1px solid #ddd;
|
|
226
391
|
position: fixed;
|
|
227
|
-
|
|
392
|
+
top: 0; /* Anchor top and bottom so the pane spans exactly the */
|
|
393
|
+
bottom: 0; /* viewport; padding/border stay inside the border box so */
|
|
394
|
+
/* overflow-y scroll can reach the last items. */
|
|
228
395
|
visibility: hidden;
|
|
229
396
|
z-index: 1;
|
|
230
397
|
overflow-y: auto;
|
|
@@ -25,7 +25,9 @@ function openNav() {
|
|
|
25
25
|
document.getElementById("searchInput").style.display = "block";
|
|
26
26
|
}
|
|
27
27
|
}else{
|
|
28
|
-
|
|
28
|
+
var navPane = document.getElementById('nav_pane');
|
|
29
|
+
var hasNav = navPane && navPane.innerHTML.trim() !== "";
|
|
30
|
+
if (document.title.includes("Traceability Matrix:") || !hasNav){
|
|
29
31
|
document.getElementById('document_tree_menu_item').style.display = "none";
|
|
30
32
|
} else {
|
|
31
33
|
document.getElementById('document_tree_menu_item').style.display = "block";
|
|
@@ -74,7 +76,10 @@ function openNav() {
|
|
|
74
76
|
|
|
75
77
|
modal.style.display = "block";
|
|
76
78
|
modalImg.src = clicked.src;
|
|
77
|
-
|
|
79
|
+
// Author-supplied alt text: insert as plain text, never as HTML (ADR-188).
|
|
80
|
+
// Reading clicked.alt yields the decoded value, so innerHTML here would
|
|
81
|
+
// re-parse author markup as live DOM (DOM-based XSS).
|
|
82
|
+
captionText.textContent = clicked.alt;
|
|
78
83
|
}
|
|
79
84
|
|
|
80
85
|
function modal_close_OnClick(clicked){
|
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
// Do search only on the Index Page
|
|
2
2
|
import { create, search, insert } from 'https://unpkg.com/@orama/orama@3.1.18/dist/browser/index.js'
|
|
3
3
|
|
|
4
|
+
// Author-derived values are treated as untrusted (ADR-188). Every result field
|
|
5
|
+
// is inserted with safe DOM interfaces (createTextNode / property assignment) and
|
|
6
|
+
// never parsed as HTML, and any URL is admitted only if it is a relative reference
|
|
7
|
+
// or uses an allowed scheme; otherwise the link is rendered inert.
|
|
8
|
+
const ALLOWED_URL_SCHEMES = ['http', 'https', 'mailto'];
|
|
9
|
+
function safeUrl(url) {
|
|
10
|
+
const s = (url == null ? '' : String(url)).trim();
|
|
11
|
+
const m = s.match(/^([a-z][a-z0-9+.-]*):/i);
|
|
12
|
+
if (!m) return s; // relative path or anchor
|
|
13
|
+
return ALLOWED_URL_SCHEMES.includes(m[1].toLowerCase()) ? s : '#';
|
|
14
|
+
}
|
|
15
|
+
|
|
4
16
|
// Create DB
|
|
5
17
|
const db = await create({
|
|
6
18
|
schema: {
|
|
@@ -87,19 +99,20 @@ async function search_onKeyUp(){
|
|
|
87
99
|
let cell = document.createElement("td");
|
|
88
100
|
let i = document.createElement("i");
|
|
89
101
|
i.classList.add("fa","fa-file-text-o");
|
|
90
|
-
|
|
102
|
+
if (/^[0-9a-fA-F]{3,8}$/.test(doc_color)) {
|
|
103
|
+
i.style.backgroundColor = "#" + doc_color;
|
|
104
|
+
}
|
|
91
105
|
cell.appendChild(i);
|
|
92
106
|
let textnode = document.createTextNode("\xa0" + doc_title);
|
|
93
107
|
cell.appendChild(textnode);
|
|
94
108
|
row.appendChild(cell)
|
|
95
109
|
cell = document.createElement("td");
|
|
96
110
|
|
|
97
|
-
const a = document.createElement('a');
|
|
111
|
+
const a = document.createElement('a');
|
|
98
112
|
const link = document.createTextNode(heading_text)
|
|
99
113
|
a.appendChild(link);
|
|
100
114
|
a.title = heading_text;
|
|
101
|
-
a.href = heading_url;
|
|
102
|
-
document.body.appendChild(a);
|
|
115
|
+
a.href = safeUrl(heading_url);
|
|
103
116
|
|
|
104
117
|
cell.appendChild(a);
|
|
105
118
|
row.appendChild(cell)
|
data/lib/almirah.rb
CHANGED
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.
|
|
4
|
+
version: 0.4.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Oleksandr Ivanov
|
|
@@ -73,28 +73,38 @@ files:
|
|
|
73
73
|
- lib/almirah/doc_items/markdown_list.rb
|
|
74
74
|
- lib/almirah/doc_items/markdown_table.rb
|
|
75
75
|
- lib/almirah/doc_items/paragraph.rb
|
|
76
|
+
- lib/almirah/doc_items/scope_table.rb
|
|
76
77
|
- lib/almirah/doc_items/source_code_paragraph.rb
|
|
77
78
|
- lib/almirah/doc_items/text_line.rb
|
|
78
79
|
- lib/almirah/doc_items/todo_block.rb
|
|
80
|
+
- lib/almirah/doc_items/work_item.rb
|
|
79
81
|
- lib/almirah/doc_parser.rb
|
|
80
82
|
- lib/almirah/doc_types/base_document.rb
|
|
81
83
|
- lib/almirah/doc_types/coverage.rb
|
|
84
|
+
- lib/almirah/doc_types/critical_chain_page.rb
|
|
82
85
|
- lib/almirah/doc_types/decision.rb
|
|
86
|
+
- lib/almirah/doc_types/decision_grouping.rb
|
|
83
87
|
- lib/almirah/doc_types/decisions_overview.rb
|
|
84
88
|
- lib/almirah/doc_types/implementation.rb
|
|
85
89
|
- lib/almirah/doc_types/index.rb
|
|
86
90
|
- lib/almirah/doc_types/persistent_document.rb
|
|
91
|
+
- lib/almirah/doc_types/planning_dates.rb
|
|
87
92
|
- lib/almirah/doc_types/protocol.rb
|
|
88
93
|
- lib/almirah/doc_types/source_file.rb
|
|
89
94
|
- lib/almirah/doc_types/specification.rb
|
|
90
95
|
- lib/almirah/doc_types/traceability.rb
|
|
91
96
|
- lib/almirah/dom/doc_section.rb
|
|
92
97
|
- lib/almirah/dom/document.rb
|
|
98
|
+
- lib/almirah/html_safe.rb
|
|
93
99
|
- lib/almirah/link_registry.rb
|
|
94
100
|
- lib/almirah/navigation_pane.rb
|
|
95
101
|
- lib/almirah/project.rb
|
|
102
|
+
- lib/almirah/project/critical_chain.rb
|
|
96
103
|
- lib/almirah/project/doc_linker.rb
|
|
104
|
+
- lib/almirah/project/fever_chart.rb
|
|
97
105
|
- lib/almirah/project/project_data.rb
|
|
106
|
+
- lib/almirah/project/work_item_scheduler.rb
|
|
107
|
+
- lib/almirah/project/working_calendar.rb
|
|
98
108
|
- lib/almirah/project_configuration.rb
|
|
99
109
|
- lib/almirah/project_template.rb
|
|
100
110
|
- lib/almirah/project_utility.rb
|
|
@@ -124,7 +134,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
124
134
|
- !ruby/object:Gem::Version
|
|
125
135
|
version: '0'
|
|
126
136
|
requirements: []
|
|
127
|
-
rubygems_version: 4.0.
|
|
137
|
+
rubygems_version: 4.0.6
|
|
128
138
|
specification_version: 4
|
|
129
139
|
summary: Almirah
|
|
130
140
|
test_files: []
|