aboutsummaryrefslogtreecommitdiff
path: root/filters.go
diff options
context:
space:
mode:
authorLena <lena@omega>2026-08-01 00:00:00 +0000
committerLena <lena@omega>2026-08-01 00:00:00 +0000
commitbb6bc2387d58c737dbf92e73f8544bf39319dbd8 (patch)
tree6d5eaf5dac213074cd832da50f64260fce728fed /filters.go
downloadgit-forge-bb6bc2387d58c737dbf92e73f8544bf39319dbd8.tar.gz
Enter git-forgeHEADmaster
A small self-hosted git forge: HTTP push and pull, cgit browsing, local and OIDC accounts, TOTP, scoped push tokens, per-repo permissions, issues, a wiki, and outbound mail. It does not reimplement git. git-http-backend and cgit run as CGI behind its own listener, which authorises every request before exec'ing either. One binary, one data directory, one listener: no database, no JavaScript, and state is JSON in a git repo with a working tree.
Diffstat (limited to 'filters.go')
-rw-r--r--filters.go73
1 files changed, 73 insertions, 0 deletions
diff --git a/filters.go b/filters.go
new file mode 100644
index 0000000..64a1d21
--- /dev/null
+++ b/filters.go
@@ -0,0 +1,73 @@
+package main
+
+// The two filters: in process for the forge's pages, as programs for cgit.
+
+import (
+ "bytes"
+ "fmt"
+ "html/template"
+ "io"
+ "log"
+ "os"
+ "os/exec"
+ "path"
+
+ "github.com/yuin/goldmark"
+)
+
+// Raw HTML is left unrendered, goldmark's default, which is what makes user
+// text safe to hand it.
+var markdown = goldmark.New()
+
+func renderMarkdown(source string) template.HTML {
+ var buf bytes.Buffer
+ if err := markdown.Convert([]byte(source), &buf); err != nil {
+ log.Printf("markdown: %v", err)
+ return template.HTML(template.HTMLEscapeString(source))
+ }
+ return template.HTML(buf.String())
+}
+
+// runMarkdown is the about-filter: markdown on stdin, HTML on stdout.
+func runMarkdown() int {
+ source, err := io.ReadAll(os.Stdin)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, "md:", err)
+ return 1
+ }
+ if err := markdown.Convert(source, os.Stdout); err != nil {
+ // A readable page beats an empty one.
+ fmt.Fprintln(os.Stderr, "md:", err)
+ template.HTMLEscape(os.Stdout, source)
+ return 1
+ }
+ return 0
+}
+
+// runHighlight is the source-filter: cgit's bundled one issues a command line
+// the installed highlight refuses, silently.
+func runHighlight(args []string) int {
+ source, err := io.ReadAll(os.Stdin)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, "highlight:", err)
+ return 1
+ }
+ name := "source"
+ if len(args) > 0 && args[0] != "" {
+ name = path.Base(args[0])
+ }
+ // --force: an unknown syntax comes back as escaped text, not as nothing.
+ cmd := exec.Command("highlight", "--fragment", "--force", "--out-format=html", "--syntax-by-name="+name)
+ cmd.Stdin = bytes.NewReader(source)
+ cmd.Stderr = os.Stderr
+ out, err := cmd.Output()
+ if err != nil || len(bytes.TrimSpace(out)) == 0 {
+ if err != nil {
+ fmt.Fprintln(os.Stderr, "highlight:", err)
+ }
+ template.HTMLEscape(os.Stdout, source)
+ return 0
+ }
+ os.Stdout.Write(out)
+ return 0
+}