mdlinkt/main.go
2023-12-24 20:13:31 +03:00

103 lines
2.1 KiB
Go

package main
import (
"bufio"
"flag"
"net/http"
"os"
"regexp"
"strings"
"github.com/fatih/color"
"log/slog"
)
type LinkCheckResult struct {
Link string
IsValid bool
StatusCode int
}
func main() {
filename := flag.String("file", "", "Markdown file to test")
verbose := flag.Bool("verbose", false, "Enable verbose mode")
failedOnly := flag.Bool("failed-only", false, "Return only failed links")
flag.Parse()
if *filename == "" {
slog.Error("Please provide a markdown file.")
os.Exit(1)
}
file, err := os.Open(*filename)
if err != nil {
slog.Error("Failed to open file: ", err)
os.Exit(1)
}
defer file.Close()
scanner := bufio.NewScanner(file)
re := regexp.MustCompile(`\[(.*?)\]\((.*?)\)`)
results := []LinkCheckResult{}
for scanner.Scan() {
line := scanner.Text()
matches := re.FindAllStringSubmatch(line, -1)
for _, match := range matches {
link := strings.TrimSpace(match[2])
resp, err := http.Head(link)
if err != nil {
slog.Error("Error checking link: ", err)
} else {
result := LinkCheckResult{
Link: link,
IsValid: resp.StatusCode == http.StatusOK,
StatusCode: resp.StatusCode,
}
results = append(results, result)
if *verbose || (!*failedOnly && !result.IsValid) {
statusColor := color.GreenString
if !result.IsValid {
statusColor = color.RedString
}
slog.Info(link + ": " + statusColor("%d", result.StatusCode))
}
}
}
}
if err := scanner.Err(); err != nil {
slog.Info("Error scanning file: ", err)
os.Exit(1)
}
// Print summary
validCount := 0
invalidCount := 0
for _, result := range results {
if result.IsValid {
validCount++
} else {
invalidCount++
}
}
if *failedOnly {
for _, result := range results {
if !result.IsValid {
slog.Info("Failed link: " + result.Link)
}
}
} else {
summaryColor := color.GreenString
if invalidCount > 0 {
summaryColor = color.RedString
}
slog.Info(summaryColor("Summary: %d valid links, %d invalid links", validCount, invalidCount))
}
if invalidCount > 0 {
os.Exit(1)
}
}