Kaku/kaku/lineclassifier.go
2026-08-28 01:47:25 +02:00

76 lines
1.7 KiB
Go

package kaku
import "strings"
type lineKind int
const (
lineBlank lineKind = iota
lineHeading
lineHR
lineCodeFence
lineBullet
lineOrdered
lineDef
lineKeyedTag
lineAside
lineTodo
lineHTML
lineParagraph
)
var keyedTagPrefixes = []string{"(quote:", "(link:", "(image:", "(video:", "(audio:", "(details:"}
// Checks what kind of block a line starts, based on its (trimmed) prefix
func classifyLine(line string) lineKind {
trimmed := strings.TrimSpace(line)
switch {
case trimmed == "":
return lineBlank
case trimmed == "----":
return lineHR
case strings.HasPrefix(trimmed, "```"):
return lineCodeFence
case strings.HasPrefix(trimmed, "#"):
return lineHeading
case strings.HasPrefix(trimmed, "- "):
return lineBullet
case strings.HasPrefix(trimmed, "+ "):
return lineOrdered
case strings.HasPrefix(trimmed, "? "):
return lineDef
case strings.HasPrefix(trimmed, "{") && strings.HasSuffix(trimmed, "}"):
return lineAside
case strings.HasPrefix(trimmed, "<"):
return lineHTML
case isTodoLine(trimmed):
return lineTodo
case hasParenthesisPrefix(trimmed, keyedTagPrefixes):
return lineKeyedTag
default:
return lineParagraph
}
}
// Checks if text starts with any of the given prefixes.
func hasParenthesisPrefix(text string, prefixes []string) bool {
for _, p := range prefixes {
if strings.HasPrefix(text, p) {
return true
}
}
return false
}
// isTodoLine reports whether the line matches "[X] text" where X is one of the known todo state characters.
func isTodoLine(trimmed string) bool {
if len(trimmed) < 3 || trimmed[0] != '[' || trimmed[2] != ']' {
return false
}
switch trimmed[1] {
case ' ', '@', '~', 'x':
return true
}
return false
}