Escape HTML

This commit is contained in:
2026-07-14 22:57:01 +02:00
parent 10c4e50f23
commit fafe5b0eab
2 changed files with 36 additions and 17 deletions
+2 -2
View File
@@ -10,9 +10,9 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam blandit dolor nibh,
#(https://krzak.org) #(https://krzak.org)
^ Links with no alt text ^ Links with no alt text
$[https://krzak.org/krzak-icon.png]
$(https://krzak.org/krzak-icon.png)
$[https://krzak.org/krzak-icon.png|img] $[https://krzak.org/krzak-icon.png|img]
$[https://frokfrdk.com/projects/staircase/staircase.wav]
$(https://9front.org/movies/no.mp4)
*italic* *italic*
**bold** **bold**
+34 -15
View File
@@ -3,6 +3,25 @@ package main
import "core:fmt" import "core:fmt"
import "core:strings" import "core:strings"
escape_html :: proc(s: string, allocator := context.temp_allocator) -> string {
b := strings.builder_make(allocator)
for ch in s {
switch ch {
case '&':
strings.write_string(&b, "&")
case '<':
strings.write_string(&b, "&lt;")
case '>':
strings.write_string(&b, "&gt;")
case '"':
strings.write_string(&b, "&quot;")
case:
strings.write_rune(&b, ch)
}
}
return strings.to_string(b)
}
get_text_content :: proc(token: ^Token, b: ^strings.Builder) { get_text_content :: proc(token: ^Token, b: ^strings.Builder) {
if token.type == .Text { if token.type == .Text {
if v, ok := token.value.(string); ok { if v, ok := token.value.(string); ok {
@@ -237,12 +256,12 @@ print_html :: proc(token: ^Token) {
case TokenType.FootnoteRef: case TokenType.FootnoteRef:
if id, ok := token.value.(string); ok { if id, ok := token.value.(string); ok {
fmt.printf("<a href=\"#fn-%s\" id=\"ref-%s\"><sup>%s</sup></a>", id, id, id) fmt.printf("<a href=\"#fn-%s\" id=\"ref-%s\"><sup>%s</sup></a>", escape_html(id), escape_html(id), escape_html(id))
} }
case TokenType.FootnoteDef: case TokenType.FootnoteDef:
if id, ok := token.value.(string); ok { if id, ok := token.value.(string); ok {
fmt.printf("<div class=\"footnote\" id=\"fn-%s\"><a href=\"#ref-%s\">^</a> ", id, id) fmt.printf("<div class=\"footnote\" id=\"fn-%s\"><a href=\"#ref-%s\">^</a> ", escape_html(id), escape_html(id))
for child in token.children { for child in token.children {
print_html(child) print_html(child)
} }
@@ -269,7 +288,7 @@ print_html :: proc(token: ^Token) {
case TokenType.InlineCode: case TokenType.InlineCode:
if code, ok := token.value.(string); ok { if code, ok := token.value.(string); ok {
fmt.printf("<code>%s</code>", code) fmt.printf("<code>%s</code>", escape_html(code))
} }
case TokenType.HorizontalRule: case TokenType.HorizontalRule:
@@ -298,8 +317,8 @@ print_html :: proc(token: ^Token) {
case TokenType.HeaderLink: case TokenType.HeaderLink:
if target, ok := token.value.(string); ok { if target, ok := token.value.(string); ok {
slug := slugifyifyifyify(target) slug := slugifyifyifyify(target)
fmt.printf("<a href=\"#%s\">", slug) fmt.printf("<a href=\"#%s\">", escape_html(slug))
for child in token.children { for child in token.children {
print_html(child) print_html(child)
} }
@@ -308,7 +327,7 @@ print_html :: proc(token: ^Token) {
case TokenType.Link: case TokenType.Link:
if url, ok := token.value.(string); ok { if url, ok := token.value.(string); ok {
fmt.printf("<a href=\"%s\">", url) fmt.printf("<a href=\"%s\">", escape_html(url))
for child in token.children { for child in token.children {
print_html(child) print_html(child)
} }
@@ -322,12 +341,12 @@ print_html :: proc(token: ^Token) {
get_text_content(child, &b) get_text_content(child, &b)
} }
alt_text := strings.to_string(b) alt_text := strings.to_string(b)
fmt.printf("<img src=\"%s\" alt=\"%s\">", url, alt_text) fmt.printf("<img src=\"%s\" alt=\"%s\">", escape_html(url), escape_html(alt_text))
} }
case TokenType.Audio: case TokenType.Audio:
if url, ok := token.value.(string); ok { if url, ok := token.value.(string); ok {
fmt.printf("<audio controls src=\"%s\">", url) fmt.printf("<audio controls src=\"%s\">", escape_html(url))
for child in token.children { for child in token.children {
print_html(child) print_html(child)
} }
@@ -336,7 +355,7 @@ print_html :: proc(token: ^Token) {
case TokenType.Video: case TokenType.Video:
if url, ok := token.value.(string); ok { if url, ok := token.value.(string); ok {
fmt.printf("<video controls src=\"%s\">", url) fmt.printf("<video controls src=\"%s\">", escape_html(url))
for child in token.children { for child in token.children {
print_html(child) print_html(child)
} }
@@ -345,12 +364,12 @@ print_html :: proc(token: ^Token) {
case TokenType.Iframe: case TokenType.Iframe:
if url, ok := token.value.(string); ok { if url, ok := token.value.(string); ok {
fmt.printf("<iframe src=\"%s\"></iframe>", url) fmt.printf("<iframe src=\"%s\"></iframe>", escape_html(url))
} }
case TokenType.Script: case TokenType.Script:
if url, ok := token.value.(string); ok { if url, ok := token.value.(string); ok {
fmt.printf("<script src=\"%s\"></script>", url) fmt.printf("<script src=\"%s\"></script>", escape_html(url))
} }
case TokenType.ScriptBlock: case TokenType.ScriptBlock:
@@ -360,7 +379,7 @@ print_html :: proc(token: ^Token) {
case TokenType.Variable: case TokenType.Variable:
if name, ok := token.value.(string); ok { if name, ok := token.value.(string); ok {
fmt.printf("<span data-tlm-var=\"%s\">", name) fmt.printf("<span data-tlm-var=\"%s\">", escape_html(name))
for child in token.children { for child in token.children {
print_html(child) print_html(child)
} }
@@ -376,8 +395,8 @@ print_html :: proc(token: ^Token) {
val := strings.to_string(b) val := strings.to_string(b)
fmt.printf( fmt.printf(
"<template data-tlm-def=\"%s\" data-tlm-value=\"%s\"></template>", "<template data-tlm-def=\"%s\" data-tlm-value=\"%s\"></template>",
name, escape_html(name),
val, escape_html(val),
) )
} }
@@ -386,7 +405,7 @@ print_html :: proc(token: ^Token) {
case TokenType.Text: case TokenType.Text:
if v, ok := token.value.(string); ok { if v, ok := token.value.(string); ok {
fmt.print(v) fmt.print(escape_html(v))
} }
for child in token.children { for child in token.children {
print_html(child) print_html(child)