diff --git a/backend/main.py b/backend/main.py index fffb41d..07f2fb9 100644 --- a/backend/main.py +++ b/backend/main.py @@ -2364,6 +2364,37 @@ async def api_file(vault_name: str, path: str = Query(..., description="Relative logger.error(f"PDF read error for {path}: {e}") raise HTTPException(status_code=500, detail=f"Error reading PDF: {e!s}") + # === Images: return as viewable image === + IMAGE_EXTENSIONS = {".png", ".jpg", ".jpeg", ".gif", ".svg", ".webp", ".bmp", ".ico"} + if ext in IMAGE_EXTENSIONS: + size = file_path.stat().st_size + mime_map = { + ".png": "image/png", ".jpg": "image/jpeg", ".jpeg": "image/jpeg", + ".gif": "image/gif", ".svg": "image/svg+xml", ".webp": "image/webp", + ".bmp": "image/bmp", ".ico": "image/x-icon", + } + mime = mime_map.get(ext, "application/octet-stream") + html = ( + f'
Fichier CSV vide
" + else: + headers = rows[0] + data_rows = rows[1:] + html = '| {h} | " + html += "
|---|
| {cell} | " + html += "
{html_mod.escape(formatted)}"
+ return {
+ "vault": vault_name, "path": path,
+ "title": file_path.name, "tags": [], "frontmatter": {},
+ "html": html, "raw_length": len(raw), "extension": ext,
+ "is_markdown": False, "is_json": True,
+ }
+
+ # === Plain text / other readable files ===
+ TEXT_EXTENSIONS = {".txt", ".log", ".yml", ".yaml", ".toml", ".ini", ".cfg",
+ ".sh", ".bash", ".py", ".js", ".ts", ".html", ".css",
+ ".xml", ".rst", ".tex", ".sql", ".conf", ".env"}
+ if ext in TEXT_EXTENSIONS or ext == ".md":
+ pass # handled below or by markdown section
+
if ext == ".md":
post = parse_markdown_file(raw)
diff --git a/build.sh b/build.sh
old mode 100644
new mode 100755
diff --git a/data/users.json b/data/users.json
deleted file mode 100644
index cccdd1f..0000000
--- a/data/users.json
+++ /dev/null
@@ -1,20 +0,0 @@
-{
- "version": 1,
- "users": {
- "admin": {
- "id": "f7b85dfa-bcf6-4e42-b861-7563673620a6",
- "username": "admin",
- "display_name": "admin",
- "password_hash": "$argon2id$v=19$m=65536,t=2,p=2$H4Pa7H4HOWeQoEbj4Ndkbw$c61e9zRHuXXdrLB6uTrjIBo/FFQaaZMaNHkB7CZaHhM",
- "role": "admin",
- "vaults": [
- "*"
- ],
- "active": true,
- "created_at": "2026-03-23T19:38:00.742597+00:00",
- "last_login": null,
- "failed_attempts": 5,
- "locked_until": "2026-06-02T14:01:43.472937+00:00"
- }
- }
-}
\ No newline at end of file
diff --git a/frontend/js/viewer.js b/frontend/js/viewer.js
index cf8eaf8..3cd58ed 100644
--- a/frontend/js/viewer.js
+++ b/frontend/js/viewer.js
@@ -431,13 +431,78 @@ export function renderFile(data) {
${escapeHtml(text)}
+ Erreur lors du chargement du fichier.
`; + }); + return; + } + // Handle unsupported (binary) files if (data.unsupported) { const sizeStr = data.size_bytes diff --git a/frontend/style.css b/frontend/style.css index ae2d9f5..fcf8694 100644 --- a/frontend/style.css +++ b/frontend/style.css @@ -8539,6 +8539,97 @@ body.popup-mode .content-area { margin-left: 4px; } +/* ── Image Viewer ── */ +.image-viewer-body { + display: flex; + align-items: center; + justify-content: center; + min-height: 200px; + background: var(--surface1); + padding: 20px; +} +.image-viewer-body img { + border-radius: 4px; + box-shadow: 0 2px 12px rgba(0,0,0,0.15); +} + +/* ── Text / CSV Viewer ── */ +.text-viewer-container { + display: flex; + flex-direction: column; + height: 100%; +} +.file-toolbar { + display: flex; + align-items: center; + gap: 8px; + padding: 8px 16px; + background: var(--surface1); + border-bottom: 1px solid var(--border); + font-size: 0.85rem; + flex-shrink: 0; +} +.file-info { + flex: 1; + color: var(--text-dim); +} +.text-viewer-body { + flex: 1; + overflow: auto; + padding: 16px; + background: var(--surface2); +} +.text-viewer-body pre { + margin: 0; + font-family: 'JetBrains Mono', 'Fira Code', 'Consolas', monospace; + font-size: 0.85rem; + line-height: 1.5; + white-space: pre-wrap; +} +.text-viewer-body code { + color: var(--text); +} + +/* ── CSV Table ── */ +.csv-table-wrapper { + overflow: auto; + max-height: 70vh; +} +.csv-table { + width: 100%; + border-collapse: collapse; + font-size: 0.85rem; +} +.csv-table th { + background: var(--surface1); + color: var(--text-dim); + font-weight: 600; + padding: 8px 12px; + text-align: left; + border-bottom: 2px solid var(--border); + position: sticky; + top: 0; +} +.csv-table td { + padding: 6px 12px; + border-bottom: 1px solid var(--border-light, var(--border)); +} +.csv-table tr:hover td { + background: var(--surface1); +} + +/* ── JSON Viewer ── */ +.json-viewer { + font-family: 'JetBrains Mono', 'Fira Code', 'Consolas', monospace; + font-size: 0.85rem; + line-height: 1.5; + padding: 16px; + background: var(--surface2); + border-radius: 6px; + overflow: auto; + max-height: 70vh; +} + /* ── PaneManager — Split View ── */ .pane-grid { display: grid;