Files
goclaw/internal/tools/web_fetch_convert_handlers.go
T
viettranx bdb60de7ae chore: upgrade Go 1.25 → 1.26 and apply go fix modernizations
- Update go.mod and Dockerfile to Go 1.26
- Apply `go fix ./...` stdlib modernizations across 170+ files
- Add `go fix` to post-implementation checklist in CLAUDE.md
- Fix go fix misapplied rewrite in loop_history.go
2026-03-10 00:09:15 +07:00

252 lines
5.0 KiB
Go

package tools
import (
"fmt"
"strings"
"golang.org/x/net/html"
"golang.org/x/net/html/atom"
)
func (c *converter) handleText(n *html.Node) {
text := n.Data
if c.inPre {
c.buf.WriteString(text)
return
}
text = collapseWhitespace(text)
if text == "" {
return
}
if text == " " && c.buf.Len() > 0 {
c.buf.WriteByte(' ')
return
}
c.buf.WriteString(text)
}
func (c *converter) handleHeading(n *html.Node) {
c.ensureDoubleNewline()
if c.mode == modeMarkdown && len(n.Data) == 2 && n.Data[0] == 'h' {
level := int(n.Data[1] - '0')
for range level {
c.buf.WriteByte('#')
}
c.buf.WriteByte(' ')
}
c.walkChildren(n)
c.buf.WriteByte('\n')
}
func (c *converter) handleParagraph(n *html.Node) {
c.ensureDoubleNewline()
c.walkChildren(n)
c.buf.WriteByte('\n')
}
func (c *converter) handleLink(n *html.Node) {
href := getAttr(n, "href")
if c.mode == modeText || c.inLink || href == "" || strings.HasPrefix(href, "javascript:") {
c.walkChildren(n)
return
}
c.inLink = true
c.buf.WriteByte('[')
c.walkChildren(n)
c.buf.WriteString("](")
c.buf.WriteString(href)
c.buf.WriteByte(')')
c.inLink = false
}
func (c *converter) handleImage(n *html.Node) {
alt := getAttr(n, "alt")
src := getAttr(n, "src")
if c.mode == modeMarkdown {
c.buf.WriteString("![")
c.buf.WriteString(alt)
c.buf.WriteByte(']')
if src != "" {
c.buf.WriteByte('(')
c.buf.WriteString(src)
c.buf.WriteByte(')')
}
} else if alt != "" {
c.buf.WriteString(alt)
}
}
func (c *converter) handlePre(n *html.Node) {
c.ensureDoubleNewline()
if c.mode == modeMarkdown {
lang := ""
if code := findChild(n, atom.Code); code != nil {
cls := getAttr(code, "class")
for part := range strings.FieldsSeq(cls) {
if rest, ok := strings.CutPrefix(part, "language-"); ok {
lang = rest
break
}
if rest, ok := strings.CutPrefix(part, "lang-"); ok {
lang = rest
break
}
}
}
c.buf.WriteString("```")
c.buf.WriteString(lang)
c.buf.WriteByte('\n')
}
c.inPre = true
c.walkChildren(n)
c.inPre = false
if c.mode == modeMarkdown {
c.ensureNewline()
c.buf.WriteString("```\n")
} else {
c.buf.WriteByte('\n')
}
}
func (c *converter) handleCode(n *html.Node) {
if c.inPre {
c.walkChildren(n)
return
}
if c.mode == modeMarkdown {
c.buf.WriteByte('`')
c.walkChildren(n)
c.buf.WriteByte('`')
} else {
c.walkChildren(n)
}
}
func (c *converter) handleBlockquote(n *html.Node) {
c.ensureDoubleNewline()
if c.mode == modeMarkdown {
sub := &converter{mode: c.mode, inPre: c.inPre}
sub.walkChildren(n)
for i, line := range strings.Split(strings.TrimSpace(sub.buf.String()), "\n") {
if i > 0 {
c.buf.WriteByte('\n')
}
c.buf.WriteString("> ")
c.buf.WriteString(line)
}
c.buf.WriteByte('\n')
} else {
c.walkChildren(n)
}
}
func (c *converter) handleStrong(n *html.Node) {
if c.mode == modeMarkdown {
c.buf.WriteString("**")
c.walkChildren(n)
c.buf.WriteString("**")
} else {
c.walkChildren(n)
}
}
func (c *converter) handleEmphasis(n *html.Node) {
if c.mode == modeMarkdown {
c.buf.WriteByte('*')
c.walkChildren(n)
c.buf.WriteByte('*')
} else {
c.walkChildren(n)
}
}
func (c *converter) handleList(n *html.Node) {
c.ensureNewline()
c.listDepth++
c.listType = append(c.listType, n.DataAtom)
c.listIndex = append(c.listIndex, 0)
c.walkChildren(n)
c.listDepth--
c.listType = c.listType[:len(c.listType)-1]
c.listIndex = c.listIndex[:len(c.listIndex)-1]
c.ensureNewline()
}
func (c *converter) handleListItem(n *html.Node) {
c.ensureNewline()
indent := strings.Repeat(" ", max(0, c.listDepth-1))
c.buf.WriteString(indent)
if len(c.listType) > 0 && c.listType[len(c.listType)-1] == atom.Ol {
idx := len(c.listIndex) - 1
c.listIndex[idx]++
fmt.Fprintf(&c.buf, "%d. ", c.listIndex[idx])
} else {
c.buf.WriteString("- ")
}
c.walkChildren(n)
}
func (c *converter) handleTable(n *html.Node) {
c.ensureDoubleNewline()
rows := collectTableRows(n, c.mode)
if len(rows) == 0 {
return
}
colCount := 0
for _, row := range rows {
if len(row) > colCount {
colCount = len(row)
}
}
if c.mode == modeMarkdown {
for i, row := range rows {
c.buf.WriteByte('|')
for j := 0; j < colCount; j++ {
cell := ""
if j < len(row) {
cell = row[j]
}
c.buf.WriteByte(' ')
c.buf.WriteString(cell)
c.buf.WriteString(" |")
}
c.buf.WriteByte('\n')
if i == 0 {
c.buf.WriteByte('|')
for j := 0; j < colCount; j++ {
c.buf.WriteString(" --- |")
}
c.buf.WriteByte('\n')
}
}
} else {
for _, row := range rows {
c.buf.WriteString(strings.Join(row, " | "))
c.buf.WriteByte('\n')
}
}
c.buf.WriteByte('\n')
}
func (c *converter) handleDefinitionTerm(n *html.Node) {
c.ensureDoubleNewline()
if c.mode == modeMarkdown {
c.buf.WriteString("**")
c.walkChildren(n)
c.buf.WriteString("**")
} else {
c.walkChildren(n)
}
c.buf.WriteByte('\n')
}
func (c *converter) handleDefinitionDesc(n *html.Node) {
c.ensureNewline()
if c.mode == modeMarkdown {
c.buf.WriteString(": ")
}
c.walkChildren(n)
c.buf.WriteByte('\n')
}