simple-learning

Simple learning web program
git clone git://git.laack.co/simple-learning.git
Log | Files | Refs | README | LICENSE

commit 9ca143d06a06f9092ca102a7fa2f1543f356f75a
parent 700f5afe39e8adc6954e08a84df07c1313e5c21d
Author: Andrew Laack <andrew@laack.co>
Date:   Wed,  2 Sep 2026 12:58:48 -0500

Convert data fetching ops into functions.

Diffstat:
Alearning/Containerfile | 17+++++++++++++++++
Alearning/Dockerfile | 2++
Mlearning/lib/render.ml | 34+++++++++++++++++++---------------
Mlearning/lib/server.ml | 14++++----------
Mlearning/lib/shared.ml | 7+++++++
5 files changed, 49 insertions(+), 25 deletions(-)

diff --git a/learning/Containerfile b/learning/Containerfile @@ -0,0 +1,17 @@ +FROM ocaml/opam:ubuntu-25.04-ocaml-5.5 + +RUN sudo mkdir /app + +RUN sudo apt-get update && sudo apt-get install -y libev-dev libgmp-dev + +COPY . /app + +WORKDIR /app + +RUN opam update && opam install --deps-only -y . && opam install dune + +RUN sudo chown -R opam /app + +RUN /home/opam/.opam/5.5/bin/dune build + +ENTRYPOINT ["/home/opam/.opam/5.5/bin/dune" "exec" "learning"] diff --git a/learning/Dockerfile b/learning/Dockerfile @@ -0,0 +1 @@ +Containerfile+ \ No newline at end of file diff --git a/learning/lib/render.ml b/learning/lib/render.ml @@ -3,32 +3,36 @@ open Jingoo let to_tval value = Jg_types.Tobj [ ("name", Jg_types.Tstr value) ] let get_pages_in_order course_name = - let arr = Sys.readdir (Shared.course_dir ^ course_name) in - Array.sort compare arr; - let lst : string list = - List.filter Basic_functions.has_sl_postfix (Array.to_list arr) - in - lst + if Shared.is_directory (Shared.course_dir ^ course_name) then + let arr = Sys.readdir (Shared.course_dir ^ course_name) in + Array.sort compare arr; + let lst : string list = + List.filter Basic_functions.has_sl_postfix (Array.to_list arr) + in + lst + else [] let get_course_home course_name = List.map to_tval (get_pages_in_order course_name) -let get_course_array = - let arr = Sys.readdir Shared.course_dir in - Array.sort compare arr; - arr +let get_course_array () = + if Shared.is_directory (Shared.course_dir) then + let arr = Sys.readdir Shared.course_dir in + Array.sort compare arr; + arr + else Array.make 0 "" -let get_courses = - let arr = get_course_array in +let get_courses () = + let arr = get_course_array () in Jg_types.Tlist (Array.to_list (Array.map to_tval arr)) -let render_course_list = +let render_course_list () = Jg_template.from_string Templates.course_list_jingoo - ~models:[ ("courses", get_courses) ] + ~models:[ ("courses", get_courses ()) ] let render_sidebar s = Jg_template.from_string Templates.sidebar_jingoo - ~models:[ ("courses", get_courses) ] + ~models:[ ("courses", get_courses ()) ] ^ s let page_line_to_tobj (line : Parser.page_line) = diff --git a/learning/lib/server.ml b/learning/lib/server.ml @@ -1,12 +1,6 @@ (* TODO: Make this a whitelist based on the page / course lists *) (* TODO: Favicon *) -let is_file filename = if Sys.file_exists filename then true else false - -let is_directory path = - if Sys.file_exists path then if Sys.is_directory path then true else false - else false - let is_safe_path name = String.length name > 0 && name <> "." && name <> ".." @@ -43,11 +37,11 @@ let get_page_name request = Dream.param request "page_name" let is_valid_course name = let pth = Shared.course_dir ^ name in - is_safe_path name && is_directory pth + is_safe_path name && Shared.is_directory pth let is_valid_page course_name page_name = let pth = Shared.course_dir ^ course_name ^ "/" ^ page_name in - is_safe_path course_name && is_safe_path page_name && is_file pth + is_safe_path course_name && is_safe_path page_name && Shared.is_file pth let routes = [ @@ -66,8 +60,8 @@ let routes = else Dream.empty `Not_Found else Dream.empty `Not_Found); Dream.get "/static/**" (Dream.static "./static"); - Dream.get "/" (fun _ -> - Dream.html (Render.render_sidebar @@ Render.render_course_list)); + Dream.get "/" (fun request -> + Dream.html (Render.render_sidebar @@ Render.render_course_list ())); Dream.get "/robots.txt" (Dream.from_filesystem "./static" "robots.txt"); Dream.get "/course/:course_name/page/assets/**" (fun request -> let name = get_course_name request in diff --git a/learning/lib/shared.ml b/learning/lib/shared.ml @@ -1,3 +1,10 @@ (* ALWAYS pass in directory to watch. Fallback should only be for tests. *) let course_dir = if Array.length Sys.argv > 1 then Sys.argv.(1) ^ "/" else "./test_courses/" + + +let is_file filename = if Sys.file_exists filename then true else false + +let is_directory path = + if Sys.file_exists path then if Sys.is_directory path then true else false + else false