diff --git a/lib/esbonio/changes/704.enhancement.md b/lib/esbonio/changes/704.enhancement.md new file mode 100644 index 000000000..c6555312d --- /dev/null +++ b/lib/esbonio/changes/704.enhancement.md @@ -0,0 +1 @@ +When clicking on internal links of a previewed page, the corresponding source file will be automatically opened in the editor diff --git a/lib/esbonio/changes/906.fix.md b/lib/esbonio/changes/906.fix.md index 218dfe35d..7fd2cc9de 100644 --- a/lib/esbonio/changes/906.fix.md +++ b/lib/esbonio/changes/906.fix.md @@ -1 +1,3 @@ -The `esbonio.preview.showLineMarkers` option should now work again +The `esbonio.preview.showLineMarkers` option should now work again. + +When clicking on internal links of a previewed page, the websocket connection to the language server is now preserved. diff --git a/lib/esbonio/esbonio/sphinx_agent/static/webview.js b/lib/esbonio/esbonio/sphinx_agent/static/webview.js index e18dacb6c..c659f530b 100644 --- a/lib/esbonio/esbonio/sphinx_agent/static/webview.js +++ b/lib/esbonio/esbonio/sphinx_agent/static/webview.js @@ -2,6 +2,60 @@ // which allows the webpage to talk with the preview server and coordinate details such as refreshes // and page scrolling. +/** + * Rewrite internal links so that the link between the webview and + * language server is maintained across pages. + */ +function rewriteInternalLinks(wsPort) { + if (!wsPort) { + return + } + + const links = Array.from(document.querySelectorAll("a.internal")) + + for (let link of links) { + let uri + try { + uri = new URL(link.href) + } catch (err) { + console.debug(`Skipping link ${link.href}, ${err}`) + continue + } + + if (!uri.search) { + uri.search = `?ws=${wsPort}` + } else if (!uri.searchParams.get('ws')) { + uri.search += `&ws=${wsPort}` + } + + link.href = uri.toString() + } +} + +/** + * Sync the webview's scroll position with the editor + */ +function syncScrollPosition() { + const target = findEditorScrollTarget() + if (!target) { + console.debug('No target found') + return + } + + const uri = target[0] + const line = target[1] + + if (!uri || !line) { + console.debug('Missing uri or line') + return + } + + // TODO: Rate limits. + sendMessage( + { jsonrpc: "2.0", method: "editor/scroll", params: { uri: uri, line: line } } + ) +} + /** * Get the uri and line number of the given marker * @@ -117,7 +171,7 @@ function scrollViewTo(uri, linum) { const t = (linum - previousLine) / Math.max(currentLine - previousLine, 1) const y = (1 - t) * previousPos + t * currentPos - console.table({line: linum, previous: previousLine, current: currentLine, t: t, y: y}) + // console.table({line: linum, previous: previousLine, current: currentLine, t: t, y: y}) window.scrollTo(0, y - 60) } @@ -216,29 +270,15 @@ function handle(message) { } window.addEventListener("scroll", (event) => { - const target = findEditorScrollTarget() - if (!target) { - return - } - - const uri = target[0] - const line = target[1] - - if (!uri || !line) { - return - } - - // TODO: Rate limits. - sendMessage( - { jsonrpc: "2.0", method: "editor/scroll", params: { uri: uri, line: line } } - ) - + syncScrollPosition() }) // Connection opened socket.addEventListener("open", (event) => { console.debug("Connected.") connected = true + + setTimeout(syncScrollPosition, 50) }); // Listen for messages @@ -251,6 +291,8 @@ function main() { renderLineMarkers() } + rewriteInternalLinks(ws) + // Are we in an