havocompare/report/
template.rs

1pub 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">&#10006;</span> {% else %} <span style="color:green;">&#10004;</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">&#10006;</span> {% else %} <span style="color:green;">&#10004;</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>&nbsp;{% endif %}</th>
356	    	<th>{% if headers.has_diff %}&nbsp;<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>&nbsp;</th>
369	    	<th>&nbsp;</th>
370	    	{% for col in rows[0].columns %}
371		    	<th>&nbsp;</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>&nbsp;{% endif %}</td>
380            	<td data-order="{{ loop.index0 }}">{% if row.has_diff or row.has_error %}&nbsp;<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>&nbsp</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">&#10006;</span> {% else %} <span style="color:green;">&#10004;</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"#;