From 67678f9024940ce4bce7ef29a6316f56fe6f924e Mon Sep 17 00:00:00 2001 From: Steven Date: Wed, 31 Aug 2022 11:09:52 -0400 Subject: [PATCH 1/6] Change `alt` to required in `next/future/image` --- docs/api-reference/next/future/image.md | 8 ++++++++ packages/next/client/future/image.tsx | 6 ++++++ .../image-future/default/pages/missing-alt.js | 13 +++++++++++++ .../image-future/default/test/index.test.ts | 10 ++++++++++ 4 files changed, 37 insertions(+) create mode 100644 test/integration/image-future/default/pages/missing-alt.js diff --git a/docs/api-reference/next/future/image.md b/docs/api-reference/next/future/image.md index ee395f9618a..90a9c74a9e9 100644 --- a/docs/api-reference/next/future/image.md +++ b/docs/api-reference/next/future/image.md @@ -9,6 +9,7 @@ description: Try the latest Image Optimization with the experimental `next/futur | Version | Changes | | --------- | -------------------------------------------- | +| `v12.3.0` | Changed `alt` property to required. | | `v12.2.4` | Support for `fill` property added. | | `v12.2.0` | Experimental `next/future/image` introduced. | @@ -43,6 +44,7 @@ Compared to `next/image`, the new `next/future/image` component has the followin - Removes `lazyBoundary` prop since there is no native equivalent - Removes `lazyRoot` prop since there is no native equivalent - Removes `loader` config in favor of [`loader`](#loader) prop +- Changed `alt` prop from optional to required ## Known Browser Bugs @@ -175,6 +177,12 @@ The `height` property represents the _rendered_ height in pixels, so it will aff Required, except for [statically imported images](/docs/basic-features/image-optimization.md#local-images) or images with the [`fill` property](#fill). +### alt + +The `alt` property is used to describe the image for screen readers and search engines. It is also the fallback text if images have been disabled or an error occurs while loading the image. + +It should contain replacement text that could be used instead of the image. It is not meant to supplement the image and should not repeat information that is already provided in the captions above or below the image. + ## Optional Props The `` component accepts a number of additional properties beyond those which are required. This section describes the most commonly-used properties of the Image component. Find details about more rarely-used properties in the [Advanced Props](#advanced-props) section. diff --git a/packages/next/client/future/image.tsx b/packages/next/client/future/image.tsx index 3031fcd7b9d..dbcc1527d5c 100644 --- a/packages/next/client/future/image.tsx +++ b/packages/next/client/future/image.tsx @@ -103,6 +103,7 @@ export type ImageProps = Omit< 'src' | 'srcSet' | 'ref' | 'width' | 'height' | 'loading' > & { src: string | StaticImport + alt: string width?: number | string height?: number | string fill?: boolean @@ -392,6 +393,11 @@ const ImageElement = ({ img ) } + if (img.getAttribute('alt') === null) { + console.error( + `Image is missing required "alt" property. Please add Alternative Text to describe the image for screen readers and search engines.` + ) + } } if (img.complete) { handleLoading( diff --git a/test/integration/image-future/default/pages/missing-alt.js b/test/integration/image-future/default/pages/missing-alt.js new file mode 100644 index 00000000000..7b48115e430 --- /dev/null +++ b/test/integration/image-future/default/pages/missing-alt.js @@ -0,0 +1,13 @@ +import React from 'react' +import Image from 'next/future/image' +import testJPG from '../public/test.jpg' + +export default function Page() { + return ( +
+

Missing alt

+ + +
+ ) +} diff --git a/test/integration/image-future/default/test/index.test.ts b/test/integration/image-future/default/test/index.test.ts index cdbe51f5f46..c5b3deb535a 100644 --- a/test/integration/image-future/default/test/index.test.ts +++ b/test/integration/image-future/default/test/index.test.ts @@ -685,6 +685,16 @@ function runTests(mode) { ) }) + it('should show missing alt error', async () => { + const browser = await webdriver(appPort, '/missing-alt') + + expect(await hasRedbox(browser)).toBe(false) + + await check(async () => { + return (await browser.log()).map((log) => log.message).join('\n') + }, /Image is missing required "alt" property/gm) + }) + it('should show error when missing width prop', async () => { const browser = await webdriver(appPort, '/missing-width') From c5c27777213ab687fecba3aeeb2ffecd275f3079 Mon Sep 17 00:00:00 2001 From: Steven Date: Wed, 31 Aug 2022 11:20:38 -0400 Subject: [PATCH 2/6] Fix ts types --- packages/next/client/future/image.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/next/client/future/image.tsx b/packages/next/client/future/image.tsx index dbcc1527d5c..30031cf1055 100644 --- a/packages/next/client/future/image.tsx +++ b/packages/next/client/future/image.tsx @@ -100,7 +100,7 @@ function isStaticImport(src: string | StaticImport): src is StaticImport { export type ImageProps = Omit< JSX.IntrinsicElements['img'], - 'src' | 'srcSet' | 'ref' | 'width' | 'height' | 'loading' + 'src' | 'srcSet' | 'ref' | 'alt' | 'width' | 'height' | 'loading' > & { src: string | StaticImport alt: string @@ -117,7 +117,7 @@ export type ImageProps = Omit< onLoadingComplete?: OnLoadingComplete } -type ImageElementProps = Omit & { +type ImageElementProps = Omit & { srcString: string imgAttributes: GenImgAttrsResult heightInt: number | undefined From 7a36e867934f220b46cfcabd76b243e5db3aa878 Mon Sep 17 00:00:00 2001 From: Steven Date: Wed, 31 Aug 2022 11:42:53 -0400 Subject: [PATCH 3/6] Update typescript test --- .../image-future/typescript/pages/invalid.tsx | 20 ++++++++++++++++--- .../image-future/typescript/pages/valid.tsx | 18 ++++++++++++++--- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/test/integration/image-future/typescript/pages/invalid.tsx b/test/integration/image-future/typescript/pages/invalid.tsx index 85a60daa677..9de4e34c16f 100644 --- a/test/integration/image-future/typescript/pages/invalid.tsx +++ b/test/integration/image-future/typescript/pages/invalid.tsx @@ -5,20 +5,34 @@ const Invalid = () => { return (

Invalid TS

- + invalid-src invalid-width + /> invalid-placeholder + /> +

This is the invalid usage

) diff --git a/test/integration/image-future/typescript/pages/valid.tsx b/test/integration/image-future/typescript/pages/valid.tsx index 2bc8a517a95..3dc5a311f9d 100644 --- a/test/integration/image-future/typescript/pages/valid.tsx +++ b/test/integration/image-future/typescript/pages/valid.tsx @@ -12,12 +12,14 @@ const Page = () => {

Valid TS

width-and-height-num width-and-height-str { /> quality-str { /> data-protocol placeholder-and-blur-data-url - + no-width-and-height object-src-with-placeholder - - + object-src-with-svg + object-src-with-avif Date: Wed, 31 Aug 2022 12:16:56 -0400 Subject: [PATCH 4/6] Add missing alt text --- test/production/typescript-basic/app/pages/image-import.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/production/typescript-basic/app/pages/image-import.tsx b/test/production/typescript-basic/app/pages/image-import.tsx index 5fe97473ec0..1cd82addc5e 100644 --- a/test/production/typescript-basic/app/pages/image-import.tsx +++ b/test/production/typescript-basic/app/pages/image-import.tsx @@ -6,9 +6,9 @@ export default function Page() { return ( <>

Example Image Usage

- +
- + ) } From b925a503fb339ee2004c2dabbbeaac1c2d5a4997 Mon Sep 17 00:00:00 2001 From: Steven Date: Wed, 31 Aug 2022 12:18:09 -0400 Subject: [PATCH 5/6] Add docs suggestion from SukkaW Co-authored-by: Sukka --- docs/api-reference/next/future/image.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/api-reference/next/future/image.md b/docs/api-reference/next/future/image.md index 90a9c74a9e9..ae59cc812a0 100644 --- a/docs/api-reference/next/future/image.md +++ b/docs/api-reference/next/future/image.md @@ -183,6 +183,8 @@ The `alt` property is used to describe the image for screen readers and search e It should contain replacement text that could be used instead of the image. It is not meant to supplement the image and should not repeat information that is already provided in the captions above or below the image. +If the image is decorative and doesn't present any information, the `alt` property should be an empty string (`alt=""`). See [A purely decorative image that doesn't add any information - HTML5 Spec](https://html.spec.whatwg.org/multipage/images.html#a-purely-decorative-image-that-doesn't-add-any-information) + ## Optional Props The `` component accepts a number of additional properties beyond those which are required. This section describes the most commonly-used properties of the Image component. Find details about more rarely-used properties in the [Advanced Props](#advanced-props) section. From a2b0663b08b81e11cf434debb2c8a9ea460d5e33 Mon Sep 17 00:00:00 2001 From: Steven Date: Wed, 31 Aug 2022 13:46:54 -0400 Subject: [PATCH 6/6] Update docs --- docs/api-reference/next/future/image.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/api-reference/next/future/image.md b/docs/api-reference/next/future/image.md index ae59cc812a0..29cb18803a8 100644 --- a/docs/api-reference/next/future/image.md +++ b/docs/api-reference/next/future/image.md @@ -181,9 +181,11 @@ Required, except for [statically imported images](/docs/basic-features/image-opt The `alt` property is used to describe the image for screen readers and search engines. It is also the fallback text if images have been disabled or an error occurs while loading the image. -It should contain replacement text that could be used instead of the image. It is not meant to supplement the image and should not repeat information that is already provided in the captions above or below the image. +It should contain text that could replace the image [without changing the meaning of the page](https://html.spec.whatwg.org/multipage/images.html#general-guidelines). It is not meant to supplement the image and should not repeat information that is already provided in the captions above or below the image. -If the image is decorative and doesn't present any information, the `alt` property should be an empty string (`alt=""`). See [A purely decorative image that doesn't add any information - HTML5 Spec](https://html.spec.whatwg.org/multipage/images.html#a-purely-decorative-image-that-doesn't-add-any-information) +If the image is [purely decorative](https://html.spec.whatwg.org/multipage/images.html#a-purely-decorative-image-that-doesn't-add-any-information) or [not intended for the user](https://html.spec.whatwg.org/multipage/images.html#an-image-not-intended-for-the-user), the `alt` property should be an empty string (`alt=""`). + +[Learn more](https://html.spec.whatwg.org/multipage/images.html#alt) ## Optional Props