A self-hosted LanguageTool (dev: docker/docker-compose.yml, started by `make up`) checks what the user writes in the compose window, through POST /api/spellcheck — the browser never talks to the engine directly. - Marks are CSS highlights over the text, never written into the message: red wavy for spelling, blue for grammar/style. Clicking one shows the message, up to five suggestions (applied as typed, so Ctrl+Z undoes them) and Ignore. The popup, like the link popup, opens above its anchor when there is no room below. - Checked after a pause in typing; the signature and quoted original are skipped; marks on words just edited drop at once; a check overtaken by a newer one, by turning checking off, or by closing the window is discarded. - With "auto", text is checked in chunks of lines, each in its own detected language — LanguageTool settles on one language per request, so a mixed Polish/English message had every English word flagged as a Polish typo. - Settings > Appearance: on/off and language (Auto-detect or any of the engine's languages); the compose window's More menu overrides it for one message. The browser's own spellcheck steps aside while ours runs, and comes back when it is off or the server has no engine (503 from the endpoint). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
56 lines
2.0 KiB
Python
56 lines
2.0 KiB
Python
"""REST API routers (SPEC §9.1). One module per route group."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from fastapi import FastAPI
|
|
|
|
|
|
def register_routers(app: FastAPI) -> None:
|
|
"""Mount all API routers under the ``/api`` prefix.
|
|
|
|
Routers are added milestone by milestone; imports are local so the app
|
|
factory stays importable while modules are still being built out.
|
|
"""
|
|
from app.api.accounts import router as accounts_router
|
|
from app.api.actions import router as actions_router
|
|
from app.api.admin import router as admin_router
|
|
from app.api.avatar import router as avatar_router
|
|
from app.api.compose import router as compose_router
|
|
from app.api.mailboxes import router as mailboxes_router
|
|
from app.api.messages import router as messages_router
|
|
from app.api.plugins import router as plugins_router
|
|
from app.api.recipients import router as recipients_router
|
|
from app.api.saved_searches import router as saved_searches_router
|
|
from app.api.search import router as search_router
|
|
from app.api.settings import router as settings_router
|
|
from app.api.spellcheck import router as spellcheck_router
|
|
from app.api.threads import router as threads_router
|
|
from app.identity.routes import router as auth_router
|
|
from app.ws import router as ws_router
|
|
|
|
for router in (
|
|
auth_router,
|
|
accounts_router,
|
|
threads_router,
|
|
messages_router,
|
|
search_router,
|
|
actions_router,
|
|
compose_router,
|
|
recipients_router,
|
|
settings_router,
|
|
mailboxes_router,
|
|
saved_searches_router,
|
|
avatar_router,
|
|
plugins_router,
|
|
admin_router,
|
|
spellcheck_router,
|
|
):
|
|
app.include_router(router, prefix="/api")
|
|
app.include_router(ws_router, prefix="/api")
|
|
|
|
# Mount discovered plugin routers at /api/plugins/{name} (SPEC §11). Hooks are
|
|
# subscribed in the lifespan startup so they register once per process.
|
|
from app.plugins import loader
|
|
|
|
loader.mount_routers(app)
|