From 4ffbe62e3b83971305af67312c7fab04f1f8b6df Mon Sep 17 00:00:00 2001 From: Garvin Hicking Date: Wed, 12 Nov 2025 12:08:29 +0100 Subject: [PATCH 1/2] [TASK] Update hot reloading javascript to remember scroll position The hot reloading currently only reloads the full page. However, it would be desirable when doing "live documentation" to reload the page and keeping the current scroll position in sync. The JavaScript is now adapted to locally store the current position, and restore it after page reload. The temporary sessionStorage is utilized for this, which is tab-specific. A small timeout ensures that if a page with locationHash is reloaded can properly jump to the stored position. Debug output is added while this feature is experimental. Also, the 'ws' URI is auto-detected so it can work on HTTPS and HTTP connections - this is queried via JavaScript and thus can work on reverse proxy setups. --- .../dev-server/src/Internal/HttpHandler.php | 31 ++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/packages/dev-server/src/Internal/HttpHandler.php b/packages/dev-server/src/Internal/HttpHandler.php index 158f9a397..54677644a 100644 --- a/packages/dev-server/src/Internal/HttpHandler.php +++ b/packages/dev-server/src/Internal/HttpHandler.php @@ -104,15 +104,38 @@ private function injectWebSocketClient(string $html): string //Read html and inject script before closing body tag $injection = <<<'EOT' -EOT; + + // Restore scroll position after page loads. Note that sessionStorage is + // browser-tab specific, so multiple instances should not affect each other. + window.addEventListener('load', function() { + const scrollPosition = sessionStorage.getItem('scrollPosition'); + const scrollURL = sessionStorage.getItem('scrollURL'); + + // Only restore if we're on the same URL (hot reload, not navigation) + if (scrollPosition !== null && scrollURL === window.location.href) { + console.log('Prepare to restore scrollPosition to: ' + scrollPosition); + + // Use setTimeout to override hash scrolling that happens after load + setTimeout(function() { + console.log('Restoring scrollPosition to: ' + scrollPosition); + window.scrollTo(0, parseInt(scrollPosition)); + }, 10); + } + + // Ensure local scroll position is reset, so other reloads to not carry state. + sessionStorage.removeItem('scrollPosition'); + sessionStorage.removeItem('scrollURL'); + }); +EOT; return str_replace('', $injection . '', $html); } From f807b9d09a2d73d7b673a68260e8f5eca3035d55 Mon Sep 17 00:00:00 2001 From: Garvin Hicking Date: Wed, 12 Nov 2025 13:20:44 +0100 Subject: [PATCH 2/2] Apply suggestion from @garvinhicking --- packages/dev-server/src/Internal/HttpHandler.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/dev-server/src/Internal/HttpHandler.php b/packages/dev-server/src/Internal/HttpHandler.php index 54677644a..820691bd6 100644 --- a/packages/dev-server/src/Internal/HttpHandler.php +++ b/packages/dev-server/src/Internal/HttpHandler.php @@ -135,7 +135,8 @@ private function injectWebSocketClient(string $html): string sessionStorage.removeItem('scrollPosition'); sessionStorage.removeItem('scrollURL'); }); -EOT; + +EOT; return str_replace('', $injection . '', $html); }