fix: resolve HTML hierarchy, accessibility and PDF link issues
Some checks failed
🚀 Build & Deploy / 🔍 Prepare (push) Successful in 7s
🚀 Build & Deploy / 🧪 QA (push) Successful in 1m19s
🚀 Build & Deploy / 🏗️ Build (push) Successful in 11m30s
🚀 Build & Deploy / 🚀 Deploy (push) Successful in 12s
🚀 Build & Deploy / 🧪 Post-Deploy Verification (push) Successful in 2m45s
🚀 Build & Deploy / 🔔 Notify (push) Successful in 2s
Nightly QA (Inlined) / 🏗️ Prepare & Install (push) Successful in 6m54s
Nightly QA (Inlined) / 🔍 Static Analysis (push) Failing after 1m29s
Nightly QA (Inlined) / 🧪 Maintenance & Links (push) Failing after 1m38s
Nightly QA (Inlined) / ♿ Accessibility (push) Successful in 2m0s
Nightly QA (Inlined) / 🎭 Lighthouse (push) Failing after 2m2s
Nightly QA (Inlined) / 🔔 Notify (push) Successful in 1s

- Fix heading level skip in ContactContent success state (H3 -> H2)
- Clean up deprecated iframe attributes in ContactContent
- Add aria-label to footer logo link for WCAG compliance
- Rename PDF assets to hyphenated filenames to fix link checks
- Update AGB page with new PDF link format
This commit is contained in:
2026-04-25 23:04:52 +02:00
parent 1315985ba2
commit 13cbc0291f
14 changed files with 48 additions and 30 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -13,22 +13,27 @@ export default function AVB() {
.filter((b) => b !== "");
// Extract title and stand more robustly
const title = rawBlocks.find(b => b.startsWith("# "))?.replace(/^#\s+/, "") || "Allgemeine Verkaufsbedingungen";
const stand = rawBlocks.find(b => b.toLowerCase().startsWith("stand:")) || "Stand: April 2026";
const title =
rawBlocks.find((b) => b.startsWith("# "))?.replace(/^#\s+/, "") ||
"Allgemeine Verkaufsbedingungen";
const stand =
rawBlocks.find((b) => b.toLowerCase().startsWith("stand:")) ||
"Stand: April 2026";
const sections: { title: string; content: string[] }[] = [];
let currentSection: { title: string; content: string[] } | null = null;
// Process sections, skipping title and stand blocks
rawBlocks.forEach((block) => {
if (block.startsWith("# ") || block.toLowerCase().startsWith("stand:")) return;
if (block.startsWith("# ") || block.toLowerCase().startsWith("stand:"))
return;
if (block.startsWith("##")) {
// New section header: e.g. "## 1. Geltungsbereich"
if (currentSection) sections.push(currentSection);
currentSection = {
title: block.replace(/^##\s+/, "").trim(),
content: []
currentSection = {
title: block.replace(/^##\s+/, "").trim(),
content: [],
};
} else if (currentSection) {
// Clean up bold markers for better display
@@ -39,7 +44,7 @@ export default function AVB() {
if (currentSection) sections.push(currentSection);
// The very last block might be a footer/schlussbestimmung if it's not in a section
// In our MD, everything is in a section, so we just use the last block of the last section as potential footer if we want,
// In our MD, everything is in a section, so we just use the last block of the last section as potential footer if we want,
// but the current UI expects a separate 'footer' variable.
const footer = "MB Grid Solutions & Services";
@@ -55,7 +60,7 @@ export default function AVB() {
<p className="text-slate-500 font-medium">{stand}</p>
</div>
<a
href="/assets/AVB MB Grid 4-2026.pdf"
href="/assets/avb-mb-grid-4-2026.pdf"
download
className="btn-primary !py-3 !px-6 flex items-center gap-2"
>

View File

@@ -162,13 +162,8 @@ export default function Contact() {
<div className="w-full h-[300px] rounded-[2.5rem] overflow-hidden border border-white/10 shadow-sm grayscale hover:grayscale-0 transition-all duration-700 relative group">
<div className="absolute inset-0 border-2 border-accent/0 group-hover:border-accent/20 transition-all duration-500 z-10 pointer-events-none rounded-[2.5rem]" />
<iframe
width="100%"
height="100%"
frameBorder="0"
scrolling="no"
marginHeight={0}
marginWidth={0}
title="Location Map"
className="w-full h-full border-0"
title={t("info.mapTitle") || "Location Map"}
src="https://www.openstreetmap.org/export/embed.html?bbox=9.445,48.815,9.465,48.825&layer=mapnik&marker=48.8198,9.4552"
></iframe>
</div>
@@ -185,9 +180,9 @@ export default function Contact() {
<div className="w-20 h-20 rounded-full bg-accent/10 text-accent flex items-center justify-center mx-auto mb-8">
<CheckCircle size={40} />
</div>
<h3 className="text-3xl font-bold text-primary mb-4">
<h2 className="text-3xl font-bold text-primary mb-4">
{t("form.successTitle")}
</h3>
</h2>
<p className="text-slate-600 text-lg mb-10">
{t("form.successMessage")}
</p>

View File

@@ -184,7 +184,11 @@ const Layout = ({ children }: { children: React.ReactNode }) => {
<div className="container-custom relative z-10">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-10 md:gap-12 mb-12 md:mb-16">
<div className="lg:col-span-2">
<Link href="/" className="inline-block mb-6 md:mb-8 group">
<Link
href="/"
className="inline-block mb-6 md:mb-8 group"
aria-label={t("nav.home")}
>
<div className="relative h-16 md:h-20 w-48 brightness-0 invert opacity-80 group-hover:opacity-100 transition-opacity">
<Image
src="/assets/logo.png"

View File

@@ -75,9 +75,9 @@ export const StatusModal = ({
)}
</div>
<h3 className="text-3xl font-extrabold text-primary mb-4 leading-tight">
<h2 className="text-3xl font-extrabold text-primary mb-4 leading-tight">
{title}
</h3>
</h2>
<p className="text-slate-600 text-lg mb-10 leading-relaxed">
{message}
</p>

View File

@@ -0,0 +1,14 @@
import * as cheerio from "cheerio";
import * as fs from "fs";
const file = process.argv[2];
const html = fs.readFileSync(file, "utf8");
const $ = cheerio.load(html);
$("a").each((i, el) => {
const text = $(el).text().trim();
const label = $(el).attr("aria-label");
if (!text && !label) {
console.log(`Empty anchor found: ${$(el).toString()}`);
}
});