Add browser Python editor with Pyodide, user auth, and workspace API

- FastAPI serves static UI, file CRUD under code/ and read-only lib/
- Pyodide worker runs Python and Jedi completions in the browser
- SQLite accounts: login/register, session cookies, superuser user management
- Optional EDITOR_API_KEY, AUTH_* env vars, .env.example
- Pipenv, pytest, Selenium smoke test, README

Made-with: Cursor
This commit is contained in:
2026-05-01 14:33:26 +12:00
parent d245ecd353
commit f204109a84
40 changed files with 4950 additions and 2 deletions

72
src/static/index.html Normal file
View File

@@ -0,0 +1,72 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Python Editor</title>
<link rel="icon" href="data:,">
<link rel="stylesheet" href="/static/styles.css?v=6">
</head>
<body>
<div class="container">
<div class="sidebar">
<div class="sidebar-header">
<h3>Files</h3>
<div class="sidebar-actions">
<button id="new-file-btn" title="New File">📄</button>
<button id="new-folder-btn" title="New Folder">📁+</button>
<button id="delete-selected-btn" title="Delete Selected">🗑️</button>
<button id="refresh-btn" title="Refresh">🔄</button>
</div>
</div>
<div class="file-tree" id="file-tree">
<div class="loading">Loading files...</div>
</div>
</div>
<div class="main-content">
<div class="editor-header">
<div class="file-info">
<span id="save-status" class="save-status"></span>
<span class="runtime-hint" title="Python runs locally in your browser via Pyodide; completions use Jedi in the same runtime.">Browser · Pyodide</span>
</div>
<div class="mode-toggle">
<a id="home-btn" class="mode-btn active" href="/">Home</a>
</div>
<div class="editor-actions">
<button id="run-btn" disabled>Run Python</button>
<button id="stop-btn" disabled>Stop</button>
<select id="run-file-select" title="Script to run">
<option value="">Run active file</option>
</select>
</div>
</div>
<div id="tabs" class="tabs"></div>
<div class="editor-container">
<div id="editor"></div>
<div id="completion-dropdown" class="completion-dropdown"></div>
</div>
<div class="console-container">
<div class="console-header">Console Output</div>
<pre id="console-output" class="console-output"></pre>
</div>
</div>
</div>
<div id="new-file-modal" class="modal">
<div class="modal-content">
<h3>Create New File</h3>
<input type="text" id="new-filename" placeholder="Enter filename (e.g., example.txt)" />
<div class="modal-actions">
<button id="create-file-btn">Create</button>
<button id="cancel-create-btn">Cancel</button>
</div>
</div>
</div>
<script type="module" src="/static/script.js?v=10"></script>
</body>
</html>