1+ <!DOCTYPE html>  
2+ < html  lang ="en "> 
3+ < head > 
4+     < meta  charset ="UTF-8 "> 
5+     < meta  name ="viewport " content ="width=device-width, initial-scale=1.0 "> 
6+     < title > Accessibility Test Report - {{ summary.test_info.url }}</ title > 
7+     < style > 
8+         body  {
9+             font-family :  'Segoe UI' ,  Tahoma,  Geneva,  Verdana,  sans-serif;
10+             line-height :  1.6 ;
11+             margin :  0 ;
12+             padding :  20px  ;
13+             background-color :  # f5f5f5
14+         }
15+         .container  {
16+             max-width :  1200px  ;
17+             margin :  0  auto;
18+             background :  white;
19+             border-radius :  8px  ;
20+             box-shadow :  0  2px   10px   rgba (0 , 0 , 0 , 0.1 );
21+         }
22+         .header  {
23+             background :  linear-gradient (135deg  ,  # 667eea0%  ,  # 764ba2100%  );
24+             color :  white;
25+             padding :  30px  ;
26+             text-align :  center;
27+         }
28+         .header  h1  {
29+             margin :  0 ;
30+             font-size :  2.5em  ;
31+             font-weight :  300 ;
32+         }
33+         .header  .subtitle  {
34+             margin-top :  10px  ;
35+             opacity :  0.9 ;
36+             font-size :  1.1em  ;
37+         }
38+         .summary-stats  {
39+             display :  grid;
40+             grid-template-columns :  repeat (auto-fit,  minmax (200px  ,  1fr  ));
41+             gap :  20px  ;
42+             padding :  30px  ;
43+             background :  # f8f9fa
44+         }
45+         .stat-card  {
46+             background :  white;
47+             padding :  20px  ;
48+             border-radius :  8px  ;
49+             text-align :  center;
50+             box-shadow :  0  2px   5px   rgba (0 , 0 , 0 , 0.1 );
51+         }
52+         .stat-number  {
53+             font-size :  2.5em  ;
54+             font-weight :  bold;
55+             margin-bottom :  10px  ;
56+         }
57+         .stat-label  {
58+             color :  # 666
59+             font-size :  0.9em  ;
60+             text-transform :  uppercase;
61+             letter-spacing :  1px  ;
62+         }
63+         .violations  {
64+             color :  # dc3545
65+         }
66+         .passes  {
67+             color :  # 28a745
68+         }
69+         .inapplicable  {
70+             color :  # 6c757d
71+         }
72+         .incomplete  {
73+             color :  # ffc107
74+         }
75+         .content  {
76+             padding :  30px  ;
77+         }
78+         .section  {
79+             margin-bottom :  40px  ;
80+         }
81+         .section  h2  {
82+             color :  # 333
83+             border-bottom :  2px   solid # 667eea
84+             padding-bottom :  10px  ;
85+             margin-bottom :  20px  ;
86+         }
87+         .violation-card  {
88+             background :  # fff5f5
89+             border-left :  4px   solid # dc3545
90+             margin-bottom :  20px  ;
91+             border-radius :  4px  ;
92+             overflow :  hidden;
93+         }
94+         .violation-header  {
95+             background :  # dc3545
96+             color :  white;
97+             padding :  15px   20px  ;
98+             font-weight :  bold;
99+         }
100+         .violation-body  {
101+             padding :  20px  ;
102+         }
103+         .impact-badge  {
104+             display :  inline-block;
105+             padding :  4px   8px  ;
106+             border-radius :  4px  ;
107+             font-size :  0.8em  ;
108+             font-weight :  bold;
109+             text-transform :  uppercase;
110+         }
111+         .impact-critical  {
112+             background :  # dc3545
113+             color :  white;
114+         }
115+         .impact-serious  {
116+             background :  # fd7e14
117+             color :  white;
118+         }
119+         .impact-moderate  {
120+             background :  # ffc107
121+             color :  black;
122+         }
123+         .impact-minor  {
124+             background :  # 6c757d
125+             color :  white;
126+         }
127+         .help-link  {
128+             color :  # 667eea
129+             text-decoration :  none;
130+         }
131+         .help-link : hover  {
132+             text-decoration :  underline;
133+         }
134+         .node-item  {
135+             background :  # f8f9fa
136+             border :  1px   solid # dee2e6
137+             border-radius :  4px  ;
138+             padding :  15px  ;
139+             margin :  10px   0 ;
140+             font-family :  monospace;
141+             font-size :  0.9em  ;
142+         }
143+         .node-html  {
144+             background :  # e9ecef
145+             padding :  10px  ;
146+             border-radius :  4px  ;
147+             margin :  10px   0 ;
148+             overflow-x :  auto;
149+         }
150+         .passes-grid  {
151+             display :  grid;
152+             grid-template-columns :  repeat (auto-fill,  minmax (300px  ,  1fr  ));
153+             gap :  15px  ;
154+         }
155+         .violations-grid  {
156+             max-height :  500px  ;
157+             overflow-y :  auto;
158+             padding-right :  10px  ;
159+         }
160+         .pass-card  {
161+             background :  # f8fff9
162+             border :  1px   solid # d4edda
163+             border-radius :  4px  ;
164+             padding :  15px  ;
165+         }
166+         .pass-card  h4  {
167+             color :  # 155724
168+             margin :  0  0  10px   0 ;
169+         }
170+         .tags  {
171+             display :  flex;
172+             flex-wrap :  wrap;
173+             gap :  5px  ;
174+             margin-top :  10px  ;
175+         }
176+         .tag  {
177+             background :  # e9ecef
178+             padding :  2px   8px  ;
179+             border-radius :  12px  ;
180+             font-size :  0.8em  ;
181+             color :  # 495057
182+         }
183+         .footer  {
184+             background :  # f8f9fa
185+             padding :  20px  ;
186+             text-align :  center;
187+             color :  # 666
188+             border-top :  1px   solid # dee2e6
189+         }
190+     </ style > 
191+ </ head > 
192+ < body > 
193+     < div  class ="container "> 
194+         < div  class ="header "> 
195+             < h1 > 🔍 Accessibility Test Report</ h1 > 
196+             < div  class ="subtitle "> 
197+                 < strong > URL:</ strong >  {{ summary.test_info.url }}< br > 
198+                 < strong > Test Date:</ strong >  {{ summary.test_info.test_date_formatted }}
199+             </ div > 
200+         </ div > 
201+         
202+         < div  class ="summary-stats "> 
203+             < div  class ="stat-card "> 
204+                 < div  class ="stat-number violations "> {{ summary.summary.violations_count }}</ div > 
205+                 < div  class ="stat-label "> Violations</ div > 
206+             </ div > 
207+             < div  class ="stat-card "> 
208+                 < div  class ="stat-number passes "> {{ summary.summary.passes_count }}</ div > 
209+                 < div  class ="stat-label "> Passes</ div > 
210+             </ div > 
211+             < div  class ="stat-card "> 
212+                 < div  class ="stat-number inapplicable "> {{ summary.summary.inapplicable_count }}</ div > 
213+                 < div  class ="stat-label "> Inapplicable</ div > 
214+             </ div > 
215+             < div  class ="stat-card "> 
216+                 < div  class ="stat-number incomplete "> {{ summary.summary.incomplete_count }}</ div > 
217+                 < div  class ="stat-label "> Incomplete</ div > 
218+             </ div > 
219+         </ div > 
220+         
221+         < div  class ="content "> 
222+             {% if result.violations and result.violations|length >  0 %}
223+             < div  class ="section "> 
224+                 < h2 > ❌ Accessibility Violations</ h2 > 
225+                 < div  class ="violations-grid "> 
226+                     {% for violation in result.violations %}
227+                     < div  class ="violation-card "> 
228+                         < div  class ="violation-header "> 
229+                             {{ violation.id|default('Unknown') }} - {{ violation.description|default('No description') }}
230+                             < span  class ="impact-badge impact-{{ violation.impact|default('minor') }} "> {{ violation.impact|default('minor') }}</ span > 
231+                         </ div > 
232+                         < div  class ="violation-body "> 
233+                             < p > < strong > Help:</ strong >  {{ violation.help|default('No help available') }}</ p > 
234+                             < p > < strong > Affected Elements:</ strong >  {{ violation.nodes|length if violation.nodes else 0 }}</ p > 
235+                             {% if violation.helpUrl %}
236+                             < p > < strong > More Info:</ strong >  < a  href ="{{ violation.helpUrl }} " class ="help-link " target ="_blank "> View Documentation</ a > </ p > 
237+                             {% endif %}
238+                             
239+                             {% if violation.tags %}
240+                             < div  class ="tags "> 
241+                                 {% for tag in violation.tags %}
242+                                 < span  class ="tag "> {{ tag }}</ span > 
243+                                 {% endfor %}
244+                             </ div > 
245+                             {% endif %}
246+                             
247+                             {% if violation.nodes and violation.nodes|length >  0 %}
248+                             < h4 > All Affected Elements ({{ violation.nodes|length }} total):</ h4 > 
249+                             {% for node in violation.nodes %}
250+                             < div  class ="node-item "> 
251+                                 < strong > Element {{ loop.index }}:</ strong > 
252+                                 < div  class ="node-html "> {{ node.html|default('No HTML available')|e }}</ div > 
253+                                 < strong > Target:</ strong >  {{ safe_join_target(node.target) }}
254+                                 < br > < strong > Impact:</ strong >  {{ node.impact|default('Unknown') }}
255+                                 < br > < strong > Issue:</ strong >  {{ node.failureSummary|default('No failure summary') }}
256+                             </ div > 
257+                             {% endfor %}
258+                             {% endif %}
259+                         </ div > 
260+                     </ div > 
261+                     {% endfor %}
262+                 </ div > 
263+             </ div > 
264+             {% else %}
265+             < div  class ="section "> 
266+                 < h2 > ✅ No Accessibility Violations Found!</ h2 > 
267+                 < p > Great job! No accessibility violations were detected on this page.</ p > 
268+             </ div > 
269+             {% endif %}
270+             
271+             {% if result.passes and result.passes|length >  0 %}
272+             < div  class ="section "> 
273+                 < h2 > ✅ Passed Tests</ h2 > 
274+                 < div  class ="passes-grid "> 
275+                     {% for passed in result.passes %}
276+                     < div  class ="pass-card "> 
277+                         < h4 > {{ passed.id|default('Unknown') }}</ h4 > 
278+                         < p > {{ passed.description|default('No description') }}</ p > 
279+                         < p > < strong > Elements tested:</ strong >  {{ passed.nodes|length if passed.nodes else 0 }}</ p > 
280+                         < p > < strong > Impact:</ strong >  {{ passed.impact|default('Unknown') }}</ p > 
281+                         {% if passed.tags %}
282+                         < div  class ="tags "> 
283+                             {% for tag in passed.tags %}
284+                             < span  class ="tag "> {{ tag }}</ span > 
285+                             {% endfor %}
286+                         </ div > 
287+                         {% endif %}
288+                     </ div > 
289+                     {% endfor %}
290+                 </ div > 
291+             </ div > 
292+             {% endif %}
293+         </ div > 
294+         
295+         < div  class ="footer "> 
296+             < p > Generated by ZeuZ</ p > 
297+         </ div > 
298+     </ div > 
299+ </ body > 
300+ </ html >  
0 commit comments