Files
dedinit.ru/layouts/partials/extend_footer.html
T
estorozhenko 1f58f8ccc7 fix: typewriter не замирает на первом слове (reduced-motion не останавливает печать) + переключатель темы прижат вправо
- extend_footer.html: убран ранний return при prefers-reduced-motion — печать идёт всегда, мигание гасится только через CSS (кейфрейм tw-blink уже отключается)
- typewriter.css: убрано двойное auto-поле (.logo margin-inline-end:auto конфликтовало с #menu margin-inline-start:auto при justify-content:space-between) — теперь только menu толкает вправо, солнышко встаёт сразу за меню
2026-09-20 07:42:02 +00:00

52 lines
2.1 KiB
HTML

{{- /* dedinit() typewriter: animated topics inside logo parens.
Pure JS + CSS, no Alpine. Progressive enhancement — no-JS keeps
the plain "dedinit()" logo. Words configurable via hugo.toml:
[params.typewriter] words = ["linux", "llm", "politics"] */ -}}
{{- $tw_words := site.Params.typewriter.words | default (slice "linux" "llm" "politics" "homelab" "nix") -}}
<script>
(() => {
const LOGO_SEL = 'header .logo a, .logo a';
const queue = [() => {
const a = document.querySelector(LOGO_SEL);
if (!a || a.dataset.twDone) return;
a.dataset.twDone = '1';
const text = a.textContent.trim();
const open = text.lastIndexOf('(');
const close = text.lastIndexOf(')');
if (open < 0 || close < open) return;
const words = {{ $tw_words | jsonify | safeJS }};
const box = document.createElement('span');
box.id = 'dedinit-typewriter';
box.className = 'tw';
box.textContent = '';
box.appendChild(Object.assign(document.createElement('span'), { className: 'tw-cursor' }));
// rebuild: <prefix>(<typewriter>)<suffix>
a.textContent = '';
a.appendChild(document.createTextNode(text.slice(0, open + 1)));
a.appendChild(box);
a.appendChild(document.createTextNode(text.slice(close)));
// reduced motion: blink is disabled via CSS; keep typing but no blink
const TYPE = 90, ERASE = 50, HOLD = 1400, GAP = 400;
let w = 0, i = 0, dir = 1;
box.querySelector('.tw-cursor').style.display = 'inline-block';
const tick = () => {
const word = words[w];
// keep cursor as the last child; typed text goes before it
box.replaceChildren(document.createTextNode(word.slice(0, i)), box.querySelector('.tw-cursor'));
let delay;
if (dir === 1) {
if (i < word.length) { i++; delay = TYPE; }
else { dir = -1; delay = HOLD; }
} else {
if (i > 0) { i--; delay = ERASE; }
else { dir = 1; w = (w + 1) % words.length; delay = GAP; }
}
setTimeout(tick, delay);
};
tick();
}];
if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', () => queue.shift()());
else queue.shift()();
})();
</script>