From 2fc958c47142b5e1d5646e018e3c434e73dc71c3 Mon Sep 17 00:00:00 2001 From: Sam Scholten Date: Wed, 17 Jun 2026 14:14:15 +1000 Subject: Add --footer flag for custom HTML footer in web UI Allows deploying with contextual links (e.g. blog post, homepage). Also adds links to live instance and blog post in README. --- cmds/serve.go | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'cmds/serve.go') diff --git a/cmds/serve.go b/cmds/serve.go index 92aa64c..59ec14d 100644 --- a/cmds/serve.go +++ b/cmds/serve.go @@ -51,6 +51,7 @@ type ServeCommand struct { RefreshInterval string ModelPath string Title string + Footer string // Parsed interval refreshInterval time.Duration @@ -93,6 +94,7 @@ func (c *ServeCommand) Init(args []string) error { fs.StringVar(&c.RefreshInterval, "refresh-interval", "24h", "Interval for background rescans (e.g., 24h, 1h)") fs.StringVar(&c.ModelPath, "model", "model.json", "Path to trained model JSON file") fs.StringVar(&c.Title, "title", "", "Custom title for the web interface") + fs.StringVar(&c.Footer, "footer", "", "Custom HTML footer for the web interface") if err := fs.Parse(args); err != nil { return err @@ -552,6 +554,7 @@ func (c *ServeCommand) handleLiveFeed(w http.ResponseWriter, r *http.Request) { "UpdatedAt": resultsTime.Format("2006-01-02 15:04:05"), "Filter": filter, "Title": displayTitle(c.Title), + "Footer": footerHTML(c.Footer), } w.Header().Set("Content-Type", "text/html; charset=utf-8") @@ -567,8 +570,9 @@ func (c *ServeCommand) handleTools(w http.ResponseWriter, r *http.Request) { } data := map[string]interface{}{ - "Page": "tools", - "Title": displayTitle(c.Title), + "Page": "tools", + "Title": displayTitle(c.Title), + "Footer": footerHTML(c.Footer), } w.Header().Set("Content-Type", "text/html; charset=utf-8") @@ -636,6 +640,7 @@ func (c *ServeCommand) handleScore(w http.ResponseWriter, r *http.Request) { "Score": score, "Threshold": threshold, "PageTitle": displayTitle(c.Title), + "Footer": footerHTML(c.Footer), } w.Header().Set("Content-Type", "text/html; charset=utf-8") @@ -701,6 +706,7 @@ func (c *ServeCommand) handleScan(w http.ResponseWriter, r *http.Request) { "Articles": scored, "Threshold": threshold, "PageTitle": displayTitle(c.Title), + "Footer": footerHTML(c.Footer), } w.Header().Set("Content-Type", "text/html; charset=utf-8") @@ -860,6 +866,13 @@ func displayTitle(custom string) string { return "ScholScan" } +func footerHTML(custom string) template.HTML { + if custom != "" { + return template.HTML(custom) + } + return "" +} + // extractTitleFromURL fetches the content from a URL and extracts the title from the HTML. // Designed to be resilient: tries multiple title sources, handles various URL formats, // and provides meaningful error feedback if extraction fails. @@ -966,6 +979,7 @@ func (c *ServeCommand) renderResultsError(w http.ResponseWriter, errMsg, title s "Error": errMsg, "Title": title, "PageTitle": displayTitle(c.Title), + "Footer": footerHTML(c.Footer), } w.Header().Set("Content-Type", "text/html; charset=utf-8") if err := c.tmpl.ExecuteTemplate(w, "results", data); err != nil { @@ -993,6 +1007,7 @@ func (c *ServeCommand) renderScanResultsError(w http.ResponseWriter, errMsg, fee "Error": errMsg, "FeedURL": feedURL, "PageTitle": displayTitle(c.Title), + "Footer": footerHTML(c.Footer), } w.Header().Set("Content-Type", "text/html; charset=utf-8") if err := c.tmpl.ExecuteTemplate(w, "results", data); err != nil { -- cgit v1.2.3