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.
^[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]
+3 -1
View File
@@ -2,7 +2,9 @@
input=$(cat -)
input="${input#odin run src/}"
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>"
output="$start$input$end"
echo "$output" > /tmp/preview.html
+54 -26
View File
@@ -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
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
}
if asterisks == 2 {
is_bold = !is_bold
} else if asterisks == 1 {
is_italic = !is_italic
}
current_node = token
if is_bold {
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 == .Bold else push_token(current_node, TokenType.Bold, nil)
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
@@ -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
+4 -3
View File
@@ -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;
}