diff options
| author | Eltrac <hi@guhub.cn> | 2025-10-21 19:38:43 +0800 |
|---|---|---|
| committer | Eltrac <hi@guhub.cn> | 2025-10-21 19:38:43 +0800 |
| commit | 377a72b003cf5b3dbd2b9120965337ed4a98ade7 (patch) | |
| tree | 4b4e407d8c1e3555402e9343696f6579c679c11b /scripts/get_external_link_rank.go | |
| parent | e09fd5cf7551c8016fc46cf73cc801ed287da6f0 (diff) | |
refactor(build): separate link scanning logic
Generation of both internal link graph and external link rank used to be done in one single script. Now it's separated for maintenance.
Former-commit-id: 7d308beee2359afe39582ed6182f085250768f3f
Diffstat (limited to 'scripts/get_external_link_rank.go')
| -rw-r--r-- | scripts/get_external_link_rank.go | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/scripts/get_external_link_rank.go b/scripts/get_external_link_rank.go new file mode 100644 index 00000000..780bb5ec --- /dev/null +++ b/scripts/get_external_link_rank.go @@ -0,0 +1,73 @@ +package main + +import ( + "encoding/json" + "fmt" + "io/fs" + "net/url" + "os" + "path/filepath" + "regexp" + "sort" + "strings" +) + +func main() { + externalLinks := countExternalLinks("content") + writeJSON("data/externallinks.json", externalLinks) + fmt.Println("✅ External link rank data generated.") +} + +// countExternalLinks scans markdown files and counts occurrences of each external domain. +func countExternalLinks(root string) [][2]interface{} { + linkRegex := regexp.MustCompile(`https?://[^\s)>"']+`) + counts := make(map[string]int) + + filepath.WalkDir(root, func(path string, d fs.DirEntry, err error) error { + if err != nil || d.IsDir() || !strings.HasSuffix(path, ".md") { + return nil + } + data, err := os.ReadFile(path) + if err != nil { + return nil + } + matches := linkRegex.FindAllString(string(data), -1) + for _, match := range matches { + u, err := url.Parse(match) + if err == nil && u.Host != "" && u.Host != "image.guhub.cn" { + counts[u.Host]++ + } + } + return nil + }) + + // convert map to sorted array + type kv struct { + Key string + Value int + } + var list []kv + for k, v := range counts { + list = append(list, kv{k, v}) + } + sort.Slice(list, func(i, j int) bool { return list[i].Value > list[j].Value }) + + result := make([][2]interface{}, len(list)) + for i, kv := range list { + result[i] = [2]interface{}{kv.Key, kv.Value} + } + return result +} + +// writeJSON writes the result to file with indentation. +func writeJSON(path string, data interface{}) { + file, err := os.Create(path) + if err != nil { + fmt.Println("Error:", err) + return + } + defer file.Close() + enc := json.NewEncoder(file) + enc.SetIndent("", " ") + enc.Encode(data) +} |
