Implemented common formulas and Tectonic LaTeX engine#16
Implemented common formulas and Tectonic LaTeX engine#16Davictory2003 wants to merge 5 commits intomainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR shifts LaTeX rendering from an in-browser Markdown/KaTeX preview to a backend-powered PDF compilation flow using the Tectonic engine, and adds a UI formula picker to quickly insert common math expressions into the editor.
Changes:
- Replace the client-side Markdown/KaTeX preview + html2canvas/jsPDF export with backend PDF compilation + iframe preview and direct PDF download.
- Add a subject/category formula selector UI to insert common LaTeX formulas into the editor.
- Add a new backend
/api/compile/endpoint that runstectonicinside the backend container, and install Tectonic in the backend Docker image.
Reviewed changes
Copilot reviewed 7 out of 8 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| frontend/src/components/CreateCheatSheet.jsx | Adds formula picker; switches preview/download to call backend LaTeX compiler and embed returned PDF |
| frontend/src/App.css | Styles for the subject/category tabs and formula buttons |
| frontend/package.json | Removes markdown/KaTeX + PDF screenshot dependencies now that compilation is server-side |
| frontend/package-lock.json | Lockfile updates reflecting removed frontend dependencies |
| backend/requirements.txt | Adds a new Python dependency (currently unused) |
| backend/api/views.py | Introduces compile_latex endpoint that writes LaTeX to a temp dir and runs tectonic |
| backend/api/urls.py | Exposes the new /api/compile/ route |
| backend/Dockerfile | Installs OS deps and downloads the Tectonic binary into the backend image |
Files not reviewed (1)
- frontend/package-lock.json: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const response = await fetch('http://localhost:8000/api/compile/', { | ||
| method: 'POST', | ||
| headers: { 'Content-Type': 'application/json' }, | ||
| body: JSON.stringify({ content }) | ||
| }); |
There was a problem hiding this comment.
The LaTeX compile endpoint is hardcoded to http://localhost:8000, which bypasses the existing Vite /api proxy (and will break when the backend is not on localhost in production or behind a different host/path). Use a relative /api/compile/ URL (or a configured env/base URL) so it works with the configured proxy and deployments.
| const blob = await response.blob(); | ||
| const url = URL.createObjectURL(blob); | ||
| const a = document.createElement('a'); | ||
| a.href = url; | ||
| a.download = `${title || 'cheat-sheet'}.pdf`; | ||
| document.body.appendChild(a); | ||
| a.click(); | ||
| document.body.removeChild(a); |
There was a problem hiding this comment.
In the download flow, an object URL is created for the PDF but never revoked. Revoke it after triggering the download (ideally in a finally block) to avoid leaking object URLs.
| result = subprocess.run( | ||
| ["tectonic", tex_file_path], | ||
| cwd=tempdir, | ||
| capture_output=True, | ||
| text=True, | ||
| check=True | ||
| ) |
There was a problem hiding this comment.
subprocess.run(...) has no timeout or other guardrails. A malformed/complex LaTeX input can hang or run for a long time, tying up worker processes. Add a timeout and handle TimeoutExpired (and consider basic size limits for content).
| except subprocess.CalledProcessError as e: | ||
| return Response({"error": "Failed to compile LaTeX", "details": e.stderr}, status=400) |
There was a problem hiding this comment.
Returning raw LaTeX compiler stderr (details: e.stderr) to the client can leak internal paths/environment details and produces very large responses. Prefer logging the full stderr server-side and returning a sanitized/limited error message to the client.
| const blob = await response.blob(); | ||
| setPdfBlob(URL.createObjectURL(blob)); | ||
| } catch (error) { |
There was a problem hiding this comment.
URL.createObjectURL(blob) is stored in state for the preview but never revoked. Repeated previews will leak memory; revoke the previous URL when replacing it and on component unmount (e.g., via useEffect cleanup).
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
No description provided.