feat: AI/KI disclosure footer — shared/ai-disclosure.js + all 54 sites

Self-injecting script following impressum.js pattern:
- data-tone attribute: playful | serious | minimal | none
- Reads document.documentElement.lang for KI (de) vs AI (en)
- MutationObserver on lang attr for i18n toggle compat
- All tones link to msbls.de/ki
- Injected into all 54 custom sites with data-tone="playful"
- Template infra: base.html includes script, render.sh reads disclosure.tone
- disclosure.tone added to 3 example site.yaml files

Implements m/onepager#2
This commit is contained in:
m
2026-04-01 13:26:04 +02:00
parent 5c92a7b021
commit 84b28d64f5
60 changed files with 138 additions and 0 deletions

72
shared/ai-disclosure.js Normal file
View File

@@ -0,0 +1,72 @@
/**
* KI/AI disclosure for onepager sites.
*
* Include: <script src="/shared/ai-disclosure.js" data-tone="playful"></script>
*
* Configuration via data attributes on the script tag:
* data-tone="playful" — Lighthearted note with humor
* data-tone="serious" — Straightforward disclosure
* data-tone="minimal" — Single compact label
* data-tone="none" — No disclosure (script does nothing)
*
* Language is read from document.documentElement.lang:
* "de" -> KI terminology, "en" -> AI terminology.
* All tones link to msbls.de/ki.
*/
(function () {
var script = document.currentScript;
var tone = (script && script.getAttribute('data-tone')) || 'minimal';
if (tone === 'none') return;
var lang = (document.documentElement.lang || 'de').slice(0, 2).toLowerCase();
var isEn = lang === 'en';
var texts = {
minimal: isEn ? 'AI-assisted' : 'KI-unterst\u00FCtzt',
serious: isEn
? 'This site was created with AI assistance.'
: 'Diese Seite wurde mit Unterst\u00FCtzung von KI erstellt.',
playful: isEn
? 'Made with AI (no AIs were harmed)'
: 'Mit KI gemacht (keine KI wurde verletzt)',
};
var text = texts[tone] || texts.minimal;
var el = document.createElement('div');
el.className = 'onepager-ai-disclosure';
el.innerHTML = '<a href="https://msbls.de/ki" target="_blank" rel="noopener">' + text + '</a>';
el.style.cssText = 'text-align:center;font-size:0.65rem;opacity:0.4;padding:6px 0;margin-top:2px;';
var a = el.querySelector('a');
if (a) {
a.style.color = 'inherit';
a.style.textDecoration = 'none';
}
// i18n: update text when language changes
var observer = new MutationObserver(function () {
var newLang = (document.documentElement.lang || 'de').slice(0, 2).toLowerCase();
var newIsEn = newLang === 'en';
var newTexts = {
minimal: newIsEn ? 'AI-assisted' : 'KI-unterst\u00FCtzt',
serious: newIsEn
? 'This site was created with AI assistance.'
: 'Diese Seite wurde mit Unterst\u00FCtzung von KI erstellt.',
playful: newIsEn
? 'Made with AI (no AIs were harmed)'
: 'Mit KI gemacht (keine KI wurde verletzt)',
};
var link = el.querySelector('a');
if (link) link.textContent = newTexts[tone] || newTexts.minimal;
});
observer.observe(document.documentElement, { attributes: true, attributeFilter: ['lang'] });
var footer = document.querySelector('footer .container, footer');
if (footer) {
footer.appendChild(el);
} else {
document.body.appendChild(el);
}
})();