From 1adeb1660d8c370196160badf245d5094c29d9ea Mon Sep 17 00:00:00 2001 From: StJudeWasHere <707925+StJudeWasHere@users.noreply.github.com> Date: Thu, 17 Oct 2024 10:39:37 +0200 Subject: [PATCH] Check if images have size attributes --- internal/issues/errors/errors.go | 1 + internal/issues/page/images.go | 39 +++++++++++++ internal/issues/page/images_test.go | 87 +++++++++++++++++++++++++++++ internal/issues/page/reporters.go | 1 + migrations/0065_img_size.down.sql | 1 + migrations/0065_img_size.up.sql | 1 + translations/translation.en.yaml | 5 +- 7 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 migrations/0065_img_size.down.sql create mode 100644 migrations/0065_img_size.up.sql diff --git a/internal/issues/errors/errors.go b/internal/issues/errors/errors.go index 6ab9eee..e9e1642 100644 --- a/internal/issues/errors/errors.go +++ b/internal/issues/errors/errors.go @@ -81,4 +81,5 @@ const ( ErrorMissingImgElement // Pages with Picture missing the img element ErrorMetasInBody // Pages with meta tags in the document's body ErrorNosnippet // Pages with the nosnippet directive + ErrorImgWithoutSize // Pages with img elements that have no size attribtues ) diff --git a/internal/issues/page/images.go b/internal/issues/page/images.go index 54e5027..0aca71d 100644 --- a/internal/issues/page/images.go +++ b/internal/issues/page/images.go @@ -133,3 +133,42 @@ func NewMissingImgTagInPictureReporter() *models.PageIssueReporter { Callback: c, } } + +// Returns a report_manager.PageIssueReporter with a callback function to check +// if a page has img elements without size attributes. +func NewImgWithoutSizeReporter() *models.PageIssueReporter { + c := func(pageReport *models.PageReport, htmlNode *html.Node, header *http.Header) bool { + if !pageReport.Crawled { + return false + } + + if pageReport.MediaType != "text/html" { + return false + } + + e := htmlquery.Find(htmlNode, "//img") + for _, n := range e { + s := htmlquery.SelectAttr(n, "sizes") + if s != "" { + continue + } + + w := htmlquery.SelectAttr(n, "width") + if w == "" { + return true + } + + h := htmlquery.SelectAttr(n, "width") + if h == "" { + return true + } + } + + return false + } + + return &models.PageIssueReporter{ + ErrorType: errors.ErrorImgWithoutSize, + Callback: c, + } +} diff --git a/internal/issues/page/images_test.go b/internal/issues/page/images_test.go index 93055e7..fdb3e01 100644 --- a/internal/issues/page/images_test.go +++ b/internal/issues/page/images_test.go @@ -264,3 +264,90 @@ func TestMissingImgTagInPictureReporterIssues(t *testing.T) { t.Errorf("reportsIssue should be true") } } + +// Test the NewImgWithoutSizeReporter reporter with a pageReport that the img elements +// with size attributes. The reporter should not report the issue. +func TestImgWithoutSizeReporterNoIssues(t *testing.T) { + pageReport := &models.PageReport{ + Crawled: true, + MediaType: "text/html", + } + + reporter := page.NewImgWithoutSizeReporter() + if reporter.ErrorType != errors.ErrorImgWithoutSize { + t.Errorf("error type is not correct") + } + + source := ` + + + + + + +` + + doc, err := html.Parse(strings.NewReader(source)) + if err != nil { + t.Errorf("error parsing html source") + } + + reportsIssue := reporter.Callback(pageReport, doc, &http.Header{}) + + if reportsIssue == true { + t.Errorf("reportsIssue should be false") + } +} + +// Test the NewImgWithoutSizeReporter reporter with a pageReport that the img elements +// without size attributes. The reporter should report the issue. +func TestImgWithoutSizeReporterIssues(t *testing.T) { + pageReport := &models.PageReport{ + Crawled: true, + MediaType: "text/html", + } + + reporter := page.NewImgWithoutSizeReporter() + if reporter.ErrorType != errors.ErrorImgWithoutSize { + t.Errorf("error type is not correct") + } + + source := ` + + + + + +` + + doc, err := html.Parse(strings.NewReader(source)) + if err != nil { + t.Errorf("error parsing html source") + } + + reportsIssue := reporter.Callback(pageReport, doc, &http.Header{}) + + if reportsIssue == false { + t.Errorf("reportsIssue should be true") + } + + // Test img only with the height attribute. + source = ` + + + + + +` + + doc, err = html.Parse(strings.NewReader(source)) + if err != nil { + t.Errorf("error parsing html source") + } + + reportsIssue = reporter.Callback(pageReport, doc, &http.Header{}) + + if reportsIssue == false { + t.Errorf("reportsIssue should be true") + } +} diff --git a/internal/issues/page/reporters.go b/internal/issues/page/reporters.go index e845417..48f86be 100644 --- a/internal/issues/page/reporters.go +++ b/internal/issues/page/reporters.go @@ -50,6 +50,7 @@ func GetAllReporters() []*models.PageIssueReporter { NewLargeImageReporter(), NewNoImageIndexReporter(), NewMissingImgTagInPictureReporter(), + NewImgWithoutSizeReporter(), // Add language issue reporters NewInvalidLangReporter(), diff --git a/migrations/0065_img_size.down.sql b/migrations/0065_img_size.down.sql new file mode 100644 index 0000000..31bdd1e --- /dev/null +++ b/migrations/0065_img_size.down.sql @@ -0,0 +1 @@ +DELETE FROM issue_types WHERE id = 73; \ No newline at end of file diff --git a/migrations/0065_img_size.up.sql b/migrations/0065_img_size.up.sql new file mode 100644 index 0000000..6fd9672 --- /dev/null +++ b/migrations/0065_img_size.up.sql @@ -0,0 +1 @@ +INSERT INTO issue_types (id, type, priority) VALUES(73, "ERROR_IMG_SIZE_ATTR", 3); \ No newline at end of file diff --git a/translations/translation.en.yaml b/translations/translation.en.yaml index 1dbeb46..e0a4896 100644 --- a/translations/translation.en.yaml +++ b/translations/translation.en.yaml @@ -238,4 +238,7 @@ ERROR_METAS_IN_BODY: Pages with meta tags in the document's body ERROR_METAS_IN_BODY_DESC: Pages that have meta tags in the document's body. The meta tags must be placed in the head section of the document, otherwise they may get ignored by browsers as well as search engines, causing indexability issues. ERROR_NOSNIPPET: Pages with the nosnippet directive -ERROR_NOSNIPPET_DESC: The nosnippet or max-snippet:0 directives tell search engines not to display a text snippet or video preview in the search results. Review these pages to make sure this is the wanted behavior. \ No newline at end of file +ERROR_NOSNIPPET_DESC: The nosnippet or max-snippet:0 directives tell search engines not to display a text snippet or video preview in the search results. Review these pages to make sure this is the wanted behavior. + +ERROR_IMG_SIZE_ATTR: Pages containing images missing size attributes +ERROR_IMG_SIZE_ATTR_DESC: Not setting the size attributes for images can cause layout shifts as the page loads, which can negatively impact user experience as well as SEO. Make sure your images have the corresponding size attributes in place. \ No newline at end of file