Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion .github/workflows/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -131,12 +131,20 @@ jobs:
- if: ${{needs.get.outputs.filelist}}
name: Check out repo.
uses: actions/checkout@v6
- if: ${{needs.get.outputs.filelist}}
name: Install dependencies
run: pip3 install titlecase
- if: ${{needs.get.outputs.filelist}}
name: Check markdown meta.
run: |
pip3 install titlecase
shopt -s globstar extglob
python3 checks/run_meta_check.py ${{needs.get.outputs.filelist}}
- if: ${{needs.get.outputs.filelist}}
name: Run ARIA reference check (meta checks)
run: |
pip3 install -r requirements.txt
mkdocs build
python3 checks/run_aria_check.py
slurmcheck:
name: Check slurm scripts
if: ${{github.event_name != 'workflow_dispatch'|| inputs.checkSlurm}}
Expand Down Expand Up @@ -165,3 +173,4 @@ jobs:
fetch-depth: 0
- run: pip3 install -r requirements.txt
- run: ./checks/run_test_build.py
- run: python3 checks/run_aria_check.py
51 changes: 51 additions & 0 deletions checks/run_aria_check.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/usr/bin/env python3
"""Check built HTML for broken ARIA id references."""

from html.parser import HTMLParser
from pathlib import Path
import sys


class AriaParser(HTMLParser):
def __init__(self):
super().__init__()
self.ids = set()
self.refs = []

def handle_starttag(self, tag, attrs):
d = dict(attrs)
if "id" in d:
self.ids.add(d["id"])
for key in ["aria-labelledby", "aria-describedby", "aria-controls"]:
if key in d:
for ref in d[key].split():
self.refs.append((key, ref, tag))


def main():
base = Path("public")
if not base.exists():
print("::error file=checks/run_aria_check.py,title=missing_public_dir::public folder not found. Run mkdocs build first.")
return 1

broken = []
for path in sorted(base.rglob("*.html")):
text = path.read_text(encoding="utf-8", errors="ignore")
parser = AriaParser()
parser.feed(text)
for key, ref, tag in parser.refs:
if ref not in parser.ids:
broken.append((path, key, ref, tag))

if broken:
for path, key, ref, tag in broken:
print(f"::error file={path},title=broken_aria_reference,col=0,endColumn=0,line=0::{key} reference '{ref}' missing id in tag <{tag}>")
print(f"Found {len(broken)} broken aria references.")
return 1

print("ARIA reference check passed.")
return 0


if __name__ == "__main__":
raise SystemExit(main())
5 changes: 4 additions & 1 deletion docs/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ From a pull request, the status of these checks can be seen in the 'Checks' tab,

Will give three levels of output, **Errors** (serious issues that will prevent merging into main), **Warnings** (non-critical suggestions for improvement) and **Info** (pedantry).

### ARIA and accessibility checks

The CI now includes an ARIA reference validation step that checks generated HTML for broken references like `aria-labelledby`, `aria-describedby`, and `aria-controls` IDs. If this check fails, the PR will show an error in the 'Checks' tab and the broken ARIA reference will be indicated.

### Codespace Environment

Expand Down Expand Up @@ -170,7 +173,7 @@ After a few minutes, a preview of the source branch will be deployed, a bot will

Assign a reviewer if you wish.

Adding the tag <a id="label-987ef8" href="https://github.com/nesi/support-docs/labels/auto_merge" data-name="auto_merge" style="--label-r:217;--label-g:244;--label-b:210;--label-h:107;--label-s:60;--label-l:89;" data-view-component="true" class="IssueLabel hx_IssueLabel Label--inline" aria-describedby="tooltip-466464af-99fc-4bc8-87c9-f5d794783843"> will cause the request to be merged at midnight, if all checks passed.
Adding the tag <a id="label-987ef8" href="https://github.com/nesi/support-docs/labels/auto_merge" data-name="auto_merge" style="--label-r:217;--label-g:244;--label-b:210;--label-h:107;--label-s:60;--label-l:89;" data-view-component="true" class="IssueLabel hx_IssueLabel Label--inline"> will cause the request to be merged at midnight, if all checks passed.

