Strikethrough parsing

This commit is contained in:
2026-07-14 18:06:42 +02:00
parent 7737c2d763
commit 5d232786bf
4 changed files with 71 additions and 37 deletions
+5 -2
View File
@@ -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. 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]^ << (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] #[https://krzak.org/krzak-icon.png]
+3 -1
View File
@@ -2,7 +2,9 @@
input=$(cat -) input=$(cat -)
input="${input#odin run src/}" input="${input#odin run src/}"
style="<style>$(cat styles.css)</style>" style="<style>$(cat styles.css)</style>"
start="<html><head><title>TypoML Preview</title>$style</head><body>" doctype='<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">'
meta='<meta http-equiv="Content-Type" content="text/html; charset=utf-8">'
start="$doctype<html><head><title>TypoML Preview</title>$meta$style</head><body>"
end="</body></html>" end="</body></html>"
output="$start$input$end" output="$start$input$end"
echo "$output" > /tmp/preview.html echo "$output" > /tmp/preview.html
+59 -31
View File
@@ -52,63 +52,85 @@ parse_header :: proc(line: string) -> (int, string) {
return lvl, line[lvl + 1:] 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 { if token.children != nil {
for child in token.children { for i := 0; i < len(token.children); i += 1 {
pass_through_children(child) parse_inline_style(token.children[i], symbol, toggles)
} }
} }
if token.type == TokenType.Text { if token.type == .Text {
str, ok := token.value.(string) 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 return
} }
token.value = nil token.value = nil
is_bold := false active_styles: [256]bool
is_italic := false
current_node := token current_node := token
i := 0 i := 0
start := 0 start := 0
for i < len(str) { for i < len(str) {
if str[i] == '*' { if str[i] == symbol {
if i > start { if i > start {
push_token(current_node, TokenType.Text, str[start:i]) push_token(current_node, TokenType.Text, str[start:i])
} }
asterisks := 0 count := 0
for i < len(str) && str[i] == '*' { symbol_start := i
asterisks += 1 for i < len(str) && str[i] == symbol {
count += 1
i += 1 i += 1
} }
for asterisks >= 3 { for count > 0 {
is_bold = !is_bold matched := false
is_italic = !is_italic for toggle in toggles {
asterisks -= 3 if count >= toggle.amount {
} active_styles[int(toggle.type)] = !active_styles[int(toggle.type)]
if asterisks == 2 { count -= toggle.amount
is_bold = !is_bold matched = true
} else if asterisks == 1 { break
is_italic = !is_italic }
}
if !matched {
push_token(
current_node,
TokenType.Text,
str[symbol_start:symbol_start + count],
)
count = 0
break
}
} }
current_node = token current_node = token
if is_bold { for toggle in toggles {
last := if active_styles[int(toggle.type)] {
current_node.children[len(current_node.children) - 1] if len(current_node.children) > 0 else nil last :=
current_node = current_node.children[len(current_node.children) - 1] if len(current_node.children) > 0 else nil
last if last != nil && last.type == .Bold else push_token(current_node, TokenType.Bold, nil) current_node =
} last if last != nil && last.type == toggle.type else push_token(current_node, toggle.type, 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)
} }
start = i 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) { add_breaklines :: proc(token: ^Token) {
if token.children == nil { if token.children == nil {
return return
+4 -3
View File
@@ -3,7 +3,7 @@ body {
color: #e0e0e0; color: #e0e0e0;
background: #1a1a1a; background: #1a1a1a;
margin: 2em auto; margin: 2em auto;
max-width: 750px; width: 750px;
padding: 1em 2em; padding: 1em 2em;
line-height: 1.8; line-height: 1.8;
font-size: 18px; font-size: 18px;
@@ -19,7 +19,8 @@ pre {
background: #2a2a2a; background: #2a2a2a;
border: 1px solid #444; border: 1px solid #444;
padding: 1em; padding: 1em;
overflow: auto; white-space: pre-wrap;
word-wrap: break-word;
} }
code { code {
font-family: "Courier New", Courier, monospace; font-family: "Courier New", Courier, monospace;
@@ -40,7 +41,7 @@ a:hover {
color: #ff1493; color: #ff1493;
} }
table { table {
border-collapse: collapse; border-spacing: 0;
width: 100%; width: 100%;
margin-bottom: 1em; margin-bottom: 1em;
} }