Skip to main content

wcag-em-report-to-rst.py (Source)

#!/usr/bin/env python
# coding: utf-8
# Copyright 2024 Christian Lawson-Perfect
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Convert a WCAG-EM report tool JSON file to reStructuredText
#
# This script converts the JSON file you get from the [WCAG-EM Report Tool](https://www.w3.org/WAI/eval/report-tool/) into reStructuredText markup.
#
# It needs the following files:
#
# * https://raw.githubusercontent.com/w3c/wai-wcag-em-report-tool/main/src/data/wcag.json - The data on WCAG criteria used by the report tool.
# * https://raw.githubusercontent.com/w3c/wai-wcag-em-report-tool/main/src/locales/en/WCAG.json - The English readable names for WCAG criteria. Save as ``WCAG_text.json``.
#
# Usage:
#
#   python wcag-em-report-to-rst.py product-report.json
from collections import defaultdict
from itertools import groupby
import json
import sys
# Load the report data, and the WCAG criterion data
report_json_filename = sys.argv[1]
with open(report_json_filename) as f:
    data = json.load(f)
with open('wcag.json') as f:
    wcag = json.load(f)
with open('WCAG_text.json') as f:
    wcag_text = json.load(f)
wcag_ids = {v['id']: v for v in wcag['2.2'].values()}
criteria_names = {k: v['TITLE'] for k,v in wcag_text['SUCCESS_CRITERION'].items()}
criteria = defaultdict(list)
for item in data['auditSample']:
    id = item['test']['id'][len('WCAG22:'):]
    criteria[id].append(item)
# For each criterion, gather info from the report
report = []
def indent_lines(text, indent):
    lines = text.split('\n')
    return lines[0]+'\n'.join(indent+line for line in lines[1:])
for key, criterion in criteria.items():
    description = ''
    result = ''
    for item in criterion:
        if 'description' in item['result']:
            description = item['result']['description']
            
        if 'Website' not in item['subject']['type']:
            continue
        result = item['result']['outcome']['title']
    result_map = {
        'Passed': 'Supports',
        'Not present': 'Not Applicable',
    }
    result = result_map.get(result, result)
    
    info = wcag_ids[key]
    num = info['num']
    conformanceLevel = info['conformanceLevel']
    name = criteria_names[num]
    report.append({
        'key': key,
        'description': indent_lines(description, ' '*6),
        'result': result,
        'num': num,
        'conformanceLevel': conformanceLevel,
        'name': name,
    })
# Criteria not assessed
#
# The following criteria were not assessed:
print("The following criteria were not assessed:\n")
not_assessed = [n for n in wcag_ids.values() if n['id'] not in criteria]
for n in not_assessed:
    print(f'''* {n['num']} {n['id']} ({n['conformanceLevel']}) https://www.w3.org/WAI/WCAG22/quickref/#{n['id']}''')
print('\n')
# Produce ReStructuredText of report
for level, items in groupby(sorted(report, key=lambda x: (x['conformanceLevel'], x['num'])), key=lambda x: x['conformanceLevel']):
    header = f'''Table 1: Success Criteria, Level {level}'''
    print(header)
    print('*'*len(header))
    print('''
.. list-table::
  :header-rows: 1
  -
     - Criteria
     - Conformance Level
     - Remarks and Explanations''')
    
    for item in items:
        print('''  -
    - .. _vpat-{key}:
        
      `{num}: {name} <https://www.w3.org/WAI/WCAG22/quickref/#{key}>`__ (Level {conformanceLevel})
    - {result}
    - {description}'''.format(**item))
    print('')