editor first pass
This commit is contained in:
+80
-9
@@ -7,19 +7,27 @@ Serves editor/client/public/ as static files with smart routing:
|
||||
/index -> index.html
|
||||
|
||||
API endpoints (all paths relative to project root):
|
||||
GET /api/ls?path=<dir> directory listing
|
||||
GET /api/read?path=<file> file contents
|
||||
POST /api/write?path=<file> write file (JSON body: {"content":"..."})
|
||||
POST /api/mkdir?path=<dir> create directory
|
||||
GET /api/ls?path=<dir> directory listing
|
||||
GET /api/read?path=<file> file contents
|
||||
GET /api/find?path=<dir>&ext=<.json> recursive file listing by extension
|
||||
POST /api/write?path=<file> write file (JSON body: {"content":"..."})
|
||||
POST /api/mkdir?path=<dir> create directory
|
||||
POST /api/delete?path=<file> delete a file
|
||||
POST /api/compile-chunk?x=&y=&z= recompile a chunk JSON to .dcf
|
||||
"""
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import json
|
||||
import mimetypes
|
||||
import subprocess
|
||||
from http.server import HTTPServer, BaseHTTPRequestHandler
|
||||
from urllib.parse import urlparse, parse_qs, unquote
|
||||
from pathlib import Path
|
||||
|
||||
CHUNK_COORD_RE = re.compile(r"^-?\d+$")
|
||||
|
||||
PORT = 3000
|
||||
SCRIPT_DIR = Path(__file__).parent.resolve()
|
||||
PUBLIC_DIR = SCRIPT_DIR.parent / "client" / "public"
|
||||
@@ -36,6 +44,8 @@ class Handler(BaseHTTPRequestHandler):
|
||||
self.api_ls(params)
|
||||
elif path == "/api/read":
|
||||
self.api_read(params)
|
||||
elif path == "/api/find":
|
||||
self.api_find(params)
|
||||
else:
|
||||
self.send_error(404)
|
||||
else:
|
||||
@@ -48,6 +58,10 @@ class Handler(BaseHTTPRequestHandler):
|
||||
self.api_write(params)
|
||||
elif parsed.path == "/api/mkdir":
|
||||
self.api_mkdir(params)
|
||||
elif parsed.path == "/api/delete":
|
||||
self.api_delete(params)
|
||||
elif parsed.path == "/api/compile-chunk":
|
||||
self.api_compile_chunk(params)
|
||||
else:
|
||||
self.send_error(404)
|
||||
|
||||
@@ -158,6 +172,61 @@ class Handler(BaseHTTPRequestHandler):
|
||||
target.mkdir(parents=True, exist_ok=True)
|
||||
self.send_json({"ok": True, "path": str(target.relative_to(PROJECT_ROOT))})
|
||||
|
||||
def api_delete(self, params):
|
||||
rel = params.get("path", [""])[0]
|
||||
target = self.resolve_project_path(rel)
|
||||
if target is None:
|
||||
self.send_json({"error": "invalid path"}, 400)
|
||||
return
|
||||
if target.is_file():
|
||||
target.unlink()
|
||||
self.send_json({"ok": True, "path": str(target.relative_to(PROJECT_ROOT))})
|
||||
|
||||
def api_find(self, params):
|
||||
rel = params.get("path", [""])[0]
|
||||
ext = params.get("ext", [""])[0]
|
||||
target = self.resolve_project_path(rel)
|
||||
if target is None:
|
||||
self.send_json({"error": "invalid path"}, 400)
|
||||
return
|
||||
if not target.is_dir():
|
||||
self.send_json({"error": "not a directory"}, 400)
|
||||
return
|
||||
|
||||
pattern = f"*{ext}" if ext else "*"
|
||||
paths = sorted(
|
||||
str(p.relative_to(target)).replace(os.sep, "/")
|
||||
for p in target.rglob(pattern)
|
||||
if p.is_file()
|
||||
)
|
||||
self.send_json({"path": str(target.relative_to(PROJECT_ROOT)), "files": paths})
|
||||
|
||||
def api_compile_chunk(self, params):
|
||||
x = params.get("x", [""])[0]
|
||||
y = params.get("y", [""])[0]
|
||||
z = params.get("z", [""])[0]
|
||||
if not (CHUNK_COORD_RE.match(x) and CHUNK_COORD_RE.match(y) and CHUNK_COORD_RE.match(z)):
|
||||
self.send_json({"error": "invalid chunk coordinates"}, 400)
|
||||
return
|
||||
|
||||
json_path = PROJECT_ROOT / "assetsraw" / "chunks" / f"chunk_{x}_{y}_{z}.json"
|
||||
if not json_path.is_file():
|
||||
self.send_json({"error": "chunk json not found"}, 404)
|
||||
return
|
||||
|
||||
result = subprocess.run(
|
||||
[sys.executable, "-m", "tools.asset.chunk", str(json_path)],
|
||||
cwd=str(PROJECT_ROOT),
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
self.send_json({
|
||||
"ok": result.returncode == 0,
|
||||
"returncode": result.returncode,
|
||||
"stdout": result.stdout,
|
||||
"stderr": result.stderr,
|
||||
})
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Static file serving
|
||||
# ------------------------------------------------------------------
|
||||
@@ -194,11 +263,13 @@ class Handler(BaseHTTPRequestHandler):
|
||||
):
|
||||
fragment = file_path.read_text(encoding="utf-8")
|
||||
shell = template.read_text(encoding="utf-8")
|
||||
content = shell.replace(
|
||||
'<div id="editor"></div>',
|
||||
f'<div id="editor">{fragment}</div>',
|
||||
1,
|
||||
).encode("utf-8")
|
||||
marker = shell.find('id="editor"')
|
||||
if marker == -1:
|
||||
content = shell.encode("utf-8")
|
||||
else:
|
||||
tag_end = shell.index(">", marker) + 1
|
||||
close_idx = shell.index("</div>", tag_end)
|
||||
content = (shell[:tag_end] + fragment + shell[close_idx:]).encode("utf-8")
|
||||
else:
|
||||
content = file_path.read_bytes()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user