Skip to content

Commit

Permalink
sphinx-agent: Rewrite internal links
Browse files Browse the repository at this point in the history
As part of its initial setup, the injected `webview.js` script now
rewrites any `a.internal` links to include the port number of the
current websocket connection. This ensures that as the user navigates
by clicking on links on the page the websocket connection to the
language server is preserved.

Also by doing an initial scroll sync on page load, this ensures that
the editor is kept in sync with the change! There is a chance for this
to be a bit flaky as this in direct conflict with the initial sync an
editor might want to make if it initiates the preview of a page.

By introducing a small delay on the sync made by the webview, we are
relying on the editor winning the race and getting its message in
first... I'm sure that will never cause an issue in the future!
  • Loading branch information
alcarney committed Sep 29, 2024
1 parent 4dab038 commit b7cb5dd
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 19 deletions.
1 change: 1 addition & 0 deletions lib/esbonio/changes/704.enhancement.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
When clicking on internal links of a previewed page, the corresponding source file will be automatically opened in the editor
4 changes: 3 additions & 1 deletion lib/esbonio/changes/906.fix.md
Original file line number Diff line number Diff line change
@@ -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.
78 changes: 60 additions & 18 deletions lib/esbonio/esbonio/sphinx_agent/static/webview.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
*
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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
Expand All @@ -251,6 +291,8 @@ function main() {
renderLineMarkers()
}

rewriteInternalLinks(ws)

// Are we in an <iframe>?
if (window.parent !== window.top) {
window.parent.postMessage({ 'ready': true }, "*")
Expand Down

0 comments on commit b7cb5dd

Please sign in to comment.