- 模块名重命名 yunshu -> hub.gaomia.site/titor/YunShu - Go 版本升级 1.21 -> 1.25 - src/ 目录删除,所有文件移至根目录 - 新增 pkg/mdprint/: Markdown AST 解析+ANSI 渲染 - 新增 pkg/style/: 终端颜色样式(8色 ANSI + 24位真彩色) - 新增 pkg/termui/: 终端输入组件(交互式输入/密码/确认) - 更新文档:AGENTS.md、architecture.md、changelog.md、taolun.md - gitignore 通配符修复 yunshu.exe -> yunshu.exe*
92 lines
1.9 KiB
Go
92 lines
1.9 KiB
Go
package mdprint
|
|
|
|
func parseInline(text string) []Node {
|
|
var nodes []Node
|
|
runes := []rune(text)
|
|
i := 0
|
|
|
|
for i < len(runes) {
|
|
rem := string(runes[i:])
|
|
|
|
if len(rem) >= 2 && rem[:2] == "**" {
|
|
end := findDelim(runes, i+2, "**")
|
|
if end >= 0 {
|
|
inner := string(runes[i+2 : end])
|
|
nodes = append(nodes, Bold{Content: parseInline(inner)})
|
|
i = end + 2
|
|
continue
|
|
}
|
|
nodes = append(nodes, Text{Text: "**"})
|
|
i += 2
|
|
continue
|
|
}
|
|
|
|
if len(rem) >= 1 && rem[:1] == "*" {
|
|
end := findDelim(runes, i+1, "*")
|
|
if end >= 0 {
|
|
inner := string(runes[i+1 : end])
|
|
nodes = append(nodes, Italic{Content: parseInline(inner)})
|
|
i = end + 1
|
|
continue
|
|
}
|
|
nodes = append(nodes, Text{Text: "*"})
|
|
i++
|
|
continue
|
|
}
|
|
|
|
if len(rem) >= 1 && rem[:1] == "`" {
|
|
end := findDelim(runes, i+1, "`")
|
|
if end >= 0 {
|
|
nodes = append(nodes, Code{Text: string(runes[i+1 : end])})
|
|
i = end + 1
|
|
continue
|
|
}
|
|
nodes = append(nodes, Text{Text: "`"})
|
|
i++
|
|
continue
|
|
}
|
|
|
|
if len(rem) >= 1 && rem[:1] == "[" {
|
|
closeB := findDelim(runes, i+1, "]")
|
|
if closeB >= 0 && closeB+1 < len(runes) && runes[closeB+1] == '(' {
|
|
closeP := findDelim(runes, closeB+2, ")")
|
|
if closeP >= 0 {
|
|
linkText := string(runes[i+1 : closeB])
|
|
url := string(runes[closeB+2 : closeP])
|
|
nodes = append(nodes, Link{Content: parseInline(linkText), URL: url})
|
|
i = closeP + 1
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
textStart := i
|
|
for i < len(runes) {
|
|
ch := string(runes[i])
|
|
if ch == "*" || ch == "`" || ch == "[" {
|
|
break
|
|
}
|
|
if ch == "\\" && i+1 < len(runes) {
|
|
i += 2
|
|
continue
|
|
}
|
|
i++
|
|
}
|
|
if i > textStart {
|
|
nodes = append(nodes, Text{Text: string(runes[textStart:i])})
|
|
}
|
|
}
|
|
|
|
return nodes
|
|
}
|
|
|
|
func findDelim(runes []rune, start int, delim string) int {
|
|
for j := start; j < len(runes); j++ {
|
|
rem := string(runes[j:])
|
|
if len(rem) >= len(delim) && rem[:len(delim)] == delim {
|
|
return j
|
|
}
|
|
}
|
|
return -1
|
|
}
|