commit 084c599ff5f7e057c367b9fa6c0f615cd599d1af
parent 2bec5677a4b7c1fbbc1d1ec291cba39502e69985
Author: Andrew Laack <andrew@laack.co>
Date: Fri, 28 Aug 2026 20:36:08 -0500
Refactor to use line_format enum to describe the format of a given line, removing complex boolean unstructured structure.
Diffstat:
4 files changed, 77 insertions(+), 44 deletions(-)
diff --git a/learning/bin/parser.ml b/learning/bin/parser.ml
@@ -1,21 +1,44 @@
+
+(* TODO: These should be doing prefix matching...*)
+
+type line_format =
+ | Normal
+ | HeaderL1
+ | HeaderL2
+ | HeaderL3
+ | Embedded
+ | Preformatted
+ | Hidden
+ | Quote
+ | Link
+ | ListItem
+
+let line_format_map format =
+ match format with
+ | Normal -> "Normal", 0
+ | HeaderL1 -> "HeaderL1", 2
+ | HeaderL2 -> "HeaderL2", 3
+ | HeaderL3 -> "HeaderL3", 4
+ | Embedded -> "Embedded", 3
+ | Preformatted -> "Preformatted", 3
+ | Hidden -> "Hidden", 3
+ | Quote -> "Quote", 2
+ | Link -> "Link", 3
+ | ListItem -> "ListItem", 2
+
+let line_format_str format =
+ fst (line_format_map format)
+
+let line_format_char_cut format =
+ snd (line_format_map format)
+
type page_line = {
- header_level: int;
content: string;
- is_embedded: bool;
- is_preformatted: bool;
- is_hidden: bool;
- is_quote: bool;
- is_link: bool; (* if is_embedded == true => not is_link *)
- is_list: bool;
+ line_type: line_format;
}
-let permute_line line embedded hidden link quote list =
- if embedded then (String.sub line 4 (String.length(line) - 4)) else
- if hidden || link then String.sub line 3 (String.length(line) - 3) else
- if quote || list then String.sub line 2 (String.length(line) - 2)
- else line
-
-(* TODO: These should be doing prefix matching...*)
+let permute_line line line_type =
+ let cut = line_format_char_cut line_type in String.sub line cut (String.length(line) - cut)
let is_hidden line preformatted =
if not preformatted && String.length(line) > 2 && line.[0] = '?' && line.[1] = '?' && line.[2] = ' ' then true else false
@@ -32,16 +55,33 @@ let is_embedded_link line preformatted =
let is_link line preformatted =
if not preformatted && not (is_embedded_link line preformatted) && String.length(line) > 2 && line.[0] = '=' && line.[1] = '>' && line.[2] = ' ' then true else false
+let header_count line preformatted =
+ if not preformatted then Basic_functions.count_prefix '#' line else 0
+
+let is_h1 line preformatted = header_count line preformatted = 1 (* TODO: Make this more consistent with the others *)
+let is_h2 line preformatted = header_count line preformatted = 2
+let is_h3 line preformatted = header_count line preformatted = 3
+
+let get_line_type line preformatted =
+ let funs = [
+ (Hidden, is_hidden);
+ (ListItem, is_list);
+ (Quote, is_quote);
+ (Embedded, is_embedded_link);
+ (Link, is_link);
+ (HeaderL1, is_h1);
+ (HeaderL2, is_h2);
+ (HeaderL3, is_h3);
+ ] in
+ let lt = (List.find_opt (fun (_, f) -> f line preformatted) funs) in
+ match lt with
+ | Some v -> fst v
+ | None -> Normal
+
let parse_simple_line line preformatted =
- let hidden = is_hidden line preformatted in
- let hash_count = if not preformatted then Basic_functions.count_prefix '#' line else 0 in
- let embedded_link = is_embedded_link line preformatted in
- (* This re-computes is embedded, but maintains the 1 bit of state invariant in exchange. *)
- let link = is_link line preformatted in
- let quote = is_quote line preformatted in
- let list = is_list line preformatted in
-
- {header_level = hash_count; content = (permute_line line embedded_link hidden link quote list); is_embedded = embedded_link; is_preformatted = preformatted; is_hidden = hidden; is_link = link; is_quote = quote; is_list = list}
+ let cl_type = get_line_type line preformatted in
+
+ {line_type = cl_type; content = (permute_line line cl_type)}
let is_format_line cl =
diff --git a/learning/bin/render.ml b/learning/bin/render.ml
@@ -29,7 +29,7 @@ let render_sidebar s =
(Jg_template.from_file "./templates/sidebar.jingoo" ~models:[("courses", get_courses)]) ^ s
let page_line_to_tobj (line : Parser.page_line) =
- Jg_types.Tobj [("header_level", Jg_types.Tint line.header_level); ("content", Jg_types.Tstr line.content); ("is_embedded", Jg_types.Tbool line.is_embedded); ("is_preformatted", Jg_types.Tbool line.is_preformatted); ("is_hidden", Jg_types.Tbool line.is_hidden); ("is_quote", Jg_types.Tbool line.is_quote); ("is_link", Jg_types.Tbool line.is_link); ("is_list", Jg_types.Tbool line.is_list)]
+ Jg_types.Tobj [("content", Jg_types.Tstr line.content); ("line_type", Jg_types.Tstr (Parser.line_format_str line.line_type))]
let render_course_home course_name =
(Jg_template.from_file "./templates/course_home.jingoo" ~models:[("pages", (Jg_types.Tlist (get_course_home course_name)))])
diff --git a/learning/static/styles.css b/learning/static/styles.css
@@ -20,17 +20,6 @@ h3 {
color: #580000 ;
}
-h4 {
- color: #600000 ;
-}
-h5 {
- color: #680000 ;
-}
-
-h6 {
- color: #700000 ;
-}
-
pre-formatted {
background: #f4f4f4;
border: 1px solid #ddd;
diff --git a/learning/templates/course_page.jingoo b/learning/templates/course_page.jingoo
@@ -1,25 +1,29 @@
<div class="main">
{% for line in lines %}
- {% if line.is_preformatted %}
+ {% if line.line_type == "Preformatted"%}
<pre><pre-formatted>{{line.content}}</pre-formatted></pre>
- {% else if line.is_quote %}
+ {% else if line.line_type == "Quote"%}
<blockquote>{{line.content}}</blockquote>
- {% else if line.is_list %}
+ {% else if line.line_type == "ListItem"%}
<li>{{line.content}}</li>
- {% else if line.is_link %}
+ {% else if line.line_type == "Link"%}
<a href="{{line.content}}">{{line.content}}</a>
- {% else if line.is_hidden %}
+ {% else if line.line_type == "Hidden"%}
<details>
<summary>{{line.content}}</summary>
</details>
- {% else if line.header_level >= 1 %}
- <h{{line.header_level}}>{{line.content}}</h{{line.header_level}}>
- {% else if line.is_embedded %}
+ {% else if line.line_type == "HeaderL1"%}
+ <h1>{{line.content}}</h1>
+ {% else if line.line_type == "HeaderL2"%}
+ <h2>{{line.content}}</h2>
+ {% else if line.line_type == "HeaderL3"%}
+ <h3>{{line.content}}</h3>
+ {% else if line.line_type == "Embedded"%}
<iframe
style="width: 100%; height: 600px;overflow:auto";
src="{{line.content}}">
</iframe>
- {% else if line.header_level == 0 %}
+ {% else if line.line_type == "Normal"%}
<content-block>{{line.content}}</content-block>
{% endif %}
{% endfor %}