Hyperscript: focus command, diagnostic test output, blur keyword
Parser/compiler/runtime for focus command. Tokenizer: focus, blur, precedes, follows, ignoring, case keywords. Test spec: per-test failure output for diagnosis. 374/831 (45%) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1838,6 +1838,47 @@ let parse_http_headers data =
|
||||
) (match lines with _ :: rest -> rest | [] -> []);
|
||||
!headers
|
||||
|
||||
(* IO-aware eval for rendering — handles perform (text-measure, sleep, import).
|
||||
Used by aser and SSR so components can call measure-text via perform. *)
|
||||
let eval_with_io_render expr env =
|
||||
let state = ref (Sx_ref.cek_step_loop (Sx_ref.make_cek_state expr (Env env) Nil)) in
|
||||
while sx_truthy (Sx_ref.cek_suspended_p !state) do
|
||||
let request = Sx_ref.cek_io_request !state in
|
||||
let op = match request with
|
||||
| Dict d -> (match Hashtbl.find_opt d "op" with Some (String s) -> s | Some (Symbol s) -> s | _ -> "")
|
||||
| _ -> "" in
|
||||
let args = match request with
|
||||
| Dict d -> (match Hashtbl.find_opt d "args" with Some v -> v | None -> Nil)
|
||||
| _ -> Nil in
|
||||
let result = match op with
|
||||
| "text-measure" ->
|
||||
let size = match args with
|
||||
| List [_font; Number sz; _text] -> sz
|
||||
| List [_font; Number sz] -> sz
|
||||
| _ -> 16.0 in
|
||||
let text = match args with
|
||||
| List [_font; _sz; String t] -> t
|
||||
| _ -> "" in
|
||||
let char_width = size *. 0.6 in
|
||||
let width = char_width *. (float_of_int (String.length text)) in
|
||||
let d = Hashtbl.create 4 in
|
||||
Hashtbl.replace d "width" (Number width);
|
||||
Hashtbl.replace d "height" (Number size);
|
||||
Hashtbl.replace d "ascent" (Number (size *. 0.8));
|
||||
Hashtbl.replace d "descent" (Number (size *. 0.2));
|
||||
Dict d
|
||||
| "io-sleep" | "sleep" ->
|
||||
let ms = match args with
|
||||
| List (Number n :: _) -> n | Number n -> n | _ -> 0.0 in
|
||||
Unix.sleepf (ms /. 1000.0); Nil
|
||||
| "import" -> Nil
|
||||
| _ -> Nil
|
||||
in
|
||||
state := Sx_ref.cek_step_loop (Sx_ref.cek_resume !state result)
|
||||
done;
|
||||
if sx_truthy (Sx_ref.cek_terminal_p !state) then Sx_ref.cek_value !state
|
||||
else Nil
|
||||
|
||||
(** Render a page. Routing + AJAX detection in SX (request-handler.sx),
|
||||
render pipeline (aser → SSR → shell) in OCaml for reliable env access. *)
|
||||
let http_render_page env path headers =
|
||||
@@ -1889,7 +1930,7 @@ let http_render_page env path headers =
|
||||
(* AJAX: return SX wire format (aser output) with text/sx content type *)
|
||||
let body_result =
|
||||
let call = List [Symbol "aser"; List [Symbol "quote"; wrapped]; Env env] in
|
||||
Sx_ref.eval_expr call (Env env) in
|
||||
eval_with_io_render call env in
|
||||
let body_str = match body_result with
|
||||
| String s | SxExpr s -> s | _ -> serialize_value body_result in
|
||||
let t1 = Unix.gettimeofday () in
|
||||
@@ -1903,7 +1944,7 @@ let http_render_page env path headers =
|
||||
let t1 = Unix.gettimeofday () in
|
||||
let body_result =
|
||||
let call = List [Symbol "aser"; List [Symbol "quote"; full_ast]; Env env] in
|
||||
Sx_ref.eval_expr call (Env env) in
|
||||
eval_with_io_render call env in
|
||||
let body_str = match body_result with
|
||||
| String s | SxExpr s -> s | _ -> serialize_value body_result in
|
||||
let t2 = Unix.gettimeofday () in
|
||||
@@ -1913,7 +1954,7 @@ let http_render_page env path headers =
|
||||
if env_has env "render-to-html" then
|
||||
let render_call = List [Symbol "render-to-html";
|
||||
List [Symbol "quote"; body_expr]; Env env] in
|
||||
(match Sx_ref.eval_expr render_call (Env env) with
|
||||
(match eval_with_io_render render_call env with
|
||||
| String s | RawHTML s -> s | v -> Sx_runtime.value_to_str v)
|
||||
else Sx_render.sx_render_to_html env body_expr env
|
||||
with e -> Printf.eprintf "[http-ssr] failed for %s: %s\n%!" path (Printexc.to_string e); "" in
|
||||
|
||||
Reference in New Issue
Block a user