diff --git a/packages/vitec/Classes/Seo/VitecMetaHandler.php b/packages/vitec/Classes/Seo/VitecMetaHandler.php index e6a0b7f..c083009 100644 --- a/packages/vitec/Classes/Seo/VitecMetaHandler.php +++ b/packages/vitec/Classes/Seo/VitecMetaHandler.php @@ -290,6 +290,31 @@ class VitecMetaHandler extends MetaHandler } } } + // Self-canonical pages need their own title/description, otherwise + // they count as duplicates of page 1 ("VITEC News and Articles" x3). + if ($keep !== []) { + $suffix = []; + if (isset($keep['category'])) { + $suffix[] = ucfirst(str_replace('-', ' ', $keep['category'])); + } + if (isset($keep['page'])) { + $suffix[] = 'Page ' . (int)$keep['page']; + } + $suffixText = ' – ' . implode(' – ', $suffix); + $currentTitle = trim((string)($content['seo']['title'] ?? '')); + if ($currentTitle !== '') { + $content['seo']['title'] = preg_match('/^(.*?)(\s*\|\s*VITEC)$/i', $currentTitle, $m) === 1 + ? $m[1] . $suffixText . $m[2] + : $currentTitle . $suffixText; + } + foreach ($content['seo']['meta'] as $index => $entry) { + if (in_array($entry['name'] ?? '', ['description', 'twitter:description'], true) + || ($entry['property'] ?? '') === 'og:description' + ) { + $content['seo']['meta'][$index]['content'] = rtrim((string)$entry['content'], '. ') . $suffixText . '.'; + } + } + } } return $content; diff --git a/packages/vitec/Resources/Public/Javascript/ssr-warm-progress.js b/packages/vitec/Resources/Public/Javascript/ssr-warm-progress.js deleted file mode 100644 index 6caaea1..0000000 --- a/packages/vitec/Resources/Public/Javascript/ssr-warm-progress.js +++ /dev/null @@ -1,88 +0,0 @@ -/** - * Live progress for the "Cache warming" row of the VITEC SSR module. - * Polls the vitec_ssr_health ajax route (GET /__health of the node): - * every 2 s while a warm run is active, every 15 s otherwise so runs - * started from the CLI or the context menu show up without a reload. - * Also refreshes the "Cache: N pages / M MB" line and disables the - * "Warm cache" button while a run is active. - */ -import AjaxRequest from '@typo3/core/ajax/ajax-request.js'; - -const cell = document.getElementById('ssr-warm-status'); -if (cell) { - const wrap = document.getElementById('ssr-warm-progress'); - const bar = document.getElementById('ssr-warm-bar'); - const text = document.getElementById('ssr-warm-text'); - const cacheLine = document.getElementById('ssr-cache-line'); - const warmButton = document.getElementById('ssr-warm-button'); - let timer = null; - - const num = (v) => (typeof v === 'number' ? v : 0); - - const render = (h) => { - const w = h.warming || {}; - const queued = num(w.queued); - const handled = num(w.done) + num(w.skipped) + num(w.failed); - const pct = queued > 0 ? Math.min(100, Math.round((handled / queued) * 100)) : 0; - const failed = num(w.failed) - ? '' + num(w.failed) + ' failed' - : '0 failed'; - - if (w.running) { - wrap.style.display = ''; - bar.style.width = pct + '%'; - bar.textContent = pct + ' %'; - text.innerHTML = 'running ' - + handled + ' of ' + queued + ' pages (' - + num(w.done) + ' rendered, ' + num(w.skipped) + ' still fresh, ' + failed + ')' - + '
Live - updates every 2 seconds.
'; - } else if (w.startedAt) { - wrap.style.display = 'none'; - const finished = w.finishedAt - ? ' finished ' + new Date(w.finishedAt).toLocaleTimeString() + '' - : ''; - text.innerHTML = 'Last run: ' + num(w.done) + ' of ' + queued + ' pages rendered (' - + num(w.skipped) + ' still fresh, ' + failed + ')' - + (w.aborted ? ' aborted by restart' : '') - + finished; - } else { - wrap.style.display = 'none'; - text.innerHTML = 'no run since the server started'; - } - - if (cacheLine && typeof h.cachedPages === 'number') { - const limit = parseInt(cacheLine.dataset.limit || '0', 10); - cacheLine.textContent = 'Cache: ' + h.cachedPages + ' pages · ' + num(h.cacheMB) + ' MB' - + (limit > 0 ? ' of ' + limit + ' MB' : ''); - } - if (warmButton) { - warmButton.disabled = !!w.running; - warmButton.classList.toggle('is-running', !!w.running); - } - return !!w.running; - }; - - const schedule = (ms) => { - clearTimeout(timer); - timer = setTimeout(tick, ms); - }; - - const tick = () => { - new AjaxRequest(TYPO3.settings.ajaxUrls.vitec_ssr_health).get() - .then((response) => response.resolve()) - .then((data) => { - const running = data && data.health ? render(data.health) : false; - schedule(running ? 2000 : 15000); - }) - .catch(() => schedule(15000)); - }; - - schedule(cell.dataset.running === '1' ? 1000 : 15000); - document.addEventListener('visibilitychange', () => { - if (document.hidden) { - clearTimeout(timer); - } else { - tick(); - } - }); -}