aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md14
-rw-r--r--main.go77
2 files changed, 58 insertions, 33 deletions
diff --git a/README.md b/README.md
index 01197a8..f0851f3 100644
--- a/README.md
+++ b/README.md
@@ -12,15 +12,23 @@ Geminispace, but it defaults to a specific domain.
```
$ go build
-$ ./kineto [-b 127.0.0.1:8080] [-s style.css] gemini://example.org
+$ ./kineto [-b 127.0.0.1:8080] [-s style.css] [-e style.css] gemini://example.org
```
The -b argument is optional and allows you to bind to an arbitrary address; by
default kineto will bind to `:8080`. You should set up some external reverse
proxy like nginx to forward traffic to this port and add TLS.
-The -s argument is optional and allows you to specify a custom CSS file. By
-default kineto will serve its built-in style.
+The -s argument is optional and allows you to specify a custom CSS filename.
+The given file will be loaded from the local disk and placed in a `<style>`
+block. By default kineto will serve its built-in style.
+
+The -e argument is optional and allows you to specify a custom CSS URL. If
+provided, the style.css given will be treated as a link to be put in the href
+of a `<link rel="stylesheet"...>` instead of being placed inline with the body
+in a `<style>` block like with the -s flag. The given stylesheet can be a
+relative link, for instance `-e /main.css` will serve `main.css` from the root
+of the proxied Gemini capsule.
## "kineto"?
diff --git a/main.go b/main.go
index e03574f..c600985 100644
--- a/main.go
+++ b/main.go
@@ -127,10 +127,14 @@ var gemtextPage = template.Must(template.
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1" />
{{- if .CSS }}
+{{- if .ExternalCSS }}
+<link rel="stylesheet" type="text/css" href="{{.CSS | safeCSS}}">
+{{- else }}
<style>
{{.CSS | safeCSS}}
</style>
{{- end }}
+{{- end }}
<title>{{.Title}}</title>
<article{{if .Lang}} lang="{{.Lang}}"{{end}}>
{{ $ctx := . -}}
@@ -229,10 +233,14 @@ var inputPage = template.Must(template.
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1" />
{{- if .CSS }}
+{{- if .ExternalCSS }}
+<link rel="stylesheet" type="text/css" href="{{.CSS | safeCSS}}">
+{{- else }}
<style>
{{.CSS | safeCSS}}
</style>
{{- end }}
+{{- end }}
<title>{{.Prompt}}</title>
<form method="POST">
<label for="input">{{.Prompt}}</label>
@@ -359,22 +367,24 @@ input:focus {
`
type GemtextContext struct {
- CSS string
- External bool
- Lines []gemini.Line
- Pre int
- Resp *gemini.Response
- Title string
- Lang string
- URL *url.URL
- Root *url.URL
+ CSS string
+ ExternalCSS bool
+ External bool
+ Lines []gemini.Line
+ Pre int
+ Resp *gemini.Response
+ Title string
+ Lang string
+ URL *url.URL
+ Root *url.URL
}
type InputContext struct {
- CSS string
- Prompt string
- Secret bool
- URL *url.URL
+ CSS string
+ ExternalCSS bool
+ Prompt string
+ Secret bool
+ URL *url.URL
}
type GemtextHeading struct {
@@ -383,7 +393,7 @@ type GemtextHeading struct {
}
func proxyGemini(req gemini.Request, external bool, root *url.URL,
- w http.ResponseWriter, r *http.Request, css string) {
+ w http.ResponseWriter, r *http.Request, css string, externalCSS bool) {
ctx, cancel := context.WithTimeout(r.Context(), 20*time.Second)
defer cancel()
@@ -401,10 +411,11 @@ func proxyGemini(req gemini.Request, external bool, root *url.URL,
case 10, 11:
w.Header().Add("Content-Type", "text/html")
err = inputPage.Execute(w, &InputContext{
- CSS: css,
- Prompt: resp.Meta,
- Secret: resp.Status == 11,
- URL: req.URL,
+ CSS: css,
+ ExternalCSS: externalCSS,
+ Prompt: resp.Meta,
+ Secret: resp.Status == 11,
+ URL: req.URL,
})
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
@@ -478,13 +489,14 @@ func proxyGemini(req gemini.Request, external bool, root *url.URL,
w.Header().Add("Content-Type", "text/html")
gemctx := &GemtextContext{
- CSS: css,
- External: external,
- Resp: resp,
- Title: req.URL.Host + " " + req.URL.Path,
- Lang: lang,
- URL: req.URL,
- Root: root,
+ CSS: css,
+ ExternalCSS: externalCSS,
+ External: external,
+ Resp: resp,
+ Title: req.URL.Host + " " + req.URL.Path,
+ Lang: lang,
+ URL: req.URL,
+ Root: root,
}
var title bool
@@ -508,11 +520,12 @@ func proxyGemini(req gemini.Request, external bool, root *url.URL,
func main() {
var (
- bind string = ":8080"
- css string = defaultCSS
+ bind string = ":8080"
+ css string = defaultCSS
+ external bool = false
)
- opts, optind, err := getopt.Getopts(os.Args, "b:c:s:")
+ opts, optind, err := getopt.Getopts(os.Args, "b:c:s:e:")
if err != nil {
log.Fatal(err)
}
@@ -521,12 +534,16 @@ func main() {
case 'b':
bind = opt.Value
case 's':
+ external = false
cssContent, err := ioutil.ReadFile(opt.Value)
if err == nil {
css = string(cssContent)
} else {
log.Fatalf("Error opening custom CSS from '%s': %v", opt.Value, err)
}
+ case 'e':
+ external = true
+ css = opt.Value
}
}
@@ -572,7 +589,7 @@ func main() {
req.URL.Host = root.Host
req.URL.Path = r.URL.Path
req.URL.RawQuery = r.URL.RawQuery
- proxyGemini(req, false, root, w, r, css)
+ proxyGemini(req, false, root, w, r, css, external)
}))
http.Handle("/x/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@@ -606,7 +623,7 @@ func main() {
req.URL.Path = "/" + path[3]
req.URL.RawQuery = r.URL.RawQuery
log.Printf("%s (external) %s%s", r.Method, r.URL.Host, r.URL.Path)
- proxyGemini(req, true, root, w, r, css)
+ proxyGemini(req, true, root, w, r, css, external)
}))
log.Printf("HTTP server listening on %s", bind)