From c865c78cfe39d50785ef226f4f49932b6f1c5e0b Mon Sep 17 00:00:00 2001 From: Alex Carney Date: Mon, 3 Jun 2024 21:34:39 +0100 Subject: [PATCH] sphinx-agent: Inline `webview.js` into build files This is more robust than trying to compute a relative path between esbonio's install location and the target project - especially when you consider issues like separate Windows paritions --- lib/esbonio/changes/810.fix.md | 1 + .../esbonio/sphinx_agent/handlers/__init__.py | 24 +++++-------------- .../tests/sphinx-agent/test_sa_build.py | 17 ++++++------- 3 files changed, 16 insertions(+), 26 deletions(-) create mode 100644 lib/esbonio/changes/810.fix.md diff --git a/lib/esbonio/changes/810.fix.md b/lib/esbonio/changes/810.fix.md new file mode 100644 index 000000000..f4a5713bd --- /dev/null +++ b/lib/esbonio/changes/810.fix.md @@ -0,0 +1 @@ +The server should no longer throw path mount errors when used across partitions on Windows diff --git a/lib/esbonio/esbonio/sphinx_agent/handlers/__init__.py b/lib/esbonio/esbonio/sphinx_agent/handlers/__init__.py index ddd60f478..b669b4a64 100644 --- a/lib/esbonio/esbonio/sphinx_agent/handlers/__init__.py +++ b/lib/esbonio/esbonio/sphinx_agent/handlers/__init__.py @@ -1,6 +1,5 @@ import inspect import logging -import os.path import pathlib import sys import traceback @@ -125,8 +124,7 @@ def create_sphinx_app(self, request: types.CreateApplicationRequest): # TODO: Sphinx 7.x has introduced a `include-read` event # See: https://github.com/sphinx-doc/sphinx/pull/11657 - if request.params.enable_sync_scrolling: - _enable_sync_scrolling(self.app) + _enable_sync_scrolling(self.app) response = types.CreateApplicationResponse( id=request.id, @@ -199,21 +197,11 @@ def _enable_sync_scrolling(app: Sphinx): """Given a Sphinx application, configure it so that we can support syncronised scrolling.""" - # On OSes like Fedora Silverblue where `/home` is a symlink for `/var/home` - # we could have a situation where `STATIC_DIR` and `app.confdir` have - # different root dirs... which is enough to cause `os.path.relpath` to return - # the wrong path. + # Inline the JS code we need to enable sync scrolling. # - # Fully resolving both `STATIC_DIR` and `app.confdir` should be enough to - # mitigate this. - confdir = pathlib.Path(app.confdir).resolve() + # Yes this "bloats" every page in the generated docs, but is generally more robust + # see: https://github.com/swyddfa/esbonio/issues/810 + webview_js = STATIC_DIR / "webview.js" + app.add_js_file(None, body=webview_js.read_text()) - # Push our folder of static assets into the user's project. - # Path needs to be relative to their project's confdir. - reldir = os.path.relpath(str(STATIC_DIR), start=str(confdir)) - app.config.html_static_path.append(reldir) - - app.add_js_file("webview.js") - - # Inject source line numbers into build output app.add_transform(LineNumberTransform) diff --git a/lib/esbonio/tests/sphinx-agent/test_sa_build.py b/lib/esbonio/tests/sphinx-agent/test_sa_build.py index f8244d0fe..c77a30b63 100644 --- a/lib/esbonio/tests/sphinx-agent/test_sa_build.py +++ b/lib/esbonio/tests/sphinx-agent/test_sa_build.py @@ -1,6 +1,5 @@ import logging import pathlib -import re import sys import pytest @@ -19,6 +18,9 @@ from esbonio.server.features.sphinx_manager.config import SphinxConfig logger = logging.getLogger(__name__) +STATIC_DIR = ( + pathlib.Path(__file__).parent.parent.parent / "esbonio" / "sphinx_agent" / "static" +).resolve() @pytest.mark.asyncio @@ -26,18 +28,17 @@ async def test_build_includes_webview_js(client: SubprocessSphinxClient, uri_for """Ensure that builds include the ``webview.js`` script.""" out = client.build_uri - src = client.src_uri - assert out is not None and src is not None + assert out is not None - # Ensure the script is included in the build output - webview_js = pathlib.Path(out / "_static" / "webview.js") + webview_js = STATIC_DIR / "webview.js" assert webview_js.exists() - assert "editor/scroll" in webview_js.read_text() + + webview_script = webview_js.read_text() + assert "editor/scroll" in webview_script # Ensure the script is included in the page index_html = pathlib.Path(out / "index.html") - pattern = re.compile(r'') - assert pattern.search(index_html.read_text()) is not None + assert webview_script in index_html.read_text() @pytest.mark.asyncio