diff --git a/README.md b/README.md index 989ac88..cb6941a 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ tono is a node-based SPM image processing and analysis tool. The main focus is o It is heavily inspired by [Gwyddion](https://gwyddion.net/), one of my favorite scientific FOSS programs on the web. - + ## Quick start Install a local binary from the Releases section, or run locally: @@ -28,9 +28,10 @@ npm run dev # terminal 2 — Vite dev server, open the URL it prints ```bash git clone https://github.com/VIPQualityPost/tono.git && cd tono +python -m venv .venv && source .venv/bin/activate pip install -e . cd frontend && npm ci && npm run build && cd .. -TONO_HOST=0.0.0.0 tono +TONO_HOST=0.0.0.0 python -m backend.main ``` See [Self-Hosting](docs/self-hosting.md) for reverse proxy setup, environment variables, and configuration. diff --git a/backend/server.py b/backend/server.py index 5cff300..706b8c3 100644 --- a/backend/server.py +++ b/backend/server.py @@ -715,10 +715,18 @@ def create_app( app.router.add_get("/check-update", check_update) app.router.add_get("/ws", websocket_handler) + async def dist_file(request: web.Request) -> web.Response: + filename = request.match_info["filename"] + path = (DIST_DIR / filename).resolve() + if not path.is_relative_to(DIST_DIR.resolve()) or not path.is_file(): + raise web.HTTPNotFound() + return web.FileResponse(path) + if (DIST_DIR / "assets").exists(): app.router.add_static("/assets", DIST_DIR / "assets") if FRONTEND_DIR.exists(): app.router.add_static("/static", FRONTEND_DIR) + app.router.add_get("/{filename}", dist_file) async def _cors_middleware(app_, handler): async def middleware(request): diff --git a/docs/self-hosting.md b/docs/self-hosting.md index 19971c3..de7c92d 100644 --- a/docs/self-hosting.md +++ b/docs/self-hosting.md @@ -9,7 +9,7 @@ git clone https://github.com/VIPQualityPost/tono.git && cd tono python -m venv .venv && source .venv/bin/activate pip install -e . cd frontend && npm ci && npm run build && cd .. -TONO_HOST=0.0.0.0 tono +TONO_HOST=0.0.0.0 python -m backend.main ``` The server will be available at `http://:8188`. @@ -48,7 +48,7 @@ After=network.target Type=simple User=tono WorkingDirectory=/opt/tono -ExecStart=/opt/tono/.venv/bin/tono +ExecStart=/opt/tono/.venv/bin/python -m backend.main Environment=TONO_HOST=127.0.0.1 Environment=TONO_PORT=8188 Environment=TONO_APPDATA=/var/lib/tono diff --git a/frontend/src/HelpPanelManager.tsx b/frontend/src/HelpPanelManager.tsx index c685f99..03ef50b 100644 --- a/frontend/src/HelpPanelManager.tsx +++ b/frontend/src/HelpPanelManager.tsx @@ -4,16 +4,18 @@ import { marked } from 'marked'; import DOMPurify from 'dompurify'; // Open external links in new tabs -const renderer = new marked.Renderer(); -const defaultLinkRenderer = renderer.link.bind(renderer); -renderer.link = function (token) { - const html = defaultLinkRenderer(token); - if (token.href && /^https?:\/\//.test(token.href)) { - return html.replace(/^${text}`; + } + return `${text}`; + }, + }, +}); interface Heading { level: number; diff --git a/frontend/src/styles.css b/frontend/src/styles.css index 3f40027..4de3eea 100644 --- a/frontend/src/styles.css +++ b/frontend/src/styles.css @@ -608,10 +608,10 @@ html, body, #root { .node-help-panel { position: fixed; - top: 60px; + top: 12px; right: 20px; width: 620px; - max-height: calc(100vh - 80px); + max-height: calc(100vh - 32px); background: #1e293b; border: 1px solid #334155; border-radius: 8px;