From f25ee52a8bc9cc9b84dfaa3882a7ed3cacd79bc8 Mon Sep 17 00:00:00 2001 From: Jamie Hurst Date: Mon, 27 Oct 2025 10:52:56 +0000 Subject: [PATCH] Configurable excerpt through environment variables for index page --- README.md | 1 + internal/app/app.go | 6 ++++++ internal/app/controller/web/index.go | 5 +++++ internal/app/model/journal.go | 25 +++---------------------- internal/app/model/journal_test.go | 24 ++++++++++++------------ web/templates/index.html.tmpl | 2 +- 6 files changed, 28 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index 2b817fb..c52f8e8 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,7 @@ The application uses environment variables to configure all aspects. * `J_DB_PATH` - Path to SQLite DB - default is `$GOPATH/data/journal.db` * `J_DESCRIPTION` - Set the HTML description of the Journal * `J_EDIT` - Set to `0` to disable article modification +* `J_EXCERPT_WORDS` - The length of the article shown as a preview/excerpt in the index, default `50` * `J_GA_CODE` - Google Analytics tag value, starts with `UA-`, or ignore to disable Google Analytics * `J_PORT` - Port to expose over HTTP, default is `3000` * `J_THEME` - Theme to use from within the _web/themes_ folder, defaults to `default` diff --git a/internal/app/app.go b/internal/app/app.go index 2e583bc..6fabe83 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -37,6 +37,7 @@ type Configuration struct { Description string EnableCreate bool EnableEdit bool + ExcerptWords int GoogleAnalyticsCode string Port string SSLCertificate string @@ -55,6 +56,7 @@ func DefaultConfiguration() Configuration { Description: "A private journal containing Jamie's innermost thoughts", EnableCreate: true, EnableEdit: true, + ExcerptWords: 50, GoogleAnalyticsCode: "", Port: "3000", SSLCertificate: "", @@ -88,6 +90,10 @@ func ApplyEnvConfiguration(config *Configuration) { if enableEdit == "0" { config.EnableEdit = false } + excerptWords, _ := strconv.Atoi(os.Getenv("J_EXCERPT_WORDS")) + if excerptWords > 0 { + config.ExcerptWords = excerptWords + } config.GoogleAnalyticsCode = os.Getenv("J_GA_CODE") port := os.Getenv("J_PORT") if port != "" { diff --git a/internal/app/controller/web/index.go b/internal/app/controller/web/index.go index e134ee4..052c967 100644 --- a/internal/app/controller/web/index.go +++ b/internal/app/controller/web/index.go @@ -18,6 +18,7 @@ type Index struct { type indexTemplateData struct { Container interface{} + Excerpt func(model.Journal) string Journals []model.Journal Pages []int Pagination database.PaginationDisplay @@ -49,6 +50,10 @@ func (c *Index) Run(response http.ResponseWriter, request *http.Request) { i++ } + data.Excerpt = func(j model.Journal) string { + return j.GetHTMLExcerpt(container.Configuration.ExcerptWords) + } + c.SaveSession(response) template, _ := template.ParseFiles( "./web/templates/_layout/default.html.tmpl", diff --git a/internal/app/model/journal.go b/internal/app/model/journal.go index 4d52b87..a13fb33 100644 --- a/internal/app/model/journal.go +++ b/internal/app/model/journal.go @@ -52,27 +52,8 @@ func (j Journal) GetEditableDate() string { return re.FindString(j.Date) } -// GetExcerpt returns a small extract of the entry as plain text -func (j Journal) GetExcerpt() string { - strip := regexp.MustCompile("\b+") - // Markdown handling - replace newlines with spaces - text := strings.ReplaceAll(j.Content, "\n", " ") - text = strip.ReplaceAllString(text, " ") - - // Clean up multiple spaces - spaceRegex := regexp.MustCompile(`\s+`) - text = spaceRegex.ReplaceAllString(text, " ") - - words := strings.Split(text, " ") - - if len(words) > 50 { - return strings.Join(words[:50], " ") + "..." - } - return strings.TrimSpace(strings.Join(words, " ")) -} - // GetHTMLExcerpt returns a small extract of the entry rendered as HTML -func (j Journal) GetHTMLExcerpt() string { +func (j Journal) GetHTMLExcerpt(maxWords int) string { if j.Content == "" { return "" } @@ -86,7 +67,7 @@ func (j Journal) GetHTMLExcerpt() string { for _, paragraph := range paragraphs { // Skip if we've already got 50+ words - if wordCount >= 50 { + if wordCount >= maxWords { break } @@ -98,7 +79,7 @@ func (j Journal) GetHTMLExcerpt() string { lineWords := strings.Fields(line) // Calculate how many words we can take from this line - wordsToTake := 50 - wordCount + wordsToTake := maxWords - wordCount if wordsToTake <= 0 { break } diff --git a/internal/app/model/journal_test.go b/internal/app/model/journal_test.go index 748dde6..11274d9 100644 --- a/internal/app/model/journal_test.go +++ b/internal/app/model/journal_test.go @@ -49,42 +49,42 @@ func TestJournal_GetEditableDate(t *testing.T) { } } -func TestJournal_GetExcerpt(t *testing.T) { +func TestJournal_GetHTMLExcerpt(t *testing.T) { tables := []struct { input string output string }{ - {"Some simple text", "Some simple text"}, - {"Multiple\n\nparagraphs, some with\n\nmultiple words", "Multiple paragraphs, some with multiple words"}, + {"Some **bold** text", "

Some bold text

\n"}, + {"Multiple\n\nparagraphs", "

Multiple

\n\n

paragraphs

\n"}, {"", ""}, - {"\n\n", ""}, - {"a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x y z", "a b c d e f g h i j k l m n o p q r s t u v w x y z a b c d e f g h i j k l m n o p q r s t u v w x..."}, + {"*Italic* and **bold**", "

Italic and bold

\n"}, + {"Line 1\nLine 2\nLine 3", "

Line 1\nLine 2\nLine 3

\n"}, } for _, table := range tables { j := Journal{Content: table.input} - actual := j.GetExcerpt() + actual := j.GetHTMLExcerpt(50) if actual != table.output { - t.Errorf("Expected GetExcerpt() to produce result of '%s', got '%s'", table.output, actual) + t.Errorf("Expected GetHTMLExcerpt() to produce result of '%s', got '%s'", table.output, actual) } } } -func TestJournal_GetHTMLExcerpt(t *testing.T) { +func TestJournal_GetHTMLExcerpt_ShortWords(t *testing.T) { tables := []struct { input string output string }{ - {"Some **bold** text", "

Some bold text

\n"}, + {"Some **bold** text", "

Some bold

\n"}, {"Multiple\n\nparagraphs", "

Multiple

\n\n

paragraphs

\n"}, {"", ""}, - {"*Italic* and **bold**", "

Italic and bold

\n"}, - {"Line 1\nLine 2\nLine 3", "

Line 1\nLine 2\nLine 3

\n"}, + {"*Italic* and **bold**", "

Italic and…

\n"}, + {"Line 1\nLine 2\nLine 3", "

Line 1

\n"}, } for _, table := range tables { j := Journal{Content: table.input} - actual := j.GetHTMLExcerpt() + actual := j.GetHTMLExcerpt(2) if actual != table.output { t.Errorf("Expected GetHTMLExcerpt() to produce result of '%s', got '%s'", table.output, actual) } diff --git a/web/templates/index.html.tmpl b/web/templates/index.html.tmpl index 36d35c1..4229f72 100644 --- a/web/templates/index.html.tmpl +++ b/web/templates/index.html.tmpl @@ -13,7 +13,7 @@ {{.GetDate}}

- {{.GetHTMLExcerpt}} + {{call $.Excerpt . }} {{if $enableEdit}}Edit{{end}}

Read More