diff --git a/generator.odin b/generator.odin
index d711b46..3420b96 100644
--- a/generator.odin
+++ b/generator.odin
@@ -146,6 +146,151 @@ create_output_directories :: proc(dir_names: []string) {
}
}
+html_escape :: proc(sb: ^strings.Builder, html: string) {
+ strings.write_string(sb, html)
+}
+
+render_html :: proc(sb: ^strings.Builder, root: ^md.Node) {
+ iter := md.iter_new(root)
+ defer md.iter_free(iter)
+ should_write_slug: i32 = 0
+ parent_is_li := false
+
+ for md.iter_next(iter) != .Done {
+ node := md.iter_get_node(iter)
+ event := md.iter_get_event_type(iter)
+
+ #partial switch node.type {
+ case .Heading:
+ level := md.node_get_heading_level(node)
+
+ if event == .Enter {
+ should_write_slug = level
+ } else {
+ fmt.sbprintf(sb, "\n", level)
+ }
+
+ case .Paragraph:
+ if parent_is_li {
+ if event != .Enter do parent_is_li = false
+ } else {
+ if event == .Enter {
+ strings.write_string(sb, "
")
+ } else if event == .Exit {
+ strings.write_string(sb, "
\n")
+ }
+ }
+
+ case .Emph:
+ if event == .Enter {
+ strings.write_string(sb, "")
+ } else {
+ strings.write_string(sb, "")
+ }
+
+ case .Strong:
+ if event == .Enter {
+ strings.write_string(sb, "")
+ } else {
+ strings.write_string(sb, "")
+ }
+
+ case .Code:
+ strings.write_string(sb, "")
+ lit := string(md.node_get_literal(node))
+ html_escape(sb, lit)
+ strings.write_string(sb, "")
+
+ case .Text:
+ lit := string(md.node_get_literal(node))
+ if should_write_slug > 0 {
+ fmt.sbprintf(sb, "")
+ should_write_slug = 0
+ }
+ html_escape(sb, lit)
+
+ case .Soft_Break:
+ strings.write_byte(sb, ' ')
+
+ case .Line_Break:
+ strings.write_string(sb, "
\n")
+
+ case .Code_Block:
+ fence_info := string(md.node_get_fence_info(node))
+ i := strings.index_any(fence_info, " \t\r\n")
+
+ lang := fence_info
+ if i != -1 {
+ lang = fence_info[:i]
+ }
+
+ strings.write_string(sb, "")
+ html_escape(sb, string(md.node_get_literal(node)))
+ strings.write_string(sb, "
\n")
+
+ case .HTML_Inline:
+ if event == .Enter {
+ strings.write_string(sb, string(md.node_get_literal(node)))
+ }
+
+ case .HTML_Block:
+ if event == .Enter {
+ strings.write_string(sb, string(md.node_get_literal(node)))
+ }
+
+ case .Thematic_Break:
+ if event == .Enter {
+ strings.write_string(sb, "
\n")
+ }
+
+ case .List:
+ if event == .Enter {
+ if md.node_get_list_type(node) == .Bullet {
+ strings.write_string(sb, "\n")
+ } else {
+ strings.write_string(sb, "\n")
+ }
+ } else {
+ if md.node_get_list_type(node) == .Bullet {
+ strings.write_string(sb, "
\n")
+ } else {
+ strings.write_string(sb, "\n")
+ }
+ }
+
+ case .Item:
+ if event == .Enter {
+ parent_is_li = true
+ strings.write_string(sb, "")
+ } else {
+ strings.write_string(sb, "\n")
+ }
+
+ case .Link:
+ if event == .Enter {
+ fmt.sbprintf(sb,
+ "",
+ string(md.node_get_url(node)))
+ } else {
+ strings.write_string(sb, "")
+ }
+
+ case .Image:
+ if event == .Enter {
+ fmt.sbprintf(sb,
+ "
")
+ }
+ }
+ }
+}
+
remove_title :: proc(root: ^md.Node) {
heading_state: enum {
None,
@@ -182,6 +327,91 @@ remove_title :: proc(root: ^md.Node) {
//return title
}
+sb_indent :: proc(sb: ^strings.Builder, level: i32) {
+ for i in 0..= 'A' && c <= 'Z':
+ if pending_dash {
+ strings.write_byte(sb, '-')
+ pending_dash = false
+ }
+ strings.write_byte(sb, byte(c + ('a' - 'A')))
+ wrote_any = true
+
+ case (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9'):
+ if pending_dash {
+ strings.write_byte(sb, '-')
+ pending_dash = false
+ }
+ strings.write_byte(sb, byte(c))
+ wrote_any = true
+
+ case:
+ if wrote_any {
+ pending_dash = true
+ }
+ }
+ }
+}
+
+generate_toc :: proc(sb: ^strings.Builder, root: ^md.Node) {
+ entered_heading := false
+ started := false
+ iter := md.iter_new(root)
+ defer md.iter_free(iter)
+ current_level: i32 = 0
+ for md.iter_next(iter) != .Done {
+ event_type := md.iter_get_event_type(iter)
+ node := md.iter_get_node(iter)
+
+ #partial switch node.type {
+ case .Heading:
+ level := md.node_get_heading_level(node)
+ event_type := md.iter_get_event_type(iter)
+
+ if event_type == .Enter {
+ entered_heading = true
+ if !started {
+ for i in 1..")
+ started = true
+ } else {
+ for i in current_level..")
+ if current_level > level do strings.write_string(sb, "")
+ for i in level..")
+ if current_level == level do strings.write_string(sb, "")
+ }
+
+ strings.write_string(sb, "")
+ current_level = level
+ }
+ case .Text:
+ if entered_heading {
+ entered_heading = false
+ text := string(md.node_get_literal(node))
+ strings.write_string(sb, "")
+ strings.write_string(sb, text)
+ strings.write_string(sb, "")
+ }
+ }
+ }
+
+ if started {
+ strings.write_string(sb, "")
+ for i in 1..")
+ }
+}
+
// must free
parse_json :: proc(file_path: string) -> json.Value {
json_file_content, os_err := os.read_entire_file_from_path(file_path, context.temp_allocator)
@@ -326,13 +556,28 @@ process_markdown :: proc(sb: ^strings.Builder, site: Page) {
{.Validate_UTF8, .Unsafe},
)
remove_title(cmark_root)
- html := md.render_html(cmark_root, {.Unsafe})
- output_file_name := fmt.tprint(md_name, ".html", sep = "")
+
+ dir, alloc_err3 := os.join_path(
+ {OUTPUT_ROOT_NAME, markdown_dir, md_name},
+ context.temp_allocator
+ )
+ if alloc_err3 != nil {
+ fmt.println("allocator error:", alloc_err3)
+ continue
+ }
+ os.make_directory(dir)
+
output_file_path, alloc_err2 := os.join_path(
- {OUTPUT_ROOT_NAME, markdown_dir, output_file_name},
+ {OUTPUT_ROOT_NAME, markdown_dir, md_name, "index.html"},
context.temp_allocator,
)
+
+ if alloc_err2 != nil {
+ fmt.println("allocator error:", alloc_err3)
+ continue
+ }
+
out_file, os_err2 := os.open(output_file_path, {.Write, .Create, .Trunc})
if os_err2 != nil {
@@ -353,10 +598,21 @@ process_markdown :: proc(sb: ^strings.Builder, site: Page) {
last_updated_date(sb, date)
- block_begin(sb)
- defer block_end(sb)
+ {
+ block_begin(sb)
+ defer block_end(sb)
- fmt.sbprint(sb, html)
+ strings.write_string(sb, "Contents
")
+
+ generate_toc(sb, cmark_root)
+ }
+ strings.write_string(sb, "
")
+ {
+ block_begin(sb)
+ defer block_end(sb)
+
+ render_html(sb, cmark_root)
+ }
}
write_len: int
@@ -410,10 +666,11 @@ create_toc_page :: proc(title, toc_path: string, toc_info: ^[dynamic][3]string,
tr_begin(sb)
fmt.sbprintf(
sb,
- "%s | aarfsdf | ",
+ "%s | %s | ",
item[0],
item[1],
item[2],
+ item[2],
)
tr_end(sb)
}
@@ -457,19 +714,13 @@ create_toc_page :: proc(title, toc_path: string, toc_info: ^[dynamic][3]string,
}
last_updated_date :: proc(sb: ^strings.Builder, date: string) {
- fmt.sbprint(sb, "")
- fmt.sbprint(
- sb,
- "",
- sep = "",
- )
-
+ strings.write_string(sb, "Last updated: ")
+ strings.write_string(sb, date)
+ strings.write_string(sb, "")
+ strings.write_string(sb, "")
}
nav :: proc(sb: ^strings.Builder, current_path: string, site: Page) {