havocompare/report/
template.rs1pub const INDEX_FILENAME: &str = "index.html";
2pub const DETAIL_FILENAME: &str = "detail.html";
3pub const INDEX_TEMPLATE: &str = r##"
4<!DOCTYPE html>
5<html lang="en">
6<head>
7 <meta charset="UTF-8">
8 <title>Report</title>
9 <style>
10
11 .error {
12 background-color: #fbcccc !important;
13 }
14
15 h3 {
16 background-color:black;
17 color:white;
18 padding:10px;
19 margin:10px 0;
20 cursor:pointer;
21 }
22
23 .container {
24 padding:10px;
25 }
26
27 .dataTables_wrapper {
28 font-family: monospace;
29 font-size: 10pt;
30 }
31
32 table.dataTable tbody td {
33 padding:0px 0px !important;
34 }
35
36 .text-error {
37 color:red;
38 }
39
40 .ui-accordion-header-active:before {
41 content: '-'
42 }
43
44 .ui-accordion-header-collapsed:before {
45 content: '+'
46 }
47
48 </style>
49 <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/dt/dt-1.12.1/datatables.min.css"/>
50</head>
51<body>
52
53<div id="accordion">
54{% for rule_report in rule_results %}
55 <h3>
56 {{ rule_report.rule.name }}
57 </h3>
58 <div class="container">
59 <table class="report cell-border">
60 <thead>
61 {% if rule_report.rule.FileProperties %}
62 <tr>
63 <th>File</th>
64 <th colspan="2">File Size</th>
65 <th colspan="2">Creation date</th>
66 <th>Result</th>
67 </tr>
68 <tr>
69 <th></th>
70 <th>Nominal</th>
71 <th>Actual</th>
72 <th>Nominal</th>
73 <th>Actual</th>
74 <th></th>
75 </tr>
76 {% else %}
77 <tr>
78 <th>File</th>
79 <th>Result</th>
80 </tr>
81 {% endif %}
82 </thead>
83 <tbody>
84 {% for file in rule_report.diffs %}
85 <tr {% if file.is_error %} class="error" {% endif %}>
86 {% if rule_report.rule.FileProperties %}
87 <td {% if file.additional_columns.0.is_error %} class="text-error" {% endif %}>
88 {{ file.relative_file_path }}
89 </td>
90 <td {% if file.additional_columns.1.is_error %} class="text-error" {% endif %}>
91 {{ file.additional_columns.1.nominal_value }}
92 </td>
93 <td {% if file.additional_columns.1.is_error %} class="text-error" {% endif %}>
94 {{ file.additional_columns.1.actual_value }}
95 </td>
96 <td {% if file.additional_columns.2.is_error %} class="text-error" {% endif %}>
97 {{ file.additional_columns.2.nominal_value }}
98 </td>
99 <td {% if file.additional_columns.2.is_error %} class="text-error" {% endif %}>
100 {{ file.additional_columns.2.actual_value }}
101 </td>
102 <td>{% if file.is_error %} <span class="text-error">✖</span> {% else %} <span style="color:green;">✔</span> {% endif %}</td>
103 {% else %}
104 <td>
105 {% if file.detail_path %}
106 <a href="./{{ rule_report.rule.name }}/{{ file.detail_path.name }}/{{ detail_filename }}">{{ file.relative_file_path }}</a>
107 {% else %}
108 {{ file.relative_file_path }}
109 {% endif %}
110 </td>
111 <td>{% if file.is_error %} <span class="text-error">✖</span> {% else %} <span style="color:green;">✔</span> {% endif %}</td>
112 {% endif %}
113 </tr>
114 {% endfor %}
115 </tbody>
116 </table>
117 </div>
118{% endfor %}
119</div>
120
121<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
122<script
123 src="https://code.jquery.com/ui/1.13.2/jquery-ui.min.js"
124 integrity="sha256-lSjKY0/srUM9BE3dPm+c4fBo1dky2v27Gdjm2uoZaL0="
125 crossorigin="anonymous"></script>
126<script type="text/javascript" src="https://cdn.datatables.net/v/dt/dt-1.12.1/datatables.min.js"></script>
127<script>
128 document.addEventListener('DOMContentLoaded', function () {
129 let table = new DataTable('.report');
130 });
131
132 $(function() {
133 $( "#accordion" ).accordion();
134 });
135</script>
136</body>
137</html>
138"##;
139
140pub const PLAIN_TEXT_DETAIL_TEMPLATE: &str = r#"
141<!DOCTYPE html>
142<html lang="en">
143<head>
144 <meta charset="UTF-8">
145 <title>Error(s)</title>
146 <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/dt/dt-1.12.1/datatables.min.css"/>
147
148 <style>
149
150 h3 {
151 background-color:black;
152 color:white;
153 padding:10px;
154 margin:10px 0;
155 cursor:pointer;
156 }
157
158 table {
159 table-layout: fixed;
160 }
161
162 table.dataTable tr.odd {
163 background-color: #dddddd;
164 }
165
166 </style>
167</head>
168<body>
169
170<h3>Compare Result of {{ actual }} and {{ nominal }}</h3>
171
172<table id="report">
173 <thead>
174 <tr>
175 <th>Error</th>
176 </tr>
177 </thead>
178 <tbody>
179 {% for error in errors %}
180 <tr>
181 <td>{{ error }}</td>
182 </tr>
183 {% endfor %}
184 </tbody>
185</table>
186
187<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
188<script type="text/javascript" src="https://cdn.datatables.net/v/dt/dt-1.12.1/datatables.min.js"></script>
189<script>
190 document.addEventListener('DOMContentLoaded', function () {
191 let table = new DataTable('#report');
192 });
193</script>
194
195</body>
196</html>
197"#;
198
199pub const PLAIN_IMAGE_DETAIL_TEMPLATE: &str = r#"
200<!DOCTYPE html>
201<html lang="en">
202<head>
203 <meta charset="UTF-8">
204 <title>Error(s)</title>
205 <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/dt/dt-1.12.1/datatables.min.css"/>
206
207 <style>
208
209 h3 {
210 background-color:black;
211 color:white;
212 padding:10px;
213 margin:10px 0;
214 cursor:pointer;
215 }
216
217 table {
218 table-layout: fixed;
219 }
220
221 table.dataTable tr.odd {
222 background-color: #dddddd;
223 }
224
225 </style>
226</head>
227<body>
228
229<h3>Compare Result of {{ actual }} and {{ nominal }}</h3>
230
231<table id="report">
232 <thead>
233 <tr>
234 <th>Error</th>
235 </tr>
236 </thead>
237 <tbody>
238 <tr>
239 <td>{{ error }}</td>
240 </tr>
241 </tbody>
242</table>
243
244<p>
245<h3>Nominal:</h3>
246<img src="./{{ nominal_image }}" />
247</p>
248
249<p>
250<h3>Actual:</h3>
251<img src="./{{ actual_image }}" />
252</p>
253
254{% if diff_image %}
255<p>
256<h3>Diff:</h3>
257<img src="./{{ diff_image }}" />
258</p>
259{% endif %}
260
261<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
262<script type="text/javascript" src="https://cdn.datatables.net/v/dt/dt-1.12.1/datatables.min.js"></script>
263<script>
264 document.addEventListener('DOMContentLoaded', function () {
265 let table = new DataTable('#report');
266 });
267</script>
268
269</body>
270</html>
271"#;
272
273pub const PLAIN_CSV_DETAIL_TEMPLATE: &str = r#"
274<!DOCTYPE html>
275<html lang="en">
276<head>
277 <meta charset="UTF-8">
278 <title>Results</title>
279 <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/dt/dt-1.12.1/datatables.min.css"/>
280
281 <style>
282
283 h3 {
284 background-color:black;
285 color:white;
286 padding:10px;
287 margin:10px 0;
288 cursor:pointer;
289 }
290
291 .actual {
292 color: #0d6efdf0;
293 }
294
295 .diffs {
296 color: #FF4646;
297 }
298
299 table.dataTable {
300 border: 1px solid #999999;
301 }
302
303 .dataTables_wrapper {
304 font-family: monospace;
305 font-size: 10pt;
306 }
307
308 table.dataTable th:not(:last-child), table.dataTable td:not(:last-child) {
309 border-right: 1px solid #999999;
310 }
311
312 .error {
313 background-color: #fbcccc !important;
314 }
315
316 table.dataTable td, table.dataTable th {
317 white-space:nowrap;
318 }
319
320 table.dataTable tbody td, table.dataTable thead th {
321 padding:0px 0px;
322 }
323
324 .pre-text {
325 white-space:pre;
326 }
327
328 </style>
329</head>
330<body>
331
332<h3>Compare Result</h3>
333<p>
334 <table>
335 <tbody>
336 <tr>
337 <td>Left file (nominal):</td>
338 <td>{{ nominal }}</td>
339 </tr>
340 <tr>
341 <td>Right file (actual):</td>
342 <td>{{ actual }}</td>
343 </tr>
344 </tbody>
345 </table>
346</p>
347
348{% if headers.columns|length <= 0 %}
349 <p><i>Header preprocessing not enabled in config</i></p>
350{% endif %}
351<table id="report" class="cell-border">
352 <thead>
353 {% if headers.columns|length > 0 %}
354 <tr {% if headers.has_diff %} class="error" {% endif %}>
355 <th>{% if headers.has_diff %}x<br> {% endif %}</th>
356 <th>{% if headers.has_diff %} <br>x{% endif %}</th>
357 {% for col in headers.columns %}
358 <th>
359 {{ col.nominal_value }}
360 {% if headers.has_diff %}
361 <div class="{% if col.nominal_value != col.actual_value %} diffs {% endif %}">{{ col.actual_value }}</div>
362 {% endif %}
363 </th>
364 {% endfor %}
365 </tr>
366 {% else %}
367 <tr>
368 <th> </th>
369 <th> </th>
370 {% for col in rows[0].columns %}
371 <th> </th>
372 {% endfor %}
373 </tr>
374 {% endif %}
375 </thead>
376 <tbody>
377 {% for row in rows %}
378 <tr {% if row.has_error %} class="error" {% endif %}>
379 <td data-order="{{ loop.index0 }}">{{ loop.index0 }}{% if row.has_diff or row.has_error %}<br> {% endif %}</td>
380 <td data-order="{{ loop.index0 }}">{% if row.has_diff or row.has_error %} <br>{% endif %}{{ loop.index0 }}</td>
381 {% for col in row.columns %}
382 <td>
383 <span class="pre-text">{{ col.nominal_value }}</span>
384 {% if row.has_diff or row.has_error %}
385 <div class="{% if col.diffs|length > 0 %} diffs {% elif col.nominal_value != col.actual_value %} actual {% else %} {% endif %}">
386 <span class="pre-text">{{ col.actual_value }}</span>
387 </div>
388 {% endif %}
389 </td>
390 {% endfor %}
391 </tr>
392 {% endfor %}
393 </tbody>
394</table>
395
396<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
397<script type="text/javascript" src="https://cdn.datatables.net/v/dt/dt-1.12.1/datatables.min.js"></script>
398<script>
399 document.addEventListener('DOMContentLoaded', function () {
400 let table = new DataTable('#report', {
401 lengthMenu: [ [5, 10, 25, 50, -1], [5, 10, 25, 50, "All"] ],
402 iDisplayLength: -1,
403 columnDefs: [
404 { type: "num", "targets": 0 },
405 { type: "num", "targets": 1 }
406 ],
407 bPaginate: false,
408 bLengthChange: false,
409 });
410 });
411</script>
412
413</body>
414</html>
415"#;
416
417pub const PLAIN_PDF_DETAIL_TEMPLATE: &str = r#"
418<!DOCTYPE html>
419<html lang="en">
420<head>
421 <meta charset="UTF-8">
422 <title>Results</title>
423 <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/dt/dt-1.12.1/datatables.min.css"/>
424
425 <style>
426
427 h3 {
428 background-color:black;
429 color:white;
430 padding:10px;
431 margin:10px 0;
432 cursor:pointer;
433 }
434
435 table {
436 table-layout: fixed;
437 }
438
439 table.dataTable tr.odd {
440 background-color: #dddddd;
441 }
442
443 .helper {
444 color:orange;
445 font-weight:bold;
446 }
447
448 .helper a {
449 color:orange;
450 }
451
452 .has_diff {
453 color: #0d6efdf0;
454 }
455
456 .has_error {
457 color:red;
458 }
459
460 #compare th {
461 text-align:left;
462 background-color: #cccccc;
463 padding:10px;
464 }
465
466 #compare td:first-child {
467 border-right: 1px solid black;
468 }
469
470 table#compare {
471 border:1px solid grey;
472 }
473
474 .pre-text {
475 white-space:pre;
476 }
477
478 </style>
479</head>
480<body>
481
482<h3>Compare Result of {{ actual }} and {{ nominal }}</h3>
483
484<div class="helper">
485This is for viewing only.
486The extracted exact text can be downloaded here: <a href="./{{ nominal_extracted_filename }}">nominal</a> and <a href="./{{ actual_extracted_filename }}">actual</a>
487</div>
488<table id="compare">
489 <thead>
490 <tr>
491 <th></th>
492 <th>Nominal</th>
493 <th>Actual</th>
494 </tr>
495 </thead>
496 <tbody>
497 {% for line in combined_lines %}
498 <tr>
499 <td>{{ loop.index }}</td>
500 <td><span class="pre-text">{{ line.nominal_value|safe }}</span></td>
501 <td>
502 {% if line.diffs|length > 0 %}
503 <span class="pre-text has_error">{{ line.actual_value|safe }}</span>
504 {% elif line.actual_value != line.nominal_value %}
505 <span class="pre-text has_diff">{{ line.actual_value|safe }}</span>
506 {% else %}
507 <span class="pre-text">{{ line.actual_value|safe }}</span>
508 {% endif %}
509 </td>
510 </tr>
511 {% endfor %}
512 </tbody>
513</table>
514
515<br>
516<br>
517
518<table id="report">
519 <thead>
520 <tr>
521 <th>Error</th>
522 </tr>
523 </thead>
524 <tbody>
525 {% for error in errors %}
526 <tr>
527 <td>{{ error }}</td>
528 </tr>
529 {% endfor %}
530 </tbody>
531</table>
532
533<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
534<script type="text/javascript" src="https://cdn.datatables.net/v/dt/dt-1.12.1/datatables.min.js"></script>
535<script>
536 document.addEventListener('DOMContentLoaded', function () {
537 let table = new DataTable('#report');
538 });
539</script>
540
541</body>
542</html>
543"#;
544
545pub const ERROR_DETAIL_TEMPLATE: &str = r#"
546<!DOCTYPE html>
547<html lang="en">
548<head>
549 <meta charset="UTF-8">
550 <title>Error(s)</title>
551 <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/dt/dt-1.12.1/datatables.min.css"/>
552
553 <style>
554
555 h3 {
556 background-color:black;
557 color:white;
558 padding:10px;
559 margin:10px 0;
560 cursor:pointer;
561 }
562
563 table {
564 table-layout: fixed;
565 }
566
567 table.dataTable#report tbody tr {
568 background-color: #fbcccc;
569 }
570
571 </style>
572</head>
573<body>
574
575<p>
576 <table>
577 <tbody>
578 <tr>
579 <td>Nominal:</td>
580 <td>{{ nominal }}</td>
581 </tr>
582 <tr>
583 <td>Actual:</td>
584 <td>{{ actual }}</td>
585 </tr>
586 </tbody>
587 </table>
588</p>
589
590<table id="report">
591 <thead>
592 <tr>
593 <th>Error</th>
594 </tr>
595 </thead>
596 <tbody>
597 {% for error in errors %}
598 <tr>
599 <td>{{ error }}</td>
600 </tr>
601 {% endfor %}
602 </tbody>
603</table>
604
605<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
606<script type="text/javascript" src="https://cdn.datatables.net/v/dt/dt-1.12.1/datatables.min.js"></script>
607<script>
608 document.addEventListener('DOMContentLoaded', function () {
609 let table = new DataTable('#report', {
610 iDisplayLength: -1,
611 bPaginate: false,
612 bLengthChange: false,
613 bFilter: false,
614 bInfo: false
615 });
616 });
617</script>
618
619</body>
620</html>
621"#;
622
623pub const PLAIN_EXTERNAL_DETAIL_TEMPLATE: &str = r#"
624<!DOCTYPE html>
625<html lang="en">
626<head>
627 <meta charset="UTF-8">
628 <title>Results</title>
629 <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/dt/dt-1.12.1/datatables.min.css"/>
630
631 <style>
632
633 h3 {
634 background-color:black;
635 color:white;
636 padding:10px;
637 margin:10px 0;
638 cursor:pointer;
639 }
640
641 table {
642 table-layout: fixed;
643 }
644
645 table.dataTable tr.odd {
646 background-color: #dddddd;
647 }
648
649 .has_diff {
650 color: #0d6efdf0;
651 }
652
653 .has_error {
654 color:red;
655 }
656
657 #compare th {
658 text-align:left;
659 background-color: #cccccc;
660 padding:10px;
661 }
662
663 #compare td {
664 white-space: pre;
665 }
666
667 #compare td:first-child {
668 border-right: 1px solid black;
669 }
670
671 table#compare {
672 border:1px solid grey;
673 }
674
675 </style>
676</head>
677<body>
678
679<h3>Compare Result of {{ actual }} and {{ nominal }}</h3>
680
681<table id="compare">
682 <thead>
683 <tr>
684 <th>Stdout</th>
685 <th>Stderr</th>
686 </tr>
687 </thead>
688 <tbody>
689 <tr>
690 <td>
691{{ stdout }}
692 </td>
693 <td class="has_error">
694{{ stderr }}
695 </td>
696 </tr>
697 </tbody>
698</table>
699
700
701</body>
702</html>
703"#;
704
705pub const PLAIN_JSON_DETAIL_TEMPLATE: &str = r#"
706<!DOCTYPE html>
707<html lang="en">
708<head>
709 <meta charset="UTF-8">
710 <title>Results</title>
711 <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/dt/dt-1.12.1/datatables.min.css"/>
712
713 <style>
714
715 h3 {
716 background-color:black;
717 color:white;
718 padding:10px;
719 margin:10px 0;
720 cursor:pointer;
721 }
722
723 table {
724 table-layout: fixed;
725 }
726
727 table.dataTable tr.odd {
728 background-color: #dddddd;
729 }
730
731 .has_diff {
732 color: #0d6efdf0;
733 }
734
735 .has_right {
736 color:green;
737 }
738 .has_left {
739 color:red;
740 }
741
742 #compare th {
743 text-align:left;
744 background-color: #cccccc;
745 padding:10px;
746 }
747
748 #compare td {
749 white-space: pre;
750 }
751
752 #compare td:first-child {
753 border-right: 1px solid black;
754 }
755
756 table#compare {
757 border:1px solid grey;
758 }
759
760 </style>
761</head>
762<body>
763
764<h3>Compare Result of {{ actual }} and {{ nominal }}</h3>
765<div>{{ root_mismatch }} </div>
766<table id="compare">
767 <thead>
768 <tr>
769 <th>Left extra</th>
770 <th>Differences</th>
771 <th>Right extra</th>
772 </tr>
773 </thead>
774 <tbody>
775 <tr>
776 <td class="has_left">
777{{ left }}
778 </td>
779 <td >
780{{ differences }}
781 </td>
782 <td class="has_right">
783{{ right }}
784 </td>
785 </tr>
786 </tbody>
787</table>
788
789
790</body>
791</html>
792"#;
793
794pub const DIRECTORY_DETAIL_TEMPLATE: &str = r#"
795<!DOCTYPE html>
796<html lang="en">
797<head>
798 <meta charset="UTF-8">
799 <title>Results</title>
800 <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/dt/dt-1.12.1/datatables.min.css"/>
801
802 <style>
803
804 h3 {
805 background-color:black;
806 color:white;
807 padding:10px;
808 margin:10px 0;
809 cursor:pointer;
810 }
811
812 .actual {
813 color: #0d6efdf0;
814 }
815
816 .diffs {
817 color: #FF4646;
818 }
819
820 table.dataTable {
821 border: 1px solid #999999;
822 }
823
824 .dataTables_wrapper {
825 font-family: monospace;
826 font-size: 10pt;
827 }
828
829 table.dataTable th:not(:last-child), table.dataTable td:not(:last-child) {
830 border-right: 1px solid #999999;
831 }
832
833 .error {
834 background-color: #fbcccc !important;
835 }
836
837 table.dataTable td, table.dataTable th {
838 white-space:nowrap;
839 }
840
841 table.dataTable tbody td, table.dataTable thead th {
842 padding:0px 0px;
843 }
844
845 .pre-text {
846 white-space:pre;
847 }
848
849 .text-error {
850 color:red;
851 }
852
853 </style>
854</head>
855<body>
856
857<h3>Compare Result</h3>
858
859<p>Mode: {{ mode }}</p>
860
861<table id="report" class="cell-border">
862 <thead>
863 <tr>
864 <th>nominal: {{ nominal }}</th>
865 <th>actual: {{ actual }}</th>
866 <th> </th>
867 </tr>
868 </thead>
869 <tbody>
870 {% for row in rows %}
871 <tr {% if row.2 %} class="error" {% endif %}>
872 <td>{{ row.0 }}</td>
873 <td>{{ row.1 }}</td>
874 <td>{% if row.2 %}<span class="text-error">✖</span> {% else %} <span style="color:green;">✔</span>{% endif %}</td>
875 </tr>
876 {% endfor %}
877 </tbody>
878</table>
879
880<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
881<script type="text/javascript" src="https://cdn.datatables.net/v/dt/dt-1.12.1/datatables.min.js"></script>
882<script>
883 document.addEventListener('DOMContentLoaded', function () {
884 let table = new DataTable('#report', {
885 lengthMenu: [ [5, 10, 25, 50, -1], [5, 10, 25, 50, "All"] ],
886 iDisplayLength: -1,
887 columnDefs: [
888 { type: "num", "targets": 0 },
889 { type: "num", "targets": 1 }
890 ],
891 bPaginate: false,
892 bLengthChange: false,
893 });
894 });
895</script>
896
897</body>
898</html>
899"#;