Add native SX desktop browser — renders s-expressions to pixels
A 5.9MB OCaml binary that renders SX pages directly using SDL2 + Cairo, bypassing HTML/CSS/JS entirely. Can fetch live pages from sx.rose-ash.com or render local .sx files. Architecture (1,387 lines of new code): sx_native_types.ml — render nodes, styles, layout boxes, color palette sx_native_style.ml — ~40 Tailwind classes → native style records sx_native_layout.ml — pure OCaml flexbox (measure + position) sx_native_render.ml — SX value tree → native render nodes sx_native_paint.ml — render nodes → Cairo draw commands sx_native_fetch.ml — HTTP fetch via curl with SX-Request headers sx_native_app.ml — SDL2 window, event loop, navigation, scrolling Usage: dune build # from hosts/native/ ./sx_native_app.exe /sx/ # browse sx.rose-ash.com home ./sx_native_app.exe /sx/(applications.(native-browser)) ./sx_native_app.exe demo/counter.sx # render local file Features: - Flexbox layout (row/column, gap, padding, alignment, grow) - Tailwind color palette (stone, violet, white) - Rounded corners, borders, shadows - Text rendering with font size/weight - Click navigation (links trigger refetch) - Scroll with mouse wheel - Window resize → re-layout - URL bar showing current path Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
37
hosts/native/lib/sx_native_fetch.ml
Normal file
37
hosts/native/lib/sx_native_fetch.ml
Normal file
@@ -0,0 +1,37 @@
|
||||
(** HTTP fetcher for SX pages.
|
||||
|
||||
Uses curl via Unix.open_process_in for simplicity.
|
||||
Fetches pages from sx.rose-ash.com with SX-Request headers. *)
|
||||
|
||||
let base_url = "https://sx.rose-ash.com"
|
||||
|
||||
(** Fetch a URL and return the response body as a string. *)
|
||||
let fetch_url (url : string) : string =
|
||||
let cmd = Printf.sprintf
|
||||
"curl -s -L -H 'Accept: text/sx' -H 'SX-Request: true' '%s'" url in
|
||||
let ic = Unix.open_process_in cmd in
|
||||
let buf = Buffer.create 8192 in
|
||||
(try while true do Buffer.add_char buf (input_char ic) done
|
||||
with End_of_file -> ());
|
||||
ignore (Unix.close_process_in ic);
|
||||
Buffer.contents buf
|
||||
|
||||
(** Fetch an SX page by path (e.g. "/sx/" or "/sx/language"). *)
|
||||
let fetch_page (path : string) : string =
|
||||
let url = if String.length path > 0 && path.[0] = '/' then
|
||||
base_url ^ path
|
||||
else if String.length path > 4 && String.sub path 0 4 = "http" then
|
||||
path
|
||||
else
|
||||
base_url ^ "/" ^ path
|
||||
in
|
||||
fetch_url url
|
||||
|
||||
(** Read a local .sx file. *)
|
||||
let read_file (path : string) : string =
|
||||
let ic = open_in path in
|
||||
let n = in_channel_length ic in
|
||||
let buf = Bytes.create n in
|
||||
really_input ic buf 0 n;
|
||||
close_in ic;
|
||||
Bytes.to_string buf
|
||||
Reference in New Issue
Block a user