From 5d232786bf1d4f6400a5f8ec471889f67b69d1d5 Mon Sep 17 00:00:00 2001 From: "N0\\A" Date: Tue, 14 Jul 2026 18:06:42 +0200 Subject: [PATCH] Strikethrough parsing --- README.tlm | 7 ++-- preview | 4 ++- src/parser.odin | 90 ++++++++++++++++++++++++++++++++----------------- styles.css | 7 ++-- 4 files changed, 71 insertions(+), 37 deletions(-) diff --git a/README.tlm b/README.tlm index f7ab72e..742b6e5 100644 --- a/README.tlm +++ b/README.tlm @@ -3,9 +3,12 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam blandit dolor nibh, vitae tempor enim pretium non. Sed in condimentum turpis. Vivamus placerat molestie ullamcorper. Maecenas nec risus nibh. Nullam vel vestibulum sapien. Integer ante erat, aliquam id tellus in, malesuada finibus nunc. Sed porttitor ante orci, eget molestie nibh posuere nec. -^[Link on the right](http://example.com) >> +#[Link on the right](http://example.com) >> (http://example.com)[Example.com]^ << -^[Link to nekoweb.org in the middle](https://n0va.nekoweb.org) ^^ +#[Link to nekoweb.org in the middle](https://n0va.nekoweb.org) ^^ +#[https://krzak.org] +#(https://krzak.org) +^ Links with no alt text #[https://krzak.org/krzak-icon.png] diff --git a/preview b/preview index c7a9d8f..87dcce3 100755 --- a/preview +++ b/preview @@ -2,7 +2,9 @@ input=$(cat -) input="${input#odin run src/}" style="" -start="TypoML Preview$style" +doctype='' +meta='' +start="$doctypeTypoML Preview$meta$style" end="" output="$start$input$end" echo "$output" > /tmp/preview.html diff --git a/src/parser.odin b/src/parser.odin index 95aae63..e812a90 100644 --- a/src/parser.odin +++ b/src/parser.odin @@ -52,63 +52,85 @@ parse_header :: proc(line: string) -> (int, string) { return lvl, line[lvl + 1:] } -pass_through_children :: proc(token: ^Token) { +StyleToggle :: struct { + amount: int, + type: TokenType, +} + +parse_inline_style :: proc(token: ^Token, symbol: byte, toggles: []StyleToggle) { if token.children != nil { - for child in token.children { - pass_through_children(child) + for i := 0; i < len(token.children); i += 1 { + parse_inline_style(token.children[i], symbol, toggles) } } - if token.type == TokenType.Text { + if token.type == .Text { str, ok := token.value.(string) - if !ok || !strings.contains(str, "*") { + if !ok { + return + } + + symbol_found := false + for i := 0; i < len(str); i += 1 { + if str[i] == symbol { + symbol_found = true + break + } + } + if !symbol_found { return } token.value = nil - is_bold := false - is_italic := false + active_styles: [256]bool current_node := token i := 0 start := 0 for i < len(str) { - if str[i] == '*' { + if str[i] == symbol { if i > start { push_token(current_node, TokenType.Text, str[start:i]) } - asterisks := 0 - for i < len(str) && str[i] == '*' { - asterisks += 1 + count := 0 + symbol_start := i + for i < len(str) && str[i] == symbol { + count += 1 i += 1 } - for asterisks >= 3 { - is_bold = !is_bold - is_italic = !is_italic - asterisks -= 3 - } - if asterisks == 2 { - is_bold = !is_bold - } else if asterisks == 1 { - is_italic = !is_italic + for count > 0 { + matched := false + for toggle in toggles { + if count >= toggle.amount { + active_styles[int(toggle.type)] = !active_styles[int(toggle.type)] + count -= toggle.amount + matched = true + break + } + } + if !matched { + push_token( + current_node, + TokenType.Text, + str[symbol_start:symbol_start + count], + ) + count = 0 + break + } } current_node = token - if is_bold { - last := - current_node.children[len(current_node.children) - 1] if len(current_node.children) > 0 else nil - current_node = - last if last != nil && last.type == .Bold else push_token(current_node, TokenType.Bold, nil) - } - if is_italic { - last := - current_node.children[len(current_node.children) - 1] if len(current_node.children) > 0 else nil - current_node = - last if last != nil && last.type == .Italics else push_token(current_node, TokenType.Italics, nil) + for toggle in toggles { + if active_styles[int(toggle.type)] { + last := + current_node.children[len(current_node.children) - 1] if len(current_node.children) > 0 else nil + current_node = + last if last != nil && last.type == toggle.type else push_token(current_node, toggle.type, nil) + } } start = i @@ -123,6 +145,12 @@ pass_through_children :: proc(token: ^Token) { } } +pass_through_children :: proc(token: ^Token) { + parse_inline_style(token, '*', []StyleToggle{{2, .Bold}, {1, .Italics}}) + parse_inline_style(token, '~', []StyleToggle{{2, .Strikethrough}}) + parse_inline_style(token, '-', []StyleToggle{{2, .Strikethrough}}) +} + add_breaklines :: proc(token: ^Token) { if token.children == nil { return diff --git a/styles.css b/styles.css index a46b1ef..07c8e25 100644 --- a/styles.css +++ b/styles.css @@ -3,7 +3,7 @@ body { color: #e0e0e0; background: #1a1a1a; margin: 2em auto; - max-width: 750px; + width: 750px; padding: 1em 2em; line-height: 1.8; font-size: 18px; @@ -19,7 +19,8 @@ pre { background: #2a2a2a; border: 1px solid #444; padding: 1em; - overflow: auto; + white-space: pre-wrap; + word-wrap: break-word; } code { font-family: "Courier New", Courier, monospace; @@ -40,7 +41,7 @@ a:hover { color: #ff1493; } table { - border-collapse: collapse; + border-spacing: 0; width: 100%; margin-bottom: 1em; }