summaryrefslogtreecommitdiffstats
path: root/tests/contrast
diff options
context:
space:
mode:
Diffstat (limited to 'tests/contrast')
-rw-r--r--tests/contrast/min_contrasts.json50
-rw-r--r--tests/contrast/test_contrasts.py101
2 files changed, 151 insertions, 0 deletions
diff --git a/tests/contrast/min_contrasts.json b/tests/contrast/min_contrasts.json
new file mode 100644
index 0000000..a69d73f
--- /dev/null
+++ b/tests/contrast/min_contrasts.json
@@ -0,0 +1,50 @@
+{
+ "default": 4.5,
+ "emacs": 2.4,
+ "friendly": 2.2,
+ "friendly_grayscale": 2.2,
+ "colorful": 2.2,
+ "autumn": 2.2,
+ "murphy": 1.4,
+ "manni": 1.4,
+ "material": 1.6,
+ "monokai": 2.3,
+ "perldoc": 2.7,
+ "pastie": 2.5,
+ "borland": 2.3,
+ "trac": 2.3,
+ "native": 3.0,
+ "fruity": 1.6,
+ "bw": 21.0,
+ "vim": 1.3,
+ "vs": 3.6,
+ "tango": 2.4,
+ "rrt": 5.3,
+ "xcode": 5.1,
+ "igor": 3.6,
+ "paraiso-light": 1.3,
+ "paraiso-dark": 1.3,
+ "lovelace": 3.5,
+ "algol": 3.5,
+ "algol_nu": 3.5,
+ "arduino": 2.6,
+ "rainbow_dash": 2.1,
+ "abap": 2.5,
+ "solarized-dark": 1.5,
+ "solarized-light": 1.0,
+ "sas": 4.6,
+ "staroffice": 4.5,
+ "stata": 2.4,
+ "stata-light": 2.4,
+ "stata-dark": 3.4,
+ "inkpot": 1.0,
+ "zenburn": 1.6,
+ "gruvbox-dark": 4.0,
+ "gruvbox-light": 3.2,
+ "dracula": 1.4,
+ "one-dark": 3.7,
+ "lilypond": 2.3,
+ "nord": 2.4,
+ "nord-darker": 2.8,
+ "github-dark": 4.8
+} \ No newline at end of file
diff --git a/tests/contrast/test_contrasts.py b/tests/contrast/test_contrasts.py
new file mode 100644
index 0000000..517b34e
--- /dev/null
+++ b/tests/contrast/test_contrasts.py
@@ -0,0 +1,101 @@
+"""
+ Contrast Tests
+ ~~~~~~~~~~
+
+ Pygments styles should be accessible to people with suboptimal vision.
+ This test ensures that the minimum contrast of styles does not degrade,
+ and that every rule of a new style fulfills the WCAG AA standard.[1]
+
+ [1]: https://www.w3.org/WAI/WCAG21/Understanding/contrast-minimum.html
+"""
+
+import json
+import os
+import sys
+
+import pygments.styles
+import pygments.token
+import wcag_contrast_ratio
+
+JSON_FILENAME = os.path.join(os.path.dirname(__file__), "min_contrasts.json")
+WCAG_AA_CONTRAST = 4.5
+
+
+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)
+
+
+def get_style_contrasts(style_cls):
+ return [
+ (
+ round(
+ wcag_contrast_ratio.rgb(
+ hex2rgb(style["bgcolor"] or style_cls.background_color),
+ hex2rgb(style["color"] or "#000000")
+ # we default to black because browsers also do
+ ),
+ 1,
+ ),
+ ttype,
+ )
+ for ttype, style in style_cls.list_styles()
+ if ttype != pygments.token.Whitespace
+ ]
+
+
+def builtin_styles():
+ for style_name in pygments.styles.STYLE_MAP:
+ yield (style_name, pygments.styles.get_style_by_name(style_name))
+
+
+def min_contrasts():
+ return {
+ name: min(x[0] for x in get_style_contrasts(style))
+ for name, style in builtin_styles()
+ }
+
+
+def update_json():
+ with open(JSON_FILENAME, "w") as f:
+ json.dump(
+ min_contrasts(),
+ f,
+ indent=2,
+ )
+
+
+def test_contrasts(fail_if_improved=True):
+ with open(JSON_FILENAME) as f:
+ previous_contrasts = json.load(f)
+
+ for style_name in pygments.styles.STYLE_MAP:
+ style = pygments.styles.get_style_by_name(style_name)
+ contrasts = get_style_contrasts(style)
+ min_contrast = min([x[0] for x in contrasts])
+
+ bar = previous_contrasts.get(style_name, WCAG_AA_CONTRAST)
+
+ assert not min_contrast < bar, (
+ "contrast degradation for style '{}'\n"
+ "The following rules have a contrast lower than the required {}:\n\n"
+ "{}\n"
+ ).format(
+ style_name,
+ bar,
+ "\n".join(
+ [
+ "* {:.2f} {}".format(contrast, ttype)
+ for contrast, ttype in contrasts
+ if contrast < bar
+ ]
+ ),
+ )
+
+ if fail_if_improved:
+ assert (
+ not min_contrast > bar
+ ), "congrats, you improved a contrast! please run ./scripts/update_contrasts.py"