feat(excalidraw): support complet des fichiers .excalidraw (#78)
CI / lint (push) Failing after 9s
CI / test (push) Has been skipped
CI / build (push) Has been skipped
CI / e2e (push) Has been skipped
CI / security (push) Successful in 13s
Desktop Build / build-windows (push) Has been cancelled
Desktop Build / build-linux (push) Has been cancelled
CI / lint (push) Failing after 9s
CI / test (push) Has been skipped
CI / build (push) Has been skipped
CI / e2e (push) Has been skipped
CI / security (push) Successful in 13s
Desktop Build / build-windows (push) Has been cancelled
Desktop Build / build-linux (push) Has been cancelled
- Backend: ajout .excalidraw dans SUPPORTED_EXTENSIONS + squelette JSON creation - Backend: détection is_excalidraw dans api_file() + FileContentResponse - Frontend: icône pen-tool dans EXT_ICONS - Frontend: ajout dans la modale de création (ui.js) - Frontend: excalidraw-editor.html (iframe autonome, React+Excalidraw via esm.sh) - Frontend: excalidraw-viewer.js (postMessage, auto-save 2s, thème) - Frontend: dispatch dans viewer.js (renderFile) - Tests: 6 tests (détection, création squelette, fallback, tree, roundtrip) - 359/359 tests passent
This commit is contained in:
@@ -63,6 +63,7 @@ SUPPORTED_EXTENSIONS = {
|
||||
".java", ".c", ".cpp", ".h", ".hpp", ".cs", ".go", ".rs", ".rb",
|
||||
".php", ".sql", ".r", ".m", ".swift", ".kt",
|
||||
".dockerfile", ".makefile", ".cmake",
|
||||
".excalidraw",
|
||||
}
|
||||
|
||||
|
||||
|
||||
+44
-1
@@ -118,6 +118,15 @@ class FileContentResponse(BaseModel):
|
||||
is_markdown: bool = Field(description="Whether the file is markdown")
|
||||
unsupported: bool | None = Field(default=False, description="True for binary/unsupported files")
|
||||
size_bytes: int | None = Field(default=None, description="File size in bytes (for unsupported files)")
|
||||
is_pdf: bool | None = Field(default=None, description="True for PDF files")
|
||||
is_image: bool | None = Field(default=None, description="True for image files")
|
||||
is_csv: bool | None = Field(default=None, description="True for CSV files")
|
||||
is_json: bool | None = Field(default=None, description="True for JSON files")
|
||||
is_excalidraw: bool | None = Field(default=None, description="True for Excalidraw diagram files")
|
||||
excalidraw_data: dict[str, Any] | None = Field(default=None, description="Excalidraw diagram data (elements, appState, files)")
|
||||
pdf_metadata: dict[str, Any] | None = Field(default=None, description="PDF metadata")
|
||||
pdf_toc: list[dict[str, Any]] | None = Field(default=None, description="PDF table of contents")
|
||||
image_mime: str | None = Field(default=None, description="MIME type for image files")
|
||||
|
||||
|
||||
class FileRawResponse(BaseModel):
|
||||
@@ -1793,8 +1802,13 @@ async def api_file_create(
|
||||
# Create parent directories if needed
|
||||
file_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# For .excalidraw files, inject skeleton JSON if content is empty
|
||||
content = body.content
|
||||
if ext == ".excalidraw" and not content.strip():
|
||||
content = '{"type":"excalidraw","version":2,"elements":[],"appState":{"viewBackgroundColor":"#ffffff"},"files":{}}'
|
||||
|
||||
# Create file with initial content
|
||||
file_path.write_text(body.content, encoding="utf-8")
|
||||
file_path.write_text(content, encoding="utf-8")
|
||||
logger.info(f"File created: {vault_name}/{body.path}")
|
||||
|
||||
# Update index
|
||||
@@ -2489,6 +2503,35 @@ async def api_file(vault_name: str, path: str = Query(..., description="Relative
|
||||
"is_markdown": False, "is_json": True,
|
||||
}
|
||||
|
||||
# === Excalidraw: diagram editor ===
|
||||
if ext == ".excalidraw":
|
||||
import json as json_mod
|
||||
try:
|
||||
parsed = json_mod.loads(raw)
|
||||
except json_mod.JSONDecodeError:
|
||||
parsed = None
|
||||
if parsed and parsed.get("type") == "excalidraw":
|
||||
return {
|
||||
"vault": vault_name,
|
||||
"path": path,
|
||||
"title": parsed.get("appState", {}).get("name") or file_path.name,
|
||||
"tags": [],
|
||||
"frontmatter": {},
|
||||
"html": "",
|
||||
"raw_length": len(raw),
|
||||
"extension": ext,
|
||||
"is_markdown": False,
|
||||
"is_excalidraw": True,
|
||||
"excalidraw_data": {
|
||||
"elements": parsed.get("elements", []),
|
||||
"appState": parsed.get("appState", {}),
|
||||
"files": parsed.get("files", {}),
|
||||
},
|
||||
}
|
||||
else:
|
||||
# Not a valid Excalidraw file — fall through to text viewer
|
||||
pass
|
||||
|
||||
# === Plain text / other readable files ===
|
||||
TEXT_EXTENSIONS = {".txt", ".log", ".yml", ".yaml", ".toml", ".ini", ".cfg",
|
||||
".sh", ".bash", ".py", ".js", ".ts", ".html", ".css",
|
||||
|
||||
Reference in New Issue
Block a user