#!/usr/bin/env python3 """ Script that checks if Pygments styles meet the WCAG color contrast standards """ import sys import statistics import pygments.styles import wcag_contrast_ratio def hex2rgb(hexstr): hexstr = hexstr.lstrip('#') r = int(hexstr[:2], 16) / 255 g = int(hexstr[2:4], 16) / 255 b = int(hexstr[4:], 16) / 255 return (r, g, b) total_wcag_fails = 0 styles = [] for name in pygments.styles.get_all_styles(): style = pygments.styles.get_style_by_name(name) bgcolor = hex2rgb(style.background_color) contrasts = [ ( wcag_contrast_ratio.rgb( bgcolor, hex2rgb(style['color'] or '#000000') # we default to black because browsers also do ), ttype, ) for ttype, style in style.list_styles() ] if len(contrasts) == 0: continue styles.append( ( statistics.mean([x[0] for x in contrasts]), min([x[0] for x in contrasts]), name, ) ) bad_contrasts = [c for c in contrasts if not wcag_contrast_ratio.passes_AA(c[0])] print(f'=== {name} ===') if len(bad_contrasts) > 0: for contrast, ttype in sorted(bad_contrasts): print(f'{contrast:.2f} {ttype}') else: print('meets AA standard') print() total_wcag_fails += len(bad_contrasts) if total_wcag_fails: print(f'found {total_wcag_fails} contrasts that fail to meet the WCAG AA standard') print( '''According to WCAG: AA contrast is >= 4.5 AAA contrast is >= 7.0 ''' ) print('=== Styles ranked by contrast ===') print(' avg min name') for contrast, minimum, name in sorted(styles): print(f'{contrast:4.1f} {minimum:4.1f} {name}') sys.exit(1)