Article content with images having query parameters:
+

More images with various query parameters:
+

Image without query parameters:
+
Images with various other params:
+

diff --git a/internal/reader/rewrite/content_rewrite.go b/internal/reader/rewrite/content_rewrite.go
index 4d806dad..fab9cedb 100644
--- a/internal/reader/rewrite/content_rewrite.go
+++ b/internal/reader/rewrite/content_rewrite.go
@@ -94,6 +94,8 @@ func (rule rule) applyRule(entryURL string, entry *model.Entry) {
entry.Title = titlelize(entry.Title)
case "fix_ghost_cards":
entry.Content = fixGhostCards(entry.Content)
+ case "strip_image_query_params":
+ entry.Content = stripImageQueryParams(entry.Content)
}
}
diff --git a/internal/reader/rewrite/content_rewrite_functions.go b/internal/reader/rewrite/content_rewrite_functions.go
index a3858270..6416fe79 100644
--- a/internal/reader/rewrite/content_rewrite_functions.go
+++ b/internal/reader/rewrite/content_rewrite_functions.go
@@ -10,6 +10,7 @@ import (
"log/slog"
"net/url"
"regexp"
+ "strconv"
"strings"
"unicode"
@@ -547,3 +548,50 @@ func fixGhostCards(entryContent string) string {
output, _ := doc.FindMatcher(goquery.Single("body")).Html()
return strings.TrimSpace(output)
}
+
+func stripImageQueryParams(entryContent string) string {
+ doc, err := goquery.NewDocumentFromReader(strings.NewReader(entryContent))
+ if err != nil {
+ return entryContent
+ }
+
+ changed := false
+
+ doc.Find("img").Each(func(i int, img *goquery.Selection) {
+ srcAttr, exists := img.Attr("src")
+ if !exists {
+ return
+ }
+
+ parsedURL, err := url.Parse(srcAttr)
+ if err != nil {
+ return
+ }
+
+ // Only strip query parameters if this is a blurry placeholder image
+ if parsedURL.RawQuery != "" {
+ queryParams, err := url.ParseQuery(parsedURL.RawQuery)
+ if err != nil {
+ return
+ }
+
+ // Check if there's a blur parameter with a non-zero value
+ blurValues, hasBlur := queryParams["blur"]
+ if hasBlur && len(blurValues) > 0 {
+ blurValue, err := strconv.Atoi(blurValues[0])
+ if err == nil && blurValue > 0 {
+ parsedURL.RawQuery = ""
+ img.SetAttr("src", parsedURL.String())
+ changed = true
+ }
+ }
+ }
+ })
+
+ if changed {
+ output, _ := doc.FindMatcher(goquery.Single("body")).Html()
+ return output
+ }
+
+ return entryContent
+}
diff --git a/internal/reader/rewrite/content_rewrite_test.go b/internal/reader/rewrite/content_rewrite_test.go
index 307dd747..9106fea9 100644
--- a/internal/reader/rewrite/content_rewrite_test.go
+++ b/internal/reader/rewrite/content_rewrite_test.go
@@ -1248,3 +1248,158 @@ func TestFixGhostCardMultipleSplit(t *testing.T) {
t.Errorf(`Not expected output: got "%+v" instead of "%+v"`, testEntry, controlEntry)
}
}
+
+func TestStripImageQueryParams(t *testing.T) {
+ testEntry := &model.Entry{
+ URL: "https://example.org/article",
+ Title: `News Article Title`,
+ Content: `
+ Article content with images having query parameters: More images with various query parameters: Image without query parameters: Images with various other params: Article content with images having query parameters: More images with various query parameters: Image without query parameters: Images with various other params:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
No images here:
+No images here:
+Edge cases for image query parameter stripping:
+ + +Edge cases for image query parameter stripping:
+ + +Testing query parameter stripping:
+ + +Testing query parameter stripping:
+ + +