1
0
Fork 0
mirror of https://github.com/miniflux/v2.git synced 2025-06-27 16:36:00 +00:00

feat(sanitizer): add support for fetchpriority and decoding attributes in img tags

This commit is contained in:
Frédéric Guillot 2025-06-09 20:07:33 -07:00
parent d59990f1dd
commit 21d22d7f0b
2 changed files with 117 additions and 1 deletions

View file

@ -46,7 +46,7 @@ var (
"h6": {"id"}, "h6": {"id"},
"hr": {}, "hr": {},
"iframe": {"width", "height", "frameborder", "src", "allowfullscreen"}, "iframe": {"width", "height", "frameborder", "src", "allowfullscreen"},
"img": {"alt", "title", "src", "srcset", "sizes", "width", "height"}, "img": {"alt", "title", "src", "srcset", "sizes", "width", "height", "fetchpriority", "decoding"},
"ins": {}, "ins": {},
"kbd": {}, "kbd": {},
"li": {"id"}, "li": {"id"},
@ -234,6 +234,18 @@ func sanitizeAttributes(baseURL, tagName string, attributes []html.Attribute, sa
continue continue
} }
if tagName == "img" && attribute.Key == "fetchpriority" {
if !isValidFetchPriorityValue(value) {
continue
}
}
if tagName == "img" && attribute.Key == "decoding" {
if !isValidDecodingValue(value) {
continue
}
}
if (tagName == "img" || tagName == "source") && attribute.Key == "srcset" { if (tagName == "img" || tagName == "source") && attribute.Key == "srcset" {
value = sanitizeSrcsetAttr(baseURL, value) value = sanitizeSrcsetAttr(baseURL, value)
} }
@ -540,3 +552,13 @@ func getIntegerAttributeValue(name string, attributes []html.Attribute) int {
} }
return 0 return 0
} }
func isValidFetchPriorityValue(value string) bool {
allowedValues := []string{"high", "low", "auto"}
return slices.Contains(allowedValues, value)
}
func isValidDecodingValue(value string) bool {
allowedValues := []string{"sync", "async", "auto"}
return slices.Contains(allowedValues, value)
}

View file

@ -139,6 +139,100 @@ func TestImgWithSrcsetAndNoSrcAttribute(t *testing.T) {
} }
} }
func TestImgWithFetchPriorityAttribute(t *testing.T) {
cases := []struct {
input string
expected string
}{
{
`<img src="https://example.org/image.png" fetchpriority="high">`,
`<img src="https://example.org/image.png" fetchpriority="high" loading="lazy">`,
},
{
`<img src="https://example.org/image.png" fetchpriority="low">`,
`<img src="https://example.org/image.png" fetchpriority="low" loading="lazy">`,
},
{
`<img src="https://example.org/image.png" fetchpriority="auto">`,
`<img src="https://example.org/image.png" fetchpriority="auto" loading="lazy">`,
},
}
for _, tc := range cases {
output := SanitizeHTMLWithDefaultOptions("http://example.org/", tc.input)
if output != tc.expected {
t.Errorf(`Wrong output for input %q: expected %q, got %q`, tc.input, tc.expected, output)
}
}
}
func TestImgWithInvalidFetchPriorityAttribute(t *testing.T) {
input := `<img src="https://example.org/image.png" fetchpriority="invalid">`
expected := `<img src="https://example.org/image.png" loading="lazy">`
output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
if output != expected {
t.Errorf(`Wrong output: expected %q, got %q`, expected, output)
}
}
func TestNonImgWithFetchPriorityAttribute(t *testing.T) {
input := `<p fetchpriority="high">Text</p>`
expected := `<p>Text</p>`
output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
if output != expected {
t.Errorf(`Wrong output: expected %q, got %q`, expected, output)
}
}
func TestImgWithDecodingAttribute(t *testing.T) {
cases := []struct {
input string
expected string
}{
{
`<img src="https://example.org/image.png" decoding="sync">`,
`<img src="https://example.org/image.png" decoding="sync" loading="lazy">`,
},
{
`<img src="https://example.org/image.png" decoding="async">`,
`<img src="https://example.org/image.png" decoding="async" loading="lazy">`,
},
{
`<img src="https://example.org/image.png" decoding="auto">`,
`<img src="https://example.org/image.png" decoding="auto" loading="lazy">`,
},
}
for _, tc := range cases {
output := SanitizeHTMLWithDefaultOptions("http://example.org/", tc.input)
if output != tc.expected {
t.Errorf(`Wrong output for input %q: expected %q, got %q`, tc.input, tc.expected, output)
}
}
}
func TestImgWithInvalidDecodingAttribute(t *testing.T) {
input := `<img src="https://example.org/image.png" decoding="invalid">`
expected := `<img src="https://example.org/image.png" loading="lazy">`
output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
if output != expected {
t.Errorf(`Wrong output: expected %q, got %q`, expected, output)
}
}
func TestNonImgWithDecodingAttribute(t *testing.T) {
input := `<p decoding="async">Text</p>`
expected := `<p>Text</p>`
output := SanitizeHTMLWithDefaultOptions("http://example.org/", input)
if output != expected {
t.Errorf(`Wrong output: expected %q, got %q`, expected, output)
}
}
func TestSourceWithSrcsetAndMedia(t *testing.T) { func TestSourceWithSrcsetAndMedia(t *testing.T) {
input := `<picture><source media="(min-width: 800px)" srcset="elva-800w.jpg"></picture>` input := `<picture><source media="(min-width: 800px)" srcset="elva-800w.jpg"></picture>`
expected := `<picture><source media="(min-width: 800px)" srcset="http://example.org/elva-800w.jpg"></picture>` expected := `<picture><source media="(min-width: 800px)" srcset="http://example.org/elva-800w.jpg"></picture>`