<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def render_html(data_dir, output_dir):
 """ The main workhorse of this script. Finds all the JSON data files from pa11ycrawler, and transforms them into HTML files via Jinja2 templating. """

    env = Environment(loader=PackageLoader('pa11ycrawler', 'templates'))
    env.globals["wcag_refs"] = wcag_refs
    pages = []
    counter = collections.Counter()
    grouped_violations = collections.defaultdict(dict)

    # render detail templates
    for data_file in data_dir.files('*.json'):
        data = json.load(data_file.open())
        num_error, num_warning, num_notice = pa11y_counts(data['pa11y'])

        data["num_error"] = num_error
        data["num_warning"] = num_warning
        data["num_notice"] = num_notice
        fname = data_file.namebase + ".html"
        html_path = output_dir / fname
        render_template(env, html_path, 'detail.html', data)

        data["filename"] = fname
        pages.append(data)

        for violation in data['pa11y']:
            violation_id = hashlib.md5(
                (violation['selector'] + violation['code']).encode('utf-8')
            ).hexdigest()

            if violation_id not in grouped_violations[violation['type']]:
                violation['pages'] = []
                grouped_violations[violation['type']][violation_id] = violation
                counter[violation['type']] += 1

            grouped_violations[violation['type']][violation_id]['pages'].append({
                'url': data['url'],
                'page_title': data['page_title']
            })

    def extract_nums(page):
        "Used to sort pages by violation counts"
        return (
            page["num_error"],
            page["num_warning"],
            page["num_notice"],
        )

    index_path = output_dir / INDEX_TEMPLATE
    render_template(env, index_path, INDEX_TEMPLATE, {
        "pages": sorted(pages, key=extract_nums, reverse=True),
        "num_error": counter["error"],
        "num_warning": counter["warning"],
        "num_notice": counter["notice"]
    })

    for violation_type in grouped_violations:
        unique_path = output_dir / u'{}s.html'.format(violation_type)
        render_template(env, unique_path, UNIQUE_TEMPLATE, {
            "grouped_violations": sorted(
                grouped_violations[violation_type].values(),
                key=lambda item: len(item['pages']),
                reverse=True
            ),
            "current_type": violation_type,
            "violation_counts": counter
        })