~m15o/nightfall-server

ref: ba89521b763a4209cd127101285607180b3b4342 nightfall-server/gmi2html/convert.go -rw-r--r-- 3.6 KiB
ba89521bm15o Fix gemini links 10 months ago
                                                                                
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
121
122
123
124
125
package gmi2html

import (
	"html"
	"net/url"
	"regexp"
	"strings"
)

var heading1Regexp = regexp.MustCompile("^# (.*)$")
var heading2Regexp = regexp.MustCompile("^## (.*)$")
var heading3Regexp = regexp.MustCompile("^### (.*)$")
var linkRegexp = regexp.MustCompile("^=> ([^\\s]+) ?(.+)?$")
var blockquoteRegexp = regexp.MustCompile("^> (.*)$")
var preRegexp = regexp.MustCompile("^```.*$")
var bulletRegexp = regexp.MustCompile(`^\* ?(.*)$`)

func clearLinkMode(linkMode *bool, rv *[]string) {
	if *linkMode {
		*rv = append(*rv, "</p>")
		*linkMode = false
	}
}

func clearUlMode(ulMode *bool, rv *[]string) {
	if *ulMode {
		*rv = append(*rv, "</ul>")
		*ulMode = false
	}
}

func sanitize(input string) string {
	return html.EscapeString(input)
}

func Convert(gmi, baseurl string) string {
	var rv []string
	preMode := false
	ulMode := false
	linkMode := false
	for _, l := range strings.Split(gmi, "\n") {
		l = strings.TrimRight(l, "\r")
		if preMode {
			switch {
			case preRegexp.MatchString(l):
				rv = append(rv, "</pre>")
				preMode = false
			default:
				rv = append(rv, sanitize(l))
			}
		} else {
			switch {
			case heading1Regexp.MatchString(l):
				clearUlMode(&ulMode, &rv)
				clearLinkMode(&linkMode, &rv)
				matches := heading1Regexp.FindStringSubmatch(l)
				rv = append(rv, "<h1>"+sanitize(matches[1])+"</h1>")
			case heading2Regexp.MatchString(l):
				clearUlMode(&ulMode, &rv)
				clearLinkMode(&linkMode, &rv)
				matches := heading2Regexp.FindStringSubmatch(l)
				rv = append(rv, "<h2>"+sanitize(matches[1])+"</h2>")
			case heading3Regexp.MatchString(l):
				clearUlMode(&ulMode, &rv)
				clearLinkMode(&linkMode, &rv)
				matches := heading3Regexp.FindStringSubmatch(l)
				rv = append(rv, "<h3>"+sanitize(matches[1])+"</h3>")
			case blockquoteRegexp.MatchString(l):
				clearUlMode(&ulMode, &rv)
				clearLinkMode(&linkMode, &rv)
				matches := blockquoteRegexp.FindStringSubmatch(l)
				rv = append(rv, "<blockquote>"+sanitize(matches[1])+"</blockquote>")
			case linkRegexp.MatchString(l):
				clearUlMode(&ulMode, &rv)
				matches := linkRegexp.FindStringSubmatch(l)
				if len(matches[2]) == 0 {
					matches[2] = matches[1]
				}
				linkurl := matches[1]
				bu, _ := url.Parse("gemini://" + baseurl)
				lu, _ := url.Parse(linkurl)
				ru := linkurl
				if !strings.Contains(linkurl, "://") {
					ru = bu.ResolveReference(lu).String()
				}
				if strings.Contains(ru, "gemini://") {
					ru = strings.Replace(ru, "gemini://", "/gemini/",1)
				}
				if strings.HasSuffix(ru, ".png") || strings.HasSuffix(ru, ".PNG") || strings.HasSuffix(ru, ".jpg") || strings.HasSuffix(ru, ".JPG") || strings.HasSuffix(ru, ".jpeg") || strings.HasSuffix(ru, ".gif") || strings.HasSuffix(ru, ".GIF") {
					rv = append(rv, "<img src=\""+sanitize(ru)+"\"/>")
					continue
				}
				if linkMode {
					rv = append(rv, "<a href=\""+sanitize(ru)+"\">"+sanitize(matches[2])+"</a><br/>")
					continue
				}
				rv = append(rv, "<p><a href=\""+sanitize(ru)+"\">"+sanitize(matches[2])+"</a><br/>")
				linkMode = true
			case preRegexp.MatchString(l):
				clearUlMode(&ulMode, &rv)
				clearLinkMode(&linkMode, &rv)
				rv = append(rv, "<pre>")
				preMode = true
			case bulletRegexp.MatchString(l):
				clearLinkMode(&linkMode, &rv)
				matches := bulletRegexp.FindStringSubmatch(l)
				if ulMode {
					rv = append(rv, "<li>"+sanitize(matches[1])+"</li>")
					continue
				}
				rv = append(rv, "<ul>\n<li>"+sanitize(matches[1])+"</li>")
				ulMode = true
			default:
				clearUlMode(&ulMode, &rv)
				clearLinkMode(&linkMode, &rv)
				if len(l) != 0 {
					rv = append(rv, "<p>"+sanitize(l)+"</p>")
				}
			}
		}
	}
	clearUlMode(&ulMode, &rv)
	clearLinkMode(&linkMode, &rv)
	return strings.Join(rv, "\n")
}