summaryrefslogtreecommitdiff
path: root/scripts/extract_highlights.go
blob: c7253d5f391c8dd3fb0fe38b8004f717bc53f7ad (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package main

import (
	"encoding/json"
	"fmt"
	"io/fs"
	"net/url"
	"os"
	"path/filepath"
	"regexp"
	"strings"
)

type HighlightLink struct {
	Text string `json:"text"`
	Link string `json:"link"`
}

type Result struct {
	Title      string          `json:"title"`
	URL        string          `json:"url"`
	Highlights []HighlightLink `json:"highlights"`
}

func main() {
	const contentDir = "content"
	const outputFile = "data/highlights.json"

	highlightPattern := regexp.MustCompile(`==(.+?)==`)
	titlePattern := regexp.MustCompile(`(?m)^title:\s*["']?(.+?)["']?\s*$`)
	slugPattern := regexp.MustCompile(`(?m)^slug:\s*["']?(.+?)["']?\s*$`)

	var results []Result

	err := filepath.WalkDir(contentDir, func(path string, d fs.DirEntry, err error) error {
		if err != nil {
			return err
		}
		if d.IsDir() || !strings.HasSuffix(d.Name(), ".md") {
			return nil
		}

		contentBytes, err := os.ReadFile(path)
		if err != nil {
			return err
		}
		content := string(contentBytes)

		// Title
		title := filepath.Base(path)
		if m := titlePattern.FindStringSubmatch(content); len(m) > 1 {
			title = m[1]
		}

		// Slug and URL
		urlPath := ""
		if m := slugPattern.FindStringSubmatch(content); len(m) > 1 {
			slug := strings.Trim(m[1], "/")
			relDir, _ := filepath.Rel(contentDir, filepath.Dir(path))
			relDir = filepath.ToSlash(relDir)
			if relDir != "." {
				urlPath = fmt.Sprintf("/%s/%s/", relDir, slug)
			} else {
				urlPath = fmt.Sprintf("/%s/", slug)
			}
		} else {
			rel, _ := filepath.Rel(contentDir, path)
			rel = filepath.ToSlash(rel)
			urlPath = "/" + strings.TrimSuffix(rel, ".md") + "/"
		}

		// Highlights
		matches := highlightPattern.FindAllStringSubmatch(content, -1)
		if len(matches) == 0 {
			return nil
		}

		var highlightLinks []HighlightLink
		for _, m := range matches {
			if len(m) > 1 {
				h := m[1]
				encoded := url.QueryEscape(h)
				link := fmt.Sprintf("%s#:~:text=%s", urlPath, encoded)
				highlightLinks = append(highlightLinks, HighlightLink{Text: h, Link: link})
			}
		}

		results = append(results, Result{
			Title:      title,
			URL:        urlPath,
			Highlights: highlightLinks,
		})

		return nil
	})

	if err != nil {
		fmt.Println("❌ Error:", err)
		return
	}

	// Write JSON
	if err := os.MkdirAll(filepath.Dir(outputFile), os.ModePerm); err != nil {
		fmt.Println("❌ Error creating output directory:", err)
		return
	}

	jsonData, err := json.MarshalIndent(results, "", "  ")
	if err != nil {
		fmt.Println("❌ Error encoding JSON:", err)
		return
	}

	if err := os.WriteFile(outputFile, jsonData, 0644); err != nil {
		fmt.Println("❌ Error writing JSON file:", err)
		return
	}

	fmt.Printf("✔ 提取完成,共 %d 篇文章有高亮,已写入 %s\n", len(results), outputFile)
}