### Reviewing A Merge Request

Expand Down
6 changes: 3 additions & 3 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,17 @@ Technical documentation for our High Performance Computing (HPC) platforms.
<p>Access the cluster Via the OnDemand web application.</p>
</a>
<a href="Scientific_Computing/Batch_Jobs/Hardware/">
<img alt="account details" src="assets/icons/material/widget-small.svg">
<img alt="HPC resources" src="assets/icons/material/widget-small.svg">
<h3>Resources</h3>
<p>What CPUs and GPUs are available on the REANNZ Cluster.</p>
</a>
<a href="Data_Transfer/Data_Transfer_Overview/">
<img alt="ssh setup" src="./assets/icons/material/file-arrow-up-down.svg">
<img alt="Data transfer" src="./assets/icons/material/file-arrow-up-down.svg">
<h3>Data Transfer</h3>
<p>Getting your data on and off the cluster.</p>
</a>
<a href="Getting_Started/Next_Steps/Submitting_your_first_job#slurm">
<img alt="ondemand" src="assets/icons/material/tray-full.svg">
<img alt="Job scheduler" src="assets/icons/material/tray-full.svg">
<h3>Job Scheduler</h3>
<p>How to use our job scheduler, Slurm.</p>
</a>
Expand Down
9 changes: 3 additions & 6 deletions overrides/partials/header.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
{#-
This file was automatically generated - do not edit
-#}
{% set class = "md-header" %}
{% if "navigation.tabs.sticky" in features %}
{% set class = class ~ " md-header--shadow md-header--lifted" %}
Expand All @@ -9,10 +6,10 @@
{% endif %}
<header class="{{ class }}" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="{{ lang.t('header') }}">
<a href="{{ config.extra.homepage | d(nav.homepage.url, true) | url }}" title="Formerly 'New Zealand eScience Infrastructure'" class="md-header__button md-logo" aria-label="Formerly 'New Zealand eScience Infrastructure'" data-md-component="logo">
<a href="{{ config.extra.homepage | d(nav.homepage.url, true) | url }}" title="REANNZ" class="md-header__button md-logo" aria-label="REANNZ" data-md-component="logo">
{% include "partials/logo.html" %}
</a>
<label class="md-header__button md-icon" for="__drawer">
<label class="md-header__button md-icon" for="__drawer" aria-label="Navigation menu">
{% set icon = config.theme.icon.menu or "material/menu" %}
{% include ".icons/" ~ icon ~ ".svg" %}
</label>
Expand Down Expand Up @@ -46,7 +43,7 @@
{% include "partials/alternate.html" %}
{% endif %}
{% if "material/search" in config.plugins %}
<label class="md-header__button md-icon" for="__search">
<label class="md-header__button md-icon" for="__search" aria-label="Search">
{% set icon = config.theme.icon.search or "material/magnify" %}
{% include ".icons/" ~ icon ~ ".svg" %}
</label>
Expand Down
167 changes: 167 additions & 0 deletions overrides/partials/nav-item.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
{% macro render_status(nav_item, type) %}
{% set class = "md-status md-status--" ~ type %}
{% if config.extra.status and config.extra.status[type] %}
<span class="{{ class }}" title="{{ config.extra.status[type] }}">
</span>
{% else %}
<span class="{{ class }}"></span>
{% endif %}
{% endmacro %}
{% macro render_title(nav_item) %}
{% if nav_item.typeset %}
<span class="md-typeset">
{{ nav_item.typeset.title }}
</span>
{% else %}
{{ nav_item.title }}
{% endif %}
{% endmacro %}
{% macro render_content(nav_item, ref) %}
{% set ref = ref or nav_item %}
{% if nav_item.meta and nav_item.meta.icon %}
{% include ".icons/" ~ nav_item.meta.icon ~ ".svg" %}
{% endif %}
<span class="md-ellipsis">
{{ render_title(ref) }}
{% if nav_item.meta and nav_item.meta.subtitle %}
<br>
<small>{{ nav_item.meta.subtitle }}</small>
{% endif %}
</span>
{% if nav_item.meta and nav_item.meta.encrypted %}
{{ render_status(nav_item, "encrypted") }}
{% endif %}
{% if nav_item.meta and nav_item.meta.status %}
{{ render_status(nav_item, nav_item.meta.status) }}
{% endif %}
{% endmacro %}
{% macro render_pruned(nav_item, ref) %}
{% set ref = ref or nav_item %}
{% set first = nav_item.children | first %}
{% if first and first.children %}
{{ render_pruned(first, ref) }}
{% else %}
<a href="{{ first.url | url }}" class="md-nav__link">
{{ render_content(ref) }}
{% if nav_item.children | length > 0 %}
<span class="md-nav__icon md-icon"></span>
{% endif %}
</a>
{% endif %}
{% endmacro %}
{% macro render(nav_item, path, level, parent) %}
{% set class = "md-nav__item" %}
{% if nav_item.active %}
{% set class = class ~ " md-nav__item--active" %}
{% endif %}
{% if nav_item.pages %}
{% if page in nav_item.pages %}
{% set nav_item = page %}
{% endif %}
{% endif %}
{% if nav_item.children %}
{% set _ = namespace(index = none) %}
{% if "navigation.indexes" in features %}
{% for item in nav_item.children %}
{% if item.is_index and _.index is none %}
{% set _.index = item %}
{% endif %}
{% endfor %}
{% endif %}
{% set index = _.index %}
{% if "navigation.tabs" in features %}
{% if level == 1 and nav_item.active %}
{% set class = class ~ " md-nav__item--section" %}
{% set is_section = true %}
{% endif %}
{% if "navigation.sections" in features %}
{% if level == 2 and parent.active %}
{% set class = class ~ " md-nav__item--section" %}
{% set is_section = true %}
{% endif %}
{% endif %}
{% elif "navigation.sections" in features %}
{% if level == 1 %}
{% set class = class ~ " md-nav__item--section" %}
{% set is_section = true %}
{% endif %}
{% endif %}
{% if "navigation.prune" in features %}
{% if not is_section and not nav_item.active %}
{% set class = class ~ " md-nav__item--pruned" %}
{% set is_pruned = true %}
{% endif %}
{% endif %}
<li class="{{ class }} md-nav__item--nested">
{% if not is_pruned %}
{% set checked = "checked" if nav_item.active %}
{% if "navigation.expand" in features and not checked %}
{% set indeterminate = "md-toggle--indeterminate" %}
{% endif %}
<input class="md-nav__toggle md-toggle {{ indeterminate }}" type="checkbox" id="{{ path }}" {{ checked }}>
{% if not index %}
{% set tabindex = "0" if not is_section %}
<label class="md-nav__link" for="{{ path }}" id="{{ path }}_label" tabindex="{{ tabindex }}">
{{ render_content(nav_item) }}
<span class="md-nav__icon md-icon"></span>
</label>
{% else %}
{% set class = "md-nav__link--active" if index == page %}
<div class="md-nav__link md-nav__container">
<a href="{{ index.url | url }}" class="md-nav__link {{ class }}">
{{ render_content(index, nav_item) }}
</a>
{% if nav_item.children | length > 1 %}
{% set tabindex = "0" if not is_section %}
<label class="md-nav__link {{ class }}" for="{{ path }}" id="{{ path }}_label" tabindex="{{ tabindex }}">
<span class="md-nav__icon md-icon"></span>
</label>
{% endif %}
</div>
{% endif %}
<nav class="md-nav" data-md-level="{{ level }}" aria-labelledby="{{ path }}_label" aria-expanded="{{ nav_item.active | tojson }}">
<label class="md-nav__title" for="{{ path }}" {% if index and nav_item.children | length <= 1 %}id="{{ path }}_label"{% endif %}>
<span class="md-nav__icon md-icon"></span>
{{ render_title(nav_item) }}
</label>
<ul class="md-nav__list" data-md-scrollfix>
{% for item in nav_item.children %}
{% if not index or item != index %}
{{ render(item, path ~ "_" ~ loop.index, level + 1, nav_item) }}
{% endif %}
{% endfor %}
</ul>
</nav>
{% else %}
{{ render_pruned(nav_item) }}
{% endif %}
</li>
{% elif nav_item == page %}
<li class="{{ class }}">
{% set toc = page.toc %}
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
{% set first = toc | first %}
{% if first and first.level == 1 %}
{% set toc = first.children %}
{% endif %}
{% if toc %}
<label class="md-nav__link md-nav__link--active" for="__toc">
{{ render_content(nav_item) }}
<span class="md-nav__icon md-icon"></span>
</label>
{% endif %}
<a href="{{ nav_item.url | url }}" class="md-nav__link md-nav__link--active">
{{ render_content(nav_item) }}
</a>
{% if toc %}
{% include "partials/toc.html" %}
{% endif %}
</li>
{% else %}
<li class="{{ class }}">
<a href="{{ nav_item.url | url }}" class="md-nav__link">
{{ render_content(nav_item) }}
</a>
</li>
{% endif %}
{% endmacro %}
2 changes: 1 addition & 1 deletion overrides/partials/nav_support_request.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<span class="md-content__inner md-typeset">
<a href="mailto:support@nesi.org.nz?subject=SupportRequest" target="_blank" title="Click Here to rasie a support ticket" class="md-button-support md-button md-button--primary">
<a href="mailto:support@nesi.org.nz?subject=SupportRequest" target="_blank" title="Raise a support ticket" class="md-button-support md-button md-button--primary">
<span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19.79,15.41C20.74,13.24 20.74,10.75 19.79,8.59L17.05,9.83C17.65,11.21 17.65,12.78 17.06,14.17L19.79,15.41M15.42,4.21C13.25,3.26 10.76,3.26 8.59,4.21L9.83,6.94C11.22,6.35 12.79,6.35 14.18,6.95L15.42,4.21M4.21,8.58C3.26,10.76 3.26,13.24 4.21,15.42L6.95,14.17C6.35,12.79 6.35,11.21 6.95,9.82L4.21,8.58M8.59,19.79C10.76,20.74 13.25,20.74 15.42,19.78L14.18,17.05C12.8,17.65 11.22,17.65 9.84,17.06L8.59,19.79M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M12,8A4,4 0 0,0 8,12A4,4 0 0,0 12,16A4,4 0 0,0 16,12A4,4 0 0,0 12,8Z" /></svg></span>
Contact Support
</a>
Expand Down
29 changes: 29 additions & 0 deletions overrides/partials/palette.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<form class="md-header__option" data-md-component="palette">
{% set palettes = config.theme.palette or [] %}
{% for palette in palettes %}
{% set i = loop.index0 %}
{% set next_id = "__palette_" ~ ((i + 1) % palettes|length) %}
<input class="md-option"
data-md-color-media="{{ palette.media or "" }}"
data-md-color-scheme="{{ palette.scheme or "" }}"
data-md-color-primary="{{ palette.primary or "" }}"
data-md-color-accent="{{ palette.accent or "" }}"
aria-label="{{ palette.toggle.name if palette.toggle and palette.toggle.name else "Switch color mode" }}"
type="radio"
name="__palette"
id="__palette_{{ i }}">
<label
class="md-header__button md-icon"
title="{{ palette.toggle.name if palette.toggle and palette.toggle.name else "Switch color mode" }}"
aria-label="{{ palette.toggle.name if palette.toggle and palette.toggle.name else "Switch color mode" }}"
for="{{ next_id }}"
hidden>
{% if palette.toggle and palette.toggle.icon %}
{% include ".icons/" ~ palette.toggle.icon ~ ".svg" %}
{% else %}
{% set icon = "material/lightbulb" if palette.scheme != "slate" else "material/lightbulb-outline" %}
{% include ".icons/" ~ icon ~ ".svg" %}
{% endif %}
</label>
{% endfor %}
</form>
Loading