diff --git a/frontend/index.html b/frontend/index.html index 24cea3f2770..c59c69bfe74 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -60,7 +60,6 @@ {{ title }} -
diff --git a/marimo/_server/api/endpoints/assets.py b/marimo/_server/api/endpoints/assets.py index 5df2bf81ddb..65296f4d348 100644 --- a/marimo/_server/api/endpoints/assets.py +++ b/marimo/_server/api/endpoints/assets.py @@ -4,7 +4,7 @@ import mimetypes import os import re -from typing import TYPE_CHECKING, Optional +from typing import TYPE_CHECKING from starlette.authentication import requires from starlette.exceptions import HTTPException @@ -15,7 +15,6 @@ from marimo._config.manager import UserConfigManager from marimo._runtime.virtual_file import EMPTY_VIRTUAL_FILE, read_virtual_file from marimo._server.api.deps import AppState -from marimo._server.file_router import MarimoFileKey from marimo._server.router import APIRouter from marimo._server.templates.templates import ( home_page_template, @@ -91,25 +90,6 @@ async def index(request: Request) -> HTMLResponse: return HTMLResponse(html) -# This serves the custom.css file if it was -# supplied in the app config -@router.get("/custom.css") -@requires("read") -def custom_css(request: Request) -> Response: - app_state = AppState(request) - file_key: Optional[MarimoFileKey] = ( - app_state.query_params(FILE_QUERY_PARAM_KEY) - or app_state.session_manager.file_router.get_unique_file_key() - ) - - if not file_key: - return Response("", media_type="text/css") - - app_manager = app_state.session_manager.app_manager(file_key) - css = app_manager.read_css_file() or "" - return Response(css, media_type="text/css") - - STATIC_FILES = [ r"(favicon\.ico)", r"(circle-check\.ico)", diff --git a/marimo/_server/templates/templates.py b/marimo/_server/templates/templates.py index 17533cc8cef..7a0a144826d 100644 --- a/marimo/_server/templates/templates.py +++ b/marimo/_server/templates/templates.py @@ -65,6 +65,14 @@ def notebook_page_template( "{{ mode }}", "read" if mode == SessionMode.RUN else "edit", ) + # If has custom css, inline the css and add to the head + if app_config.css_file: + css_contents = read_css_file(app_config.css_file, filename=filename) + if css_contents: + css_contents = f"" + # Append to head + html = html.replace("", f"{css_contents}") + return html @@ -167,7 +175,7 @@ def static_notebook_template( .replace('src="./', f'crossorigin="anonymous" src="{asset_url}/') ) - # Append to body + # Append to head html = html.replace("", f"{static_block}") # Append to body html = html.replace("", f"{code_block}") diff --git a/marimo/_smoke_tests/theming/custom_css.py b/marimo/_smoke_tests/theming/custom_css.py index 784193b1acb..ca311783f66 100644 --- a/marimo/_smoke_tests/theming/custom_css.py +++ b/marimo/_smoke_tests/theming/custom_css.py @@ -1,3 +1,10 @@ +# /// script +# requires-python = ">=3.11" +# dependencies = [ +# "vega-datasets", +# "marimo", +# ] +# /// import marimo __generated_with = "0.8.3" diff --git a/tests/_server/api/endpoints/test_assets.py b/tests/_server/api/endpoints/test_assets.py index fa5d358072a..1fbdd805cdf 100644 --- a/tests/_server/api/endpoints/test_assets.py +++ b/tests/_server/api/endpoints/test_assets.py @@ -1,7 +1,6 @@ # Copyright 2024 Marimo. All rights reserved. from __future__ import annotations -import os from tempfile import TemporaryDirectory from typing import TYPE_CHECKING, Any, cast @@ -35,36 +34,6 @@ def test_index(client: TestClient) -> None: assert f"{title}" in content -def test_custom_css_empty(client: TestClient) -> None: - response = client.get("/custom.css", headers=token_header()) - assert response.status_code == 200, response.text - assert response.headers["content-type"] == "text/css; charset=utf-8" - - -def test_custom_css_non_empty(client: TestClient) -> None: - session_manager = AppState.from_app(cast(Any, client.app)).session_manager - css = "/* custom css */" - filename = session_manager.file_router.get_unique_file_key() - assert filename is not None - - css_file = os.path.join(os.path.dirname(filename), "custom.css") - with open(css_file, "w") as f: - f.write(css) - - # set config - session_manager.app_manager(filename).save_app_config( - {"css_file": "custom.css"} - ) - - try: - response = client.get("/custom.css", headers=token_header()) - assert response.status_code == 200, response.text - assert response.headers["content-type"] == "text/css; charset=utf-8" - assert response.text == css - finally: - os.remove(css_file) - - @with_file_router(AppFileRouter.from_files([])) def test_index_when_empty(client: TestClient) -> None: # Login page diff --git a/tests/_server/templates/test_templates.py b/tests/_server/templates/test_templates.py index 6e347094c41..62c3831e468 100644 --- a/tests/_server/templates/test_templates.py +++ b/tests/_server/templates/test_templates.py @@ -81,6 +81,29 @@ def test_notebook_page_template_edit_mode(self) -> None: assert self.filename in result assert "edit" in result + def test_notebook_page_template_custom_css(self) -> None: + # Create css file + css = "/* custom css */" + + css_file = os.path.join(os.path.dirname(self.filename), "custom.css") + with open(css_file, "w") as f: + f.write(css) + + try: + result = templates.notebook_page_template( + self.html, + self.base_url, + self.user_config, + self.server_token, + _AppConfig(css_file="custom.css"), + self.filename, + self.mode, + ) + + assert css in result + finally: + os.remove(css_file) + class TestHomePageTemplate(unittest.TestCase): def setUp(self) -> None: