From 73fc38b7ad358f36ecc01a22f6a005a89974264b Mon Sep 17 00:00:00 2001 From: Peter Harpending Date: Tue, 21 Oct 2025 22:20:24 -0700 Subject: [PATCH] begin static file caching --- priv/static/chat.html | 100 ++++++++++++++++++++++++ priv/static/default.css | 95 +++++++++++++++++++++++ priv/static/index.html | 138 ++++++++++++++++++++++++++++++++++ priv/static/scratch.txt | 56 ++++++++++++++ priv/static/ws-test-echo.html | 65 ++++++++++++++++ src/fd_static_cache.erl | 120 +++++++++++++++++++++++++++++ 6 files changed, 574 insertions(+) create mode 100644 priv/static/chat.html create mode 100644 priv/static/default.css create mode 100644 priv/static/index.html create mode 100644 priv/static/scratch.txt create mode 100644 priv/static/ws-test-echo.html create mode 100644 src/fd_static_cache.erl diff --git a/priv/static/chat.html b/priv/static/chat.html new file mode 100644 index 0000000..895393b --- /dev/null +++ b/priv/static/chat.html @@ -0,0 +1,100 @@ + + + + + Chat with Websockets + + + +
+

Chat with websockets

+ +
+ + + +
+
+ + + + diff --git a/priv/static/default.css b/priv/static/default.css new file mode 100644 index 0000000..d7f1ad5 --- /dev/null +++ b/priv/static/default.css @@ -0,0 +1,95 @@ +/* color pallette */ +* { + --white: #f7f8fb; + --lgray0: #f5fbfd; + --lgray1: #daddd6; + --lgray2: #d3d8d5; + --mgray1: #687864; + --dgreen1: #21341e; + --lgreen1: #e5eef2; + --black: #003d27; + + --sans: Helvetica, Liberation Sans, FreeSans, Roboto, sans-serif; + --mono: Liberation Mono, FreeMono, Roboto Mono, monospace; + --fsdef: 12pt; +} + +/* body */ +body { + background: var(--white); + color: var(--dgray1); + font-size: var(--fsdef); + font-family: var(--sans); + margin: 0; + padding: 0; + line-height: 1.4; +} + + +.content { + max-width: 800px; + margin: 0 auto; + /* + background: #ff0; + */ +} + + +/* add some top padding to content */ + +.content-title { + text-align: center; + text-decoration: underline; +} + +.content-body { + width: 100%; + margin: 0 auto; + /* + background: #f00; + */ + + + padding-left: 10px; + padding-right: 10px; + + box-sizing: border-box; +} + +/* element-specific styling */ + +a { + color: var(--mgray1); +} + + +#wfc-input { + font-family: var(--mono); + font-size: var(--fsdef); + background: var(--lgreen1); + + width: 100%; + + box-sizing: border-box; + + border-radius: 6px; + border: 1px solid var(--lgray1); + + padding: 5px; +} + +#wfc-output { + background: var(--lgray0); + font-family: var(--mono); + font-size: var(--fsdef); + + width: 100%; + resize: vertical; + + box-sizing: border-box; + + border-radius: 6px; + border: 1px solid var(--lgray1); + + padding: 5px; +} diff --git a/priv/static/index.html b/priv/static/index.html new file mode 100644 index 0000000..6c1b6d7 --- /dev/null +++ b/priv/static/index.html @@ -0,0 +1,138 @@ + + + + + WF Compiler Demo + + + +
+

WFC Demo

+ + + +
+ + + +

Settings

+ Auto-resize output
+ Auto-scroll output to bottom +
+
+ + + + diff --git a/priv/static/scratch.txt b/priv/static/scratch.txt new file mode 100644 index 0000000..db3b7c7 --- /dev/null +++ b/priv/static/scratch.txt @@ -0,0 +1,56 @@ + /* header */ + div#header { + background: var(--lgray2); + height: 50px; + width: 100%; + } + + img#header-logo { + height: 40px; + margin-top: 5px; + margin-bottom: 5px; + margin-left: 5px; + } + + +.main { + padding-top: 20px; +} + +.content-diagram { + max-width: 100%; + margin: 0 auto; + padding: 0 auto; +} + + +/* Pandoc makes some wacky choices with how it lays out code blocks + * + * this means all blocks that do not have a
 block as an ancestor
+ *
+ * ie the `inline code`
+ */
+code:not(pre *) {
+    border-radius:  6px;
+    border:         1px solid var(--lgray1);
+    padding-left:   3px;
+    padding-right:  3px;
+    padding-top:    1px;
+    padding-bottom: 1px;
+    background:     var(--lgreen1);
+}
+
+/* this is specifically for ```fenced blocks``` */
+pre {
+    border-radius:  6px;
+    border:         1px solid var(--lgray1);
+    padding:        5px;
+    background:     var(--lgreen1);
+    overflow:       scroll;
+}
+
+/* All `unfenced` or ```fenced``` blocks */
+code {
+    font-family:    Liberation Mono, Roboto Mono, monospace;
+    color:          var(--dgreen1);
+}
diff --git a/priv/static/ws-test-echo.html b/priv/static/ws-test-echo.html
new file mode 100644
index 0000000..2c3d47d
--- /dev/null
+++ b/priv/static/ws-test-echo.html
@@ -0,0 +1,65 @@
+
+
+
+    
+    Websockets echo test
+    
+
+
+    
+

Websockets echo test

+ +
+ + +
+
+ + + + diff --git a/src/fd_static_cache.erl b/src/fd_static_cache.erl new file mode 100644 index 0000000..472f705 --- /dev/null +++ b/src/fd_static_cache.erl @@ -0,0 +1,120 @@ +% @doc static file cache +-module(fd_static_cache). + +-behavior(gen_server). + +-export([ + start_link/0, + query/1, set/2, unset/1, + %%--- + %% everything below here runs in process context + %%-- + %% gen_server callbacks + init/1, handle_call/3, handle_cast/2, handle_info/2, + code_change/3, terminate/2 +]). + +-include("$zx_include/zx_logger.hrl"). + +-type context() :: wfc_eval_context:context(). + +-record(s, + {cookies = #{} :: #{Cookie :: binary() := context()}}). +% -type state() :: #s{}. + + +%%-------------------------------- +%% api (runs in context of caller) +%%-------------------------------- + +-spec start_link() -> {ok, pid()} | {error, term()}. +start_link() -> + gen_server:start_link({local, ?MODULE}, ?MODULE, none, []). + + + +-spec query(Cookie) -> {ok, Context} | error + when Cookie :: binary(), + Context :: context(). + +query(Cookie) -> + gen_server:call(?MODULE, {query, Cookie}). + + + +-spec set(Cookie, Context) -> ok + when Cookie :: binary(), + Context :: context(). + +set(Cookie, Context) -> + gen_server:cast(?MODULE, {set, Cookie, Context}). + + +-spec unset(Cookie) -> ok + when Cookie :: binary(). + +unset(Cookie) -> + gen_server:cast(?MODULE, {unset, Cookie}). + + +%%---------------------- +%% gen-server bs +%%---------------------- + + + +init(none) -> + log(info, "starting fd_cache"), + InitState = #s{}, + {ok, InitState}. + + +handle_call({query, Cookie}, _, State) -> + Result = do_query(Cookie, State), + {reply, Result, State}; +handle_call(Unexpected, From, State) -> + tell("~tp: unexpected call from ~tp: ~tp", [?MODULE, Unexpected, From]), + {noreply, State}. + + +handle_cast({set, Cookie, Context}, State) -> + NewState = do_set(Cookie, Context, State), + {noreply, NewState}; +handle_cast({unset, Cookie}, State) -> + NewState = do_unset(Cookie, State), + {noreply, NewState}; +handle_cast(Unexpected, State) -> + tell("~tp: unexpected cast: ~tp", [?MODULE, Unexpected]), + {noreply, State}. + + +handle_info(Unexpected, State) -> + tell("~tp: unexpected info: ~tp", [?MODULE, Unexpected]), + {noreply, State}. + + +code_change(_, State, _) -> + {ok, State}. + +terminate(_, _) -> + ok. + + +%%--------------------- +%% doers +%%--------------------- + +do_set(Cookie, Context, State = #s{cookies = Cookies}) -> + NewCookies = maps:put(Cookie, Context, Cookies), + NewState = State#s{cookies = NewCookies}, + NewState. + + +do_unset(Cookie, State = #s{cookies = Cookies}) -> + NewCookies = maps:remove(Cookie, Cookies), + NewState = State#s{cookies = NewCookies}, + NewState. + + +do_query(Cookie, _State = #s{cookies = Cookies}) -> + maps:find(Cookie, Cookies).