Merge branch 'main' into 40c3
This commit is contained in:
commit
925737eff5
16 changed files with 206 additions and 28 deletions
|
|
@ -78,3 +78,26 @@ jobs:
|
||||||
with:
|
with:
|
||||||
name: website-build
|
name: website-build
|
||||||
path: public/
|
path: public/
|
||||||
|
|
||||||
|
# Separate from the build, so that accessibility findings show up on PRs without blocking deploys.
|
||||||
|
accessibility:
|
||||||
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: docker.io/hugomods/hugo:0.165.0
|
||||||
|
steps:
|
||||||
|
- name: Install packages
|
||||||
|
run: |
|
||||||
|
apk update
|
||||||
|
# For CI actions and pa11y.
|
||||||
|
apk add nodejs-current npm
|
||||||
|
# For website build.
|
||||||
|
apk add tzdata git
|
||||||
|
# For pa11y: a browser, fonts for it, and a web server for the built site.
|
||||||
|
apk add chromium font-dejavu python3
|
||||||
|
|
||||||
|
- uses: actions/checkout@v7
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
|
- name: Check accessibility with pa11y
|
||||||
|
run: ./scripts/pa11y.sh
|
||||||
|
|
|
||||||
10
.pa11yci.json
Normal file
10
.pa11yci.json
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"defaults": {
|
||||||
|
"standard": "WCAG2AA",
|
||||||
|
"runners": ["axe", "htmlcs"],
|
||||||
|
"timeout": 60000,
|
||||||
|
"chromeLaunchConfig": {
|
||||||
|
"args": ["--no-sandbox", "--disable-dev-shm-usage"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
16
README.md
16
README.md
|
|
@ -149,3 +149,19 @@ The uMap data has been converted into this format in [data/schedule/39c3.yaml](d
|
||||||
- The whole map: the "Download" option in uMap's share panel exports all layers as one GeoJSON file.
|
- The whole map: the "Download" option in uMap's share panel exports all layers as one GeoJSON file.
|
||||||
|
|
||||||
In the GeoJSON, `coordinates` are already in `[lon, lat]` order, the colour and icon are in each feature's `properties._umap_options`, and the directions are in `properties.description`.
|
In the GeoJSON, `coordinates` are already in `[lon, lat]` order, the colour and icon are in each feature's `properties._umap_options`, and the directions are in `properties.description`.
|
||||||
|
|
||||||
|
## Accessibility check
|
||||||
|
|
||||||
|
CI runs [pa11y-ci](https://github.com/pa11y/pa11y-ci) with the axe and HTML_CodeSniffer rules for WCAG 2 AA on every push and pull request, in its own job (`accessibility`), so findings show up without blocking the deploy. To run the same check locally (needs Node.js, Python 3 and Chrome or Chromium):
|
||||||
|
|
||||||
|
```shell
|
||||||
|
./scripts/pa11y.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
The script builds the site, serves it on `localhost:8080` and checks every page in the sitemaps, except the past events and the individual news posts, which are kept as they were. The list of skipped sections is `EXCLUDE` in [scripts/pa11y.sh](scripts/pa11y.sh); the rules are in [.pa11yci.json](.pa11yci.json). pa11y only checks the light colour scheme.
|
||||||
|
|
||||||
|
Some things to keep in mind when writing pages:
|
||||||
|
|
||||||
|
- Give every image an alt text that says what it shows. The image title is the photo credit (``); it is shown below the image.
|
||||||
|
- Headings in a page start at `##`; `#` is the page title.
|
||||||
|
- Don't put information only into images, like directions on a map; write it out as text as well.
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
@import './_tour-map.css';
|
@import './_tour-map.css';
|
||||||
|
|
||||||
.header__intro_headline {
|
.header__intro_headline {
|
||||||
|
margin: 0;
|
||||||
font: bold var(--fs-xxl) "Arial";
|
font: bold var(--fs-xxl) "Arial";
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
@ -33,6 +34,7 @@ th, td {
|
||||||
--color-header-bg: #242424;
|
--color-header-bg: #242424;
|
||||||
--color-text: #faf5f5;
|
--color-text: #faf5f5;
|
||||||
--color-link: #66f2ff;
|
--color-link: #66f2ff;
|
||||||
|
--color-link-visited: #66f2ff;
|
||||||
--color-footer-bg: #242424;
|
--color-footer-bg: #242424;
|
||||||
--color-border: #faf5f5;
|
--color-border: #faf5f5;
|
||||||
--color-button: #141414;
|
--color-button: #141414;
|
||||||
|
|
@ -50,7 +52,9 @@ th, td {
|
||||||
.main-menu a:active {
|
.main-menu a:active {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
a {
|
/* Links in text keep their underline: the link colour alone is too close to the text colour. */
|
||||||
|
nav a,
|
||||||
|
.header a {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -62,3 +66,43 @@ h2 a {
|
||||||
.title-post-date {
|
.title-post-date {
|
||||||
margin-left: 0em;
|
margin-left: 0em;
|
||||||
}
|
}
|
||||||
|
/* Visible when focused with the keyboard; the visually-hidden class hides it otherwise. */
|
||||||
|
.skip-link:focus {
|
||||||
|
position: absolute;
|
||||||
|
inset-block-start: 0.5rem;
|
||||||
|
inset-inline-start: 0.5rem;
|
||||||
|
z-index: 100;
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
background: var(--color-button);
|
||||||
|
color: var(--color-button-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
#main-content:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Content images with their credit, see layouts/_markup/render-image.html. */
|
||||||
|
.content-image {
|
||||||
|
margin: 1rem 0;
|
||||||
|
|
||||||
|
img {
|
||||||
|
display: block;
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
span.content-image {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: top;
|
||||||
|
max-width: 100%;
|
||||||
|
margin: 0 0.5rem 0.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-image__credit {
|
||||||
|
display: block;
|
||||||
|
margin-block-start: 0.25rem;
|
||||||
|
font-family: var(--ff-alt);
|
||||||
|
font-size: var(--fs-xs);
|
||||||
|
color: var(--color-text-meta);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -68,16 +68,16 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lined up with the time on the cards. */
|
/* Lined up with the time on the cards, but in normal weight to stay in the background.
|
||||||
|
No transparency: it has to keep text contrast. */
|
||||||
.schedule__hour-label {
|
.schedule__hour-label {
|
||||||
display: block;
|
display: block;
|
||||||
padding: calc(0.5rem + 0.25rem) 0.75rem 0.5rem calc(0.75rem + 3px);
|
padding: calc(0.5rem + 0.25rem) 0.75rem 0.5rem calc(0.75rem + 3px);
|
||||||
font-family: var(--ff-alt);
|
font-family: var(--ff-alt);
|
||||||
font-size: var(--fs-s);
|
font-size: var(--fs-s);
|
||||||
font-weight: bold;
|
font-weight: normal;
|
||||||
font-variant-numeric: tabular-nums;
|
font-variant-numeric: tabular-nums;
|
||||||
color: var(--color-text-meta);
|
color: var(--color-text-meta);
|
||||||
opacity: 0.45;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.schedule__day-title {
|
.schedule__day-title {
|
||||||
|
|
@ -177,6 +177,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@container (width < 48rem) {
|
@container (width < 48rem) {
|
||||||
|
/* Keeps a focused card from scrolling under the sticky day picker. */
|
||||||
|
.schedule__title {
|
||||||
|
scroll-margin-block-start: 6rem;
|
||||||
|
}
|
||||||
|
|
||||||
.schedule__picker:not([hidden]) {
|
.schedule__picker:not([hidden]) {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
inset-block-start: 0;
|
inset-block-start: 0;
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,6 @@ cascade:
|
||||||
intro: Wir von Hamburg Hackertours zeigen euch die Stadt!
|
intro: Wir von Hamburg Hackertours zeigen euch die Stadt!
|
||||||
---
|
---
|
||||||
|
|
||||||
## Willkommen bei Hamburg Hackertours!
|
|
||||||
|
|
||||||
Für den [40C3](https://events.ccc.de/category/40c3/) haben wir interessante Orte in und um Hamburg gefunden, an denen ihr für ein paar Stunden in andere Welten eintauchen und spannende Dinge erleben könnt. [Wie das funktioniert, erklären wir euch hier in unseren FAQ]({{< relref "faq/_index" >}})!
|
Für den [40C3](https://events.ccc.de/category/40c3/) haben wir interessante Orte in und um Hamburg gefunden, an denen ihr für ein paar Stunden in andere Welten eintauchen und spannende Dinge erleben könnt. [Wie das funktioniert, erklären wir euch hier in unseren FAQ]({{< relref "faq/_index" >}})!
|
||||||
|
|
||||||
HackerTours ist auch auf **[Mastodon](https://chaos.social/@hackertours)**!
|
HackerTours ist auch auf **[Mastodon](https://chaos.social/@hackertours)**!
|
||||||
|
|
@ -31,4 +29,4 @@ Hackertours-Desk: DECT 8687 "TOUR", +49 40 573 0830 8687
|
||||||
|
|
||||||
Frühere Veranstaltungen: [37C3](37c3) / [38C3](38c3) / [EH22](eh22) / [39C3](39c3)
|
Frühere Veranstaltungen: [37C3](37c3) / [38C3](38c3) / [EH22](eh22) / [39C3](39c3)
|
||||||
|
|
||||||
# News
|
## News
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,6 @@ cascade:
|
||||||
intro: Let Hamburg Hackertours show you around the city!
|
intro: Let Hamburg Hackertours show you around the city!
|
||||||
---
|
---
|
||||||
|
|
||||||
## Welcome to Hamburg Hackertours!
|
|
||||||
|
|
||||||
For [40C3](https://events.ccc.de/category/40c3/) we have found interesting places in and around Hamburg where you can delve into other worlds and experience fascinating things for a few hours. [We are going to explain how this works here in our FAQ article]({{< relref "faq/_index" >}})!
|
For [40C3](https://events.ccc.de/category/40c3/) we have found interesting places in and around Hamburg where you can delve into other worlds and experience fascinating things for a few hours. [We are going to explain how this works here in our FAQ article]({{< relref "faq/_index" >}})!
|
||||||
|
|
||||||
HackerTours is also on **[Mastodon](https://chaos.social/@hackertours)**!
|
HackerTours is also on **[Mastodon](https://chaos.social/@hackertours)**!
|
||||||
|
|
@ -31,5 +29,5 @@ Hackertours Desk: DECT 8687 "TOUR", +49 40 573 0830 8687
|
||||||
|
|
||||||
Previous events: [37C3](37c3) / [38C3](38c3) / [EH22](eh22) / [39C3](39c3)
|
Previous events: [37C3](37c3) / [38C3](38c3) / [EH22](eh22) / [39C3](39c3)
|
||||||
|
|
||||||
# News
|
## News
|
||||||
|
|
||||||
|
|
@ -44,3 +44,9 @@ languages:
|
||||||
pagination:
|
pagination:
|
||||||
pagerSize: 25
|
pagerSize: 25
|
||||||
title: "Hamburg Hackertours"
|
title: "Hamburg Hackertours"
|
||||||
|
|
||||||
|
markup:
|
||||||
|
goldmark:
|
||||||
|
parser:
|
||||||
|
# Lets the image render hook tell images on their own line (.IsBlock) from inline ones.
|
||||||
|
wrapStandAloneImageWithinParagraph: false
|
||||||
|
|
|
||||||
|
|
@ -2,3 +2,6 @@ schedule_day: "Tag {{ .Day }}"
|
||||||
schedule_pick_day: "Tag auswählen"
|
schedule_pick_day: "Tag auswählen"
|
||||||
tour_map_label: "Karte der Tourorte"
|
tour_map_label: "Karte der Tourorte"
|
||||||
tour_map_osm: "auf OpenStreetMap"
|
tour_map_osm: "auf OpenStreetMap"
|
||||||
|
skip_to_content: "Zum Inhalt springen"
|
||||||
|
logo_alt: "Hamburg Hackertours – Startseite"
|
||||||
|
map_39c3_title: "Karte der 39C3-Touren mit Wegen vom CCH (uMap)"
|
||||||
|
|
|
||||||
|
|
@ -2,3 +2,6 @@ schedule_day: "Day {{ .Day }}"
|
||||||
schedule_pick_day: "Choose a day"
|
schedule_pick_day: "Choose a day"
|
||||||
tour_map_label: "Map of the tour locations"
|
tour_map_label: "Map of the tour locations"
|
||||||
tour_map_osm: "on OpenStreetMap"
|
tour_map_osm: "on OpenStreetMap"
|
||||||
|
skip_to_content: "Skip to content"
|
||||||
|
logo_alt: "Hamburg Hackertours – home page"
|
||||||
|
map_39c3_title: "Map of the 39C3 tours with routes from the CCH (uMap)"
|
||||||
|
|
|
||||||
30
layouts/_markup/render-image.html
Normal file
30
layouts/_markup/render-image.html
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
{{- /*
|
||||||
|
Content images. The Markdown title ("") is the photo credit; it is shown
|
||||||
|
as a caption instead of a tooltip, so that it is available on touch devices and to screen readers.
|
||||||
|
An image on its own line becomes a figure; images sharing a paragraph get an inline credit.
|
||||||
|
*/ -}}
|
||||||
|
{{- $src := .Destination -}}
|
||||||
|
{{- $width := 0 -}}
|
||||||
|
{{- $height := 0 -}}
|
||||||
|
{{- with or (.PageInner.Resources.Get (strings.TrimPrefix "./" .Destination)) (resources.Get .Destination) -}}
|
||||||
|
{{- $src = .RelPermalink -}}
|
||||||
|
{{- if and (eq .ResourceType "image") (ne .MediaType.SubType "svg") -}}
|
||||||
|
{{- $width = .Width -}}
|
||||||
|
{{- $height = .Height -}}
|
||||||
|
{{- end -}}
|
||||||
|
{{- end -}}
|
||||||
|
{{- /* A title that only repeats the alt text is not a credit. */ -}}
|
||||||
|
{{- $credit := cond (eq .Title .PlainText) "" .Title -}}
|
||||||
|
{{- $img := printf `<img src="%s" alt="%s"%s>` (htmlEscape $src) (htmlEscape .PlainText) (cond (gt $width 0) (printf ` width="%d" height="%d"` $width $height) "") -}}
|
||||||
|
{{- if .IsBlock -}}
|
||||||
|
<figure class="content-image">
|
||||||
|
{{ $img | safeHTML }}
|
||||||
|
{{- with $credit }}
|
||||||
|
<figcaption class="content-image__credit">{{ . }}</figcaption>
|
||||||
|
{{- end }}
|
||||||
|
</figure>
|
||||||
|
{{- else if $credit -}}
|
||||||
|
<span class="content-image">{{ $img | safeHTML }}<span class="content-image__credit">{{ $credit }}</span></span>
|
||||||
|
{{- else -}}
|
||||||
|
{{ $img | safeHTML }}
|
||||||
|
{{- end -}}
|
||||||
|
|
@ -1,21 +1,25 @@
|
||||||
{{- /* Language badge for a tour. Params: code ("de", "en" or "deen"), class (optional; without it the badge is styled as an inline superscript). */ -}}
|
{{- /* Language badge for a tour. Params: code ("de", "en" or "deen"), class (optional; without it the badge is styled as an inline superscript).
|
||||||
|
The visible label ("DE/EN") is hidden from screen readers, which read a short text instead; the full sentence is a tooltip. */ -}}
|
||||||
{{- $code := .code | lower -}}
|
{{- $code := .code | lower -}}
|
||||||
{{- $validCodes := slice "de" "en" "deen" -}}
|
{{- $validCodes := slice "de" "en" "deen" -}}
|
||||||
{{- if not (in $validCodes $code) -}}
|
{{- if not (in $validCodes $code) -}}
|
||||||
<span style="color: red; font-weight: bold;">Warning: Invalid or missing language code '{{ $code }}'. Use 'de', 'en', or 'deen'.</span>
|
<span style="color: red; font-weight: bold;">Warning: Invalid or missing language code '{{ $code }}'. Use 'de', 'en', or 'deen'.</span>
|
||||||
{{- else -}}
|
{{- else -}}
|
||||||
{{- $label := cond (eq $code "de") "DE" (cond (eq $code "en") "EN" (cond (eq $code "deen") "DE/EN" "")) -}}
|
{{- $de := eq site.Language.Name "de" -}}
|
||||||
|
{{- $label := cond (eq $code "de") "DE" (cond (eq $code "en") "EN" "DE/EN") -}}
|
||||||
{{- $title := "" -}}
|
{{- $title := "" -}}
|
||||||
|
{{- $spoken := "" -}}
|
||||||
{{- if eq $code "deen" -}}
|
{{- if eq $code "deen" -}}
|
||||||
{{- $title = cond (eq site.Language.Name "de") "Diese Tour wird zweisprachig stattfinden (Deutsch und Englisch)" "This tour will be bilingual (German and English)" -}}
|
{{- $title = cond $de "Diese Tour wird zweisprachig stattfinden (Deutsch und Englisch)" "This tour will be bilingual (German and English)" -}}
|
||||||
|
{{- $spoken = cond $de "Sprache: Deutsch und Englisch" "Language: German and English" -}}
|
||||||
{{- else if eq $code "de" -}}
|
{{- else if eq $code "de" -}}
|
||||||
{{- $title = cond (eq site.Language.Name "de") "Diese Tour wird auf Deutsch stattfinden" "This tour will be held in German" -}}
|
{{- $title = cond $de "Diese Tour wird auf Deutsch stattfinden" "This tour will be held in German" -}}
|
||||||
|
{{- $spoken = cond $de "Sprache: Deutsch" "Language: German" -}}
|
||||||
{{- else if eq $code "en" -}}
|
{{- else if eq $code "en" -}}
|
||||||
{{- $title = cond (eq site.Language.Name "de") "Diese Tour wird auf Englisch stattfinden" "This tour will be held in English" -}}
|
{{- $title = cond $de "Diese Tour wird auf Englisch stattfinden" "This tour will be held in English" -}}
|
||||||
{{- end -}}
|
{{- $spoken = cond $de "Sprache: Englisch" "Language: English" -}}
|
||||||
{{- with .class -}}
|
|
||||||
<abbr class="{{ . }}" title="{{ $title }}">{{ $label }}</abbr>
|
|
||||||
{{- else -}}
|
|
||||||
<abbr style="font-size: .65em; vertical-align: super;" title="{{ $title }}">{{ $label }}</abbr>
|
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
{{- $style := "font-size: .65em; vertical-align: super;" -}}
|
||||||
|
{{- with .class }}{{ $style = "" }}{{ end -}}
|
||||||
|
<span{{ with .class }} class="{{ . }}"{{ end }}{{ with $style }} style="{{ . | safeCSS }}"{{ end }} title="{{ $title }}"><span aria-hidden="true">{{ $label }}</span><span class="visually-hidden">{{ $spoken }}</span></span>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
<iframe style="width: 100%; height: 300px; border: 0;" allowfullscreen allow="geolocation" src="//umap.openstreetmap.fr/en/map/39c3-hackertours_1329184?scaleControl=true&miniMap=false&scrollWheelZoom=true&zoomControl=true&editMode=disabled&moreControl=true&searchControl=false&tilelayersControl=false&embedControl=false&datalayersControl=false&onLoadPanel=none&captionBar=false&captionMenus=true&datalayers=bdd7ff4a-820c-4d08-acd6-a4e1f457b09a%2C82c00520-3aac-454b-96c1-f84d76734b59%2C0b4c18d6-f604-40b0-a322-05b69635ba5c%2Cde42bd8b-d6e8-4bc0-9a2d-2b0168c693c1%2C3bb4795a-1e46-4755-b729-17aeb462498c%2C3a5870ba-4539-4f58-adc9-d0b86b82b4f1%2Cf9d4edf5-c7ac-4e8a-bb39-816312075660%2C3e12b58e-cf69-458d-86ff-6c3d7df79365%2C706815ab-ff61-4840-bc05-cae55242648f%2C6ebae518-b9c0-4900-8f52-085690afa3e7%2C8324f966-450f-4dcf-bec7-e893a3716b42&captionControl=false&locateControl=false&measureControl=false&printControl=null&homeControl=false"></iframe>
|
<iframe title="{{ i18n "map_39c3_title" }}" style="width: 100%; height: 300px; border: 0;" allowfullscreen allow="geolocation" src="//umap.openstreetmap.fr/en/map/39c3-hackertours_1329184?scaleControl=true&miniMap=false&scrollWheelZoom=true&zoomControl=true&editMode=disabled&moreControl=true&searchControl=false&tilelayersControl=false&embedControl=false&datalayersControl=false&onLoadPanel=none&captionBar=false&captionMenus=true&datalayers=bdd7ff4a-820c-4d08-acd6-a4e1f457b09a%2C82c00520-3aac-454b-96c1-f84d76734b59%2C0b4c18d6-f604-40b0-a322-05b69635ba5c%2Cde42bd8b-d6e8-4bc0-9a2d-2b0168c693c1%2C3bb4795a-1e46-4755-b729-17aeb462498c%2C3a5870ba-4539-4f58-adc9-d0b86b82b4f1%2Cf9d4edf5-c7ac-4e8a-bb39-816312075660%2C3e12b58e-cf69-458d-86ff-6c3d7df79365%2C706815ab-ff61-4840-bc05-cae55242648f%2C6ebae518-b9c0-4900-8f52-085690afa3e7%2C8324f966-450f-4dcf-bec7-e893a3716b42&captionControl=false&locateControl=false&measureControl=false&printControl=null&homeControl=false"></iframe>
|
||||||
|
|
@ -18,15 +18,16 @@
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="{{ if .IsPage }}single-page{{ else }}list-page{{ end }}{{ if .IsHome }} front{{ end }}{{ with .Section }} section-page--{{ . | urlize }}{{ end }}{{ with $.Param "bodyclass" }} {{ . }}{{ end }}">
|
<body class="{{ if .IsPage }}single-page{{ else }}list-page{{ end }}{{ if .IsHome }} front{{ end }}{{ with .Section }} section-page--{{ . | urlize }}{{ end }}{{ with $.Param "bodyclass" }} {{ . }}{{ end }}">
|
||||||
|
<a class="skip-link visually-hidden" href="#main-content">{{ i18n "skip_to_content" }}</a>
|
||||||
<div class="page layout__page{{ if $.Param "sidebar" }} layout__sidebar-second{{ end }}">
|
<div class="page layout__page{{ if $.Param "sidebar" }} layout__sidebar-second{{ end }}">
|
||||||
<header class="header layout__header">
|
<header class="header layout__header">
|
||||||
{{ if $.Param "logo" | default true -}}
|
{{ if $.Param "logo" | default true -}}
|
||||||
<a href="{{ site.Home.RelPermalink }}" title="Home" rel="home" class="header__logo">
|
<a href="{{ site.Home.RelPermalink }}" rel="home" class="header__logo">
|
||||||
<img src="{{ with $.Param "logopath" }}{{ . | relURL }}{{ else }}{{ "images/logo.png" | relURL }}{{ end }}"{{ with $.Param "logowidth" }} width="{{ . }}"{{ end }}{{ with $.Param "logoheight" }} height="{{ . }}"{{ end }} alt="Home" class="header__logo-image">
|
<img src="{{ with $.Param "logopath" }}{{ . | relURL }}{{ else }}{{ "images/logo.png" | relURL }}{{ end }}"{{ with $.Param "logowidth" }} width="{{ . }}"{{ end }}{{ with $.Param "logoheight" }} height="{{ . }}"{{ end }} alt="{{ i18n "logo_alt" }}" class="header__logo-image">
|
||||||
</a>
|
</a>
|
||||||
{{ end -}}
|
{{ end -}}
|
||||||
<div class="header__intro">
|
<div class="header__intro">
|
||||||
<div class="header__intro_headline"><a href="{{ site.Home.RelPermalink }}" title="Home" class="header__site-link" rel="home"><span>{{ site.Title }}</span></a></div>
|
<div class="header__intro_headline"><a href="{{ site.Home.RelPermalink }}" class="header__site-link" rel="home"><span>{{ site.Title }}</span></a></div>
|
||||||
<div class="header__intro_text">{{ .Param "intro" }}</div>
|
<div class="header__intro_text">{{ .Param "intro" }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="region header__region">
|
<div class="region header__region">
|
||||||
|
|
@ -38,6 +39,7 @@
|
||||||
{{ if not ($.Param "menuinheader") }}{{ partial "menu.html" . }}{{ end -}}
|
{{ if not ($.Param "menuinheader") }}{{ partial "menu.html" . }}{{ end -}}
|
||||||
{{ if $.Param "mobilemenu" }}{{ partial "mobilemenu.html" . }}{{ end -}}
|
{{ if $.Param "mobilemenu" }}{{ partial "mobilemenu.html" . }}{{ end -}}
|
||||||
|
|
||||||
|
<div id="main-content" tabindex="-1"></div>
|
||||||
{{ block "main" . }}{{ end }}
|
{{ block "main" . }}{{ end }}
|
||||||
|
|
||||||
{{ if $.Param "sidebar" }}{{ partial "sidebar.html" . }}{{ end -}}
|
{{ if $.Param "sidebar" }}{{ partial "sidebar.html" . }}{{ end -}}
|
||||||
|
|
|
||||||
|
|
@ -18,15 +18,16 @@
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="{{ if .IsPage }}single-page{{ else }}list-page{{ end }}{{ if .IsHome }} front{{ end }}{{ with .Section }} section-page--{{ . | urlize }}{{ end }}{{ with $.Param "bodyclass" }} {{ . }}{{ end }}">
|
<body class="{{ if .IsPage }}single-page{{ else }}list-page{{ end }}{{ if .IsHome }} front{{ end }}{{ with .Section }} section-page--{{ . | urlize }}{{ end }}{{ with $.Param "bodyclass" }} {{ . }}{{ end }}">
|
||||||
|
<a class="skip-link visually-hidden" href="#main-content">{{ i18n "skip_to_content" }}</a>
|
||||||
<div class="page layout__page{{ if $.Param "sidebar" }} layout__sidebar-second{{ end }}">
|
<div class="page layout__page{{ if $.Param "sidebar" }} layout__sidebar-second{{ end }}">
|
||||||
<header class="header layout__header">
|
<header class="header layout__header">
|
||||||
{{ if $.Param "logo" | default true -}}
|
{{ if $.Param "logo" | default true -}}
|
||||||
<a href="{{ site.Home.RelPermalink }}" title="Home" rel="home" class="header__logo">
|
<a href="{{ site.Home.RelPermalink }}" rel="home" class="header__logo">
|
||||||
<img src="{{ with $.Param "logopath" }}{{ . | relURL }}{{ else }}{{ "images/logo.png" | relURL }}{{ end }}"{{ with $.Param "logowidth" }} width="{{ . }}"{{ end }}{{ with $.Param "logoheight" }} height="{{ . }}"{{ end }} alt="Home" class="header__logo-image">
|
<img src="{{ with $.Param "logopath" }}{{ . | relURL }}{{ else }}{{ "images/logo.png" | relURL }}{{ end }}"{{ with $.Param "logowidth" }} width="{{ . }}"{{ end }}{{ with $.Param "logoheight" }} height="{{ . }}"{{ end }} alt="{{ i18n "logo_alt" }}" class="header__logo-image">
|
||||||
</a>
|
</a>
|
||||||
{{ end -}}
|
{{ end -}}
|
||||||
<div class="header__intro">
|
<div class="header__intro">
|
||||||
<div class="header__intro_headline">{{ .Param "headline" }}</div>
|
<h1 class="header__intro_headline">{{ .Param "headline" }}</h1>
|
||||||
{{ if .Param "intro" }}
|
{{ if .Param "intro" }}
|
||||||
<div class="header__intro_text">{{ .Param "intro" }}</div>
|
<div class="header__intro_text">{{ .Param "intro" }}</div>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
@ -40,6 +41,7 @@
|
||||||
{{ if not ($.Param "menuinheader") }}{{ partial "menu.html" . }}{{ end -}}
|
{{ if not ($.Param "menuinheader") }}{{ partial "menu.html" . }}{{ end -}}
|
||||||
{{ if $.Param "mobilemenu" }}{{ partial "mobilemenu.html" . }}{{ end -}}
|
{{ if $.Param "mobilemenu" }}{{ partial "mobilemenu.html" . }}{{ end -}}
|
||||||
|
|
||||||
|
<div id="main-content" tabindex="-1"></div>
|
||||||
{{ block "main" . }}{{ end }}
|
{{ block "main" . }}{{ end }}
|
||||||
|
|
||||||
{{ if $.Param "sidebar" }}{{ partial "sidebar.html" . }}{{ end -}}
|
{{ if $.Param "sidebar" }}{{ partial "sidebar.html" . }}{{ end -}}
|
||||||
|
|
|
||||||
34
scripts/pa11y.sh
Executable file
34
scripts/pa11y.sh
Executable file
|
|
@ -0,0 +1,34 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# Accessibility check with pa11y-ci, used by CI and for local runs (see README.md).
|
||||||
|
# Builds the site into a temporary directory, serves it on localhost and checks every page
|
||||||
|
# in the sitemaps except the past events, which are kept as they were.
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
PA11Y_CI_VERSION=5.0.0
|
||||||
|
PORT=${PORT:-8080}
|
||||||
|
# Pages that are not checked: past events and the individual news posts.
|
||||||
|
EXCLUDE='^http://localhost:[0-9]+/[a-z]+/(37c3|38c3|39c3|eh22|posts/[^/]+)/'
|
||||||
|
|
||||||
|
# Use an installed Chrome/Chromium instead of letting Puppeteer download one.
|
||||||
|
if [ -z "${PUPPETEER_EXECUTABLE_PATH:-}" ]; then
|
||||||
|
for candidate in /usr/bin/chromium-browser /usr/bin/chromium "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"; do
|
||||||
|
if [ -x "$candidate" ]; then PUPPETEER_EXECUTABLE_PATH=$candidate; break; fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
export PUPPETEER_EXECUTABLE_PATH
|
||||||
|
export PUPPETEER_SKIP_DOWNLOAD=1
|
||||||
|
|
||||||
|
cd "$(dirname "$0")/.."
|
||||||
|
site=$(mktemp -d)
|
||||||
|
hugo --quiet --buildFuture --buildDrafts --baseURL "http://localhost:$PORT/" -d "$site"
|
||||||
|
python3 -m http.server "$PORT" --bind 127.0.0.1 -d "$site" >/dev/null 2>&1 &
|
||||||
|
server=$!
|
||||||
|
trap 'kill $server; rm -rf "$site"' EXIT
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
status=0
|
||||||
|
for lang in de en; do
|
||||||
|
npx --yes "pa11y-ci@$PA11Y_CI_VERSION" --config .pa11yci.json \
|
||||||
|
--sitemap "http://localhost:$PORT/$lang/sitemap.xml" --sitemap-exclude "$EXCLUDE" || status=1
|
||||||
|
done
|
||||||
|
exit $status
|
||||||
Loading…
Reference in a new issue