commit 0bcb945484402054d96b88d414fdf8321ab1e8ce
parent dcf547b4e169d852acba76b3ab915dec16a05d04
Author: Andrew Laack <andrew@laack.co>
Date: Thu, 27 Aug 2026 15:14:32 -0500
Refactoring and stuff
Diffstat:
9 files changed, 60 insertions(+), 80 deletions(-)
diff --git a/courses/haskell/0_haskell.rl b/courses/haskell/0_haskell.sl
diff --git a/courses/haskell/1_haskell.rl b/courses/haskell/1_haskell.sl
diff --git a/courses/ocaml/0_ocaml.rl b/courses/ocaml/0_ocaml.sl
diff --git a/courses/ocaml/1_ocaml.rl b/courses/ocaml/1_ocaml.sl
diff --git a/learning/bin/main.ml b/learning/bin/main.ml
@@ -2,7 +2,36 @@ open Jingoo
let course_dir = "../courses/"
-let readFile fileName =
+let countPrefix char data =
+ let rec go idx =
+ if String.length data > idx && data.[idx] = char
+ then
+ go (idx + 1)
+ else idx
+ in go 0
+
+
+type page_line = {
+ header_level: int;
+ content: string;
+}
+
+let parse_simple_line line =
+ let hash_count = countPrefix '#' line in
+ {header_level = hash_count; content = line}
+
+let read_simple_learning_file fileName =
+ let ic = open_in fileName in
+ let rec readAll () =
+ try
+ let current_line = parse_simple_line (input_line ic) in
+ current_line :: readAll ();
+ with End_of_file ->
+ close_in_noerr ic;
+ []
+ in readAll ()
+
+let readFile fileName =
let ic = open_in fileName in
let rec readAll acc =
try
@@ -19,6 +48,8 @@ let remove_file_extension file_name =
let to_tval value =
Jg_types.Tobj [("name", Jg_types.Tstr value);]
+let page_line_to_tobj line =
+ Jg_types.Tobj [("header_level", Jg_types.Tint line.header_level); ("content", Jg_types.Tstr line.content)]
let get_courses =
let arr = Sys.readdir course_dir in
@@ -47,19 +78,25 @@ let arr_to_string arr =
else go (acc ^ arr.(idx)) (idx + 1)
in go "" 0
-
-
let get_course_home course_name =
Array.map to_tval (get_pages_in_order course_name)
let render_course_home course_name =
(Jg_template.from_file "./templates/course_home.jingoo" ~models:[("pages", (Jg_types.Tlist (Array.to_list (get_course_home course_name))))])
+let get_path_to_page course page =
+ course_dir ^ course ^ "/" ^ page
+
+let render_page course page =
+ let page_lines = read_simple_learning_file @@ get_path_to_page course page in
+ (Jg_template.from_file "./templates/course_page.jingoo" ~models:(["lines", Jg_types.Tlist (List.map page_line_to_tobj page_lines)]))
+
let () =
Dream.run
@@ Dream.logger
@@ Dream.router [
- Dream.get "/course/:id/" (fun request -> Dream.html (render_course_home (Dream.param request "id")));
+ Dream.get "/course/:course_name/" (fun request -> Dream.html (render_course_home (Dream.param request "course_name")));
+ Dream.get "/course/:course_name/page/:page_name" (fun request -> Dream.html @@ render_page (Dream.param request "course_name") (Dream.param request "page_name"));
Dream.get "/static/**" (Dream.static "./static");
Dream.get "/" (fun _ -> Dream.html render_course_list)
]
diff --git a/learning/static/styles.css b/learning/static/styles.css
@@ -27,7 +27,7 @@ h6 {
content-block {
display: block;
- color: #000000;
+ color: #222222;
}
.sidenav {
diff --git a/learning/templates/course_page.jingoo b/learning/templates/course_page.jingoo
@@ -0,0 +1,18 @@
+<link rel="stylesheet" href="/static/styles.css" type="text/css">
+<div class="sidenav">
+ <a href="/">Home</a>
+ <a href="">Services</a>
+ <a href="">Clients</a>
+ <a href="">Contact</a>
+</div>
+
+<div class="main">
+ {% for line in lines %}
+ {% if line.header_level >= 1 %}
+ <h{{line.header_level}}>{{line.content}}</h{{line.header_level}}>
+ {% endif %}
+ {% if line.header_level == 0 %}
+ <content-block>{{line.content}}</content-block>
+ {% endif %}
+ {% endfor %}
+</div>
diff --git a/outputs/out.html b/outputs/out.html
@@ -1,36 +0,0 @@
-<link rel="stylesheet" href="styles.css" type="text/css">
-<div class="sidenav">
- <a href="#">About</a>
- <a href="#">Services</a>
- <a href="#">Clients</a>
- <a href="#">Contact</a>
-</div>
-
-<div class="main">
-<h1># OCaml</h1>
-<content-block></content-block>
-<h2>## History</h2>
-<content-block></content-block>
-<content-block>OCaml is the acronym for Objective Categorical Abstract Machine Language. </content-block>
-<content-block></content-block>
-<h2>## Syntax</h2>
-<content-block></content-block>
-<content-block>In OCaml we use the 'let' keyword to bind a expressions to names (variables). Shown below is an example of this:</content-block>
-<content-block></content-block>
-<content-block>```ocaml</content-block>
-<content-block>let x = 10</content-block>
-<content-block>```</content-block>
-
-<content-block></content-block>
-<content-block>```ocaml</content-block>
-<content-block>let x = 10</content-block>
-<content-block>```</content-block>
-<content-block></content-block>
-<content-block>```ocaml</content-block>
-<content-block>let x = 10</content-block>
-<content-block>```</content-block>
-<content-block></content-block>
-<content-block>```ocaml</content-block>
-<content-block>let x = 10</content-block>
-<content-block>```</content-block>
-</div>
diff --git a/outputs/styles.css b/outputs/styles.css
@@ -1,39 +0,0 @@
-body {
- font-family: Arial, sans-serif;
- background-color: #f3f6f9;
- margin: 0;
-}
-h1 {
- color: #000000;
-}
-
-content-block {
- background-color: #f6f9fB;
- display: block;
-}
-
-.sidenav {
- height: 100%; /* Full-height: remove this if you want "auto" height */
- width: 160px; /* Set the width of the sidebar */
- position: fixed; /* Fixed Sidebar (stay in place on scroll) */
- z-index: 1; /* Stay on top */
- top: 0; /* Stay at the top */
- left: 0;
- background-color: #111; /* Black */
- overflow-x: hidden; /* Disable horizontal scroll */
- padding-top: 20px;
-}
-
-/* The navigation menu links */
-.sidenav a {
- padding: 6px 8px 6px 16px;
- text-decoration: none;
- font-size: 25px;
- color: #A18181;
- display: block;
-}
-
-.main {
- margin-left: 160px; /* Same as the width of the sidebar */
- padding: 0px 10px;
-}