From 8b9edc4e712f3adbd9f9c503dfc5e4d627f763cd Mon Sep 17 00:00:00 2001 From: Jeff Wen <3297859+sinchang@users.noreply.github.com> Date: Wed, 28 Sep 2022 14:55:10 +0800 Subject: [PATCH] feat(a11y): add attribute role="img" to the svg element (#750) --- packages/babel-preset/src/index.test.ts | 24 ++-- packages/babel-preset/src/index.ts | 7 +- .../cli/src/__snapshots__/index.test.ts.snap | 132 +++++++++++++++--- .../cli/src/__snapshots__/util.test.ts.snap | 9 +- .../src/__snapshots__/transform.test.ts.snap | 109 +++++++++++++-- packages/plugin-jsx/src/index.test.ts | 8 +- .../src/__snapshots__/index.test.ts.snap | 9 +- .../src/__snapshots__/index.test.ts.snap | 15 +- 8 files changed, 253 insertions(+), 60 deletions(-) diff --git a/packages/babel-preset/src/index.test.ts b/packages/babel-preset/src/index.test.ts index 8460c9fe..18945f50 100644 --- a/packages/babel-preset/src/index.test.ts +++ b/packages/babel-preset/src/index.test.ts @@ -28,7 +28,7 @@ describe('preset', () => { ).toMatchInlineSnapshot(` "import * as React from \\"react\\"; - const SvgComponent = () => ; + const SvgComponent = () => ; export default SvgComponent;" `) @@ -45,7 +45,7 @@ describe('preset', () => { const SvgComponent = ({ title, titleId - }) => {title ? {title} : null}; + }) => {title ? {title} : null}; export default SvgComponent;" `) @@ -62,7 +62,7 @@ describe('preset', () => { const SvgComponent = ({ title, titleId - }) => {title === undefined ? Hello : title ? {title} : null}; + }) => {title === undefined ? Hello : title ? {title} : null}; export default SvgComponent;" `) @@ -77,7 +77,7 @@ describe('preset', () => { const SvgComponent = ({ title, titleId - }) => {title === undefined ? {\\"Hello\\"} : title ? {title} : null}; + }) => {title === undefined ? {\\"Hello\\"} : title ? {title} : null}; export default SvgComponent;" `) @@ -94,7 +94,7 @@ describe('preset', () => { const SvgComponent = ({ desc, descId - }) => {desc ? {desc} : null}; + }) => {desc ? {desc} : null}; export default SvgComponent;" `) @@ -111,7 +111,7 @@ describe('preset', () => { const SvgComponent = ({ desc, descId - }) => {desc === undefined ? Hello : desc ? {desc} : null}; + }) => {desc === undefined ? Hello : desc ? {desc} : null}; export default SvgComponent;" `) @@ -126,7 +126,7 @@ describe('preset', () => { const SvgComponent = ({ desc, descId - }) => {desc === undefined ? {\\"Hello\\"} : desc ? {desc} : null}; + }) => {desc === undefined ? {\\"Hello\\"} : desc ? {desc} : null}; export default SvgComponent;" `) @@ -146,7 +146,7 @@ describe('preset', () => { titleId, desc, descId - }) => {desc ? {desc} : null}{title ? {title} : null}; + }) => {desc ? {desc} : null}{title ? {title} : null}; export default SvgComponent;" `) @@ -163,7 +163,7 @@ describe('preset', () => { ).toMatchInlineSnapshot(` "import * as React from \\"react\\"; - const SvgComponent = () => ; + const SvgComponent = () => ; export default SvgComponent;" `) @@ -179,7 +179,7 @@ describe('preset', () => { ).toMatchInlineSnapshot(` "import * as React from \\"react\\"; - const SvgComponent = props => ; + const SvgComponent = props => ; export default SvgComponent;" `) @@ -195,7 +195,7 @@ describe('preset', () => { ).toMatchInlineSnapshot(` "import * as React from \\"react\\"; - const SvgComponent = props => ; + const SvgComponent = props => ; export default SvgComponent;" `) @@ -213,7 +213,7 @@ describe('preset', () => { "import * as React from \\"react\\"; import Svg from \\"react-native-svg\\"; - const SvgComponent = props => ; + const SvgComponent = props => ; export default SvgComponent;" `) diff --git a/packages/babel-preset/src/index.ts b/packages/babel-preset/src/index.ts index c77b2396..7a5b1b39 100644 --- a/packages/babel-preset/src/index.ts +++ b/packages/babel-preset/src/index.ts @@ -49,7 +49,12 @@ function replaceMapToValues(replaceMap: { [key: string]: string }): Value[] { const plugin = (_: ConfigAPI, opts: Options) => { let toRemoveAttributes = ['version'] - let toAddAttributes: Attribute[] = [] + let toAddAttributes: Attribute[] = [ + { + name: 'role', + value: 'img', + }, + ] if (opts.svgProps) { toAddAttributes = [...toAddAttributes, ...propsToAttributes(opts.svgProps)] diff --git a/packages/cli/src/__snapshots__/index.test.ts.snap b/packages/cli/src/__snapshots__/index.test.ts.snap index f05c6526..8bbce21b 100644 --- a/packages/cli/src/__snapshots__/index.test.ts.snap +++ b/packages/cli/src/__snapshots__/index.test.ts.snap @@ -10,7 +10,7 @@ exports[`cli should not override config with cli defaults 1`] = ` "import * as React from 'react' const SvgFile = () => ( - + ) @@ -35,7 +35,13 @@ exports[`cli should support --prettier-config as file 1`] = ` "import * as React from 'react' const SvgFile = (props) => ( - + ) @@ -49,7 +55,13 @@ exports[`cli should support --prettier-config as json 1`] = ` "import * as React from 'react' const SvgFile = (props) => ( - + ) @@ -63,7 +75,13 @@ exports[`cli should support --svgo-config as file 1`] = ` "import * as React from 'react' const SvgFile = (props) => ( - + {'Rectangle 5'} @@ -78,7 +96,13 @@ exports[`cli should support --svgo-config as json 1`] = ` "import * as React from 'react' const SvgFile = (props) => ( - + {'Rectangle 5'} @@ -145,7 +169,13 @@ exports[`cli should support stdin filepath 1`] = ` "import * as React from 'react' const SvgFile = (props) => ( - + ) @@ -163,6 +193,7 @@ const SvgFile = ({ desc, descId, ...props }) => ( width={48} height={1} xmlns=\\"http://www.w3.org/2000/svg\\" + role=\\"img\\" aria-describedby={descId} {...props} > @@ -180,7 +211,7 @@ exports[`cli should support various args: --expand-props none 1`] = ` "import * as React from 'react' const SvgFile = () => ( - + ) @@ -194,7 +225,13 @@ exports[`cli should support various args: --expand-props start 1`] = ` "import * as React from 'react' const SvgFile = (props) => ( - + ) @@ -213,6 +250,7 @@ const SvgFile = (props) => ( height=\\"1em\\" viewBox=\\"0 0 48 1\\" xmlns=\\"http://www.w3.org/2000/svg\\" + role=\\"img\\" {...props} > @@ -233,6 +271,7 @@ const SvgFile = (props) => ( height=\\"2em\\" viewBox=\\"0 0 48 1\\" xmlns=\\"http://www.w3.org/2000/svg\\" + role=\\"img\\" {...props} > @@ -253,6 +292,7 @@ const SvgFile = (props) => ( height={24} viewBox=\\"0 0 48 1\\" xmlns=\\"http://www.w3.org/2000/svg\\" + role=\\"img\\" {...props} > @@ -266,7 +306,13 @@ export default SvgFile exports[`cli should support various args: --jsx-runtime automatic 1`] = ` "const SvgFile = (props) => ( - + ) @@ -280,7 +326,13 @@ exports[`cli should support various args: --jsx-runtime classic-preact 1`] = ` "import { h } from 'preact' const SvgFile = (props) => ( - + ) @@ -295,7 +347,7 @@ exports[`cli should support various args: --native --expand-props none 1`] = ` import Svg, { Path } from 'react-native-svg' const SvgFile = () => ( - + ) @@ -315,6 +367,7 @@ const SvgFile = (props) => ( height={24} viewBox=\\"0 0 48 1\\" xmlns=\\"http://www.w3.org/2000/svg\\" + role=\\"img\\" {...props} > @@ -336,6 +389,7 @@ const SvgFile = (props, ref) => ( width={48} height={1} xmlns=\\"http://www.w3.org/2000/svg\\" + role=\\"img\\" ref={ref} {...props} > @@ -354,7 +408,13 @@ exports[`cli should support various args: --native 1`] = ` import Svg, { Path } from 'react-native-svg' const SvgFile = (props) => ( - + ) @@ -368,7 +428,12 @@ exports[`cli should support various args: --no-dimensions 1`] = ` "import * as React from 'react' const SvgFile = (props) => ( - + ) @@ -381,7 +446,7 @@ export default SvgFile exports[`cli should support various args: --no-prettier 1`] = ` "import * as React from \\"react\\"; -const SvgFile = props => ; +const SvgFile = props => ; export default SvgFile; " @@ -397,6 +462,7 @@ const SvgFile = (props) => ( viewBox=\\"0 0 48 1\\" xmlns=\\"http://www.w3.org/2000/svg\\" xmlnsXlink=\\"http://www.w3.org/1999/xlink\\" + role=\\"img\\" {...props} > {'Rectangle 5'} @@ -436,6 +502,7 @@ const SvgFile = (props, ref) => ( width={48} height={1} xmlns=\\"http://www.w3.org/2000/svg\\" + role=\\"img\\" ref={ref} {...props} > @@ -453,7 +520,13 @@ exports[`cli should support various args: --replace-attr-values "#063855=current "import * as React from 'react' const SvgFile = (props) => ( - + ) @@ -471,6 +544,7 @@ const SvgFile = (props) => ( width={48} height={1} xmlns=\\"http://www.w3.org/2000/svg\\" + role=\\"img\\" hidden={true} id=\\"hello\\" {...props} @@ -492,6 +566,7 @@ const SvgFile = ({ title, titleId, ...props }) => ( width={48} height={1} xmlns=\\"http://www.w3.org/2000/svg\\" + role=\\"img\\" aria-labelledby={titleId} {...props} > @@ -521,6 +596,7 @@ const SvgFile = ( width={48} height={1} xmlns=\\"http://www.w3.org/2000/svg\\" + role=\\"img\\" ref={ref} aria-describedby={descId} {...props} @@ -552,6 +628,7 @@ const SvgFile = ( width={48} height={1} xmlns=\\"http://www.w3.org/2000/svg\\" + role=\\"img\\" ref={ref} aria-labelledby={titleId} {...props} @@ -576,6 +653,7 @@ const SvgFile = (props: SVGProps, ref: Ref) => ( width={48} height={1} xmlns=\\"http://www.w3.org/2000/svg\\" + role=\\"img\\" ref={ref} {...props} > @@ -594,7 +672,13 @@ exports[`cli should support various args: --typescript 1`] = ` import { SVGProps } from 'react' const SvgFile = (props: SVGProps) => ( - + ) @@ -648,7 +732,13 @@ exports[`cli should work with a simple file 1`] = ` "import * as React from 'react' const SvgFile = (props) => ( - + ) @@ -662,7 +752,13 @@ exports[`cli should work with stdin 1`] = ` "import * as React from 'react' const SvgComponent = (props) => ( - + ) diff --git a/packages/cli/src/__snapshots__/util.test.ts.snap b/packages/cli/src/__snapshots__/util.test.ts.snap index 09d590d2..41fd0ff8 100644 --- a/packages/cli/src/__snapshots__/util.test.ts.snap +++ b/packages/cli/src/__snapshots__/util.test.ts.snap @@ -4,7 +4,13 @@ exports[`util #convertFile should convert a file 1`] = ` "import * as React from 'react' const SvgFile = (props) => ( - + ) @@ -22,6 +28,7 @@ const SvgFile = (props) => ( height=\\"1em\\" viewBox=\\"0 0 48 1\\" xmlns=\\"http://www.w3.org/2000/svg\\" + role=\\"img\\" {...props} > diff --git a/packages/core/src/__snapshots__/transform.test.ts.snap b/packages/core/src/__snapshots__/transform.test.ts.snap index 1c7355a3..578c0cdf 100644 --- a/packages/core/src/__snapshots__/transform.test.ts.snap +++ b/packages/core/src/__snapshots__/transform.test.ts.snap @@ -8,6 +8,7 @@ const SvgComponent = ({ desc, descId, ...props }) => ( width={88} height={88} xmlns=\\"http://www.w3.org/2000/svg\\" + role=\\"img\\" aria-describedby={descId} {...props} > @@ -32,7 +33,12 @@ exports[`convert config accepts options {"dimensions":false} 1`] = ` "import * as React from 'react' const SvgComponent = (props) => ( - + ( - + ( - + ( - + ( height=\\"2em\\" viewBox=\\"0 0 88 88\\" xmlns=\\"http://www.w3.org/2000/svg\\" + role=\\"img\\" {...props} > ( height={24} viewBox=\\"0 0 88 88\\" xmlns=\\"http://www.w3.org/2000/svg\\" + role=\\"img\\" {...props} > ( height=\\"1em\\" viewBox=\\"0 0 88 88\\" xmlns=\\"http://www.w3.org/2000/svg\\" + role=\\"img\\" {...props} > ( - + ( - + ( - + ( height={24} viewBox=\\"0 0 88 88\\" xmlns=\\"http://www.w3.org/2000/svg\\" + role=\\"img\\" {...props} > ( width={88} height={88} xmlns=\\"http://www.w3.org/2000/svg\\" + role=\\"img\\" ref={ref} {...props} > @@ -323,7 +358,13 @@ exports[`convert config accepts options {"native":true} 1`] = ` import Svg, { G, Path } from 'react-native-svg' const SvgComponent = (props) => ( - + ; +const SvgComponent = props => ; export default SvgComponent;" `; @@ -357,6 +398,7 @@ const SvgComponent = (props, ref) => ( width={88} height={88} xmlns=\\"http://www.w3.org/2000/svg\\" + role=\\"img\\" ref={ref} {...props} > @@ -381,7 +423,13 @@ exports[`convert config accepts options {"replaceAttrValues":{"none":"{black}"}} "import * as React from 'react' const SvgComponent = (props) => ( - + ( - + ( width={88} height={88} xmlns=\\"http://www.w3.org/2000/svg\\" + role=\\"img\\" a=\\"b\\" b={props.b} {...props} @@ -457,6 +512,7 @@ const SvgComponent = (props) => ( viewBox=\\"0 0 88 88\\" xmlns=\\"http://www.w3.org/2000/svg\\" xmlnsXlink=\\"http://www.w3.org/1999/xlink\\" + role=\\"img\\" {...props} > {'Dismiss'} @@ -490,6 +546,7 @@ const SvgComponent = ({ title, titleId, ...props }) => ( width={88} height={88} xmlns=\\"http://www.w3.org/2000/svg\\" + role=\\"img\\" aria-labelledby={titleId} {...props} > @@ -527,6 +584,7 @@ const SvgComponent = ({ desc, descId, ...props }) => ( style={{ position: 'absolute', }} + role=\\"img\\" aria-describedby={descId} {...props} > @@ -549,6 +607,7 @@ const SvgComponent = ({ title, titleId, ...props }) => ( style={{ position: 'absolute', }} + role=\\"img\\" aria-labelledby={titleId} {...props} > @@ -565,7 +624,13 @@ exports[`convert should convert 1`] = ` "import * as React from 'react' const SvgComponent = (props) => ( - + ( xmlnsXlink=\\"http://www.w3.org/1999/xlink\\" width={48} height={48} + role=\\"img\\" {...props} > @@ -655,7 +721,7 @@ exports[`convert should handle special SVG attributes 1`] = ` "import * as React from 'react' const SvgComponent = (props) => ( - + ) @@ -668,7 +734,13 @@ exports[`convert should not remove all style tags 1`] = ` "import * as React from 'react' const SvgComponent = (props) => ( - + ( enableBackground: 'new 0 0 25 25', }} xmlSpace=\\"preserve\\" + role=\\"img\\" {...props} > ( - + { expect(result).toMatchInlineSnapshot(` "import * as React from \\"react\\"; - const SvgComponent = () => {\\"Dismiss\\"}{\\"Created with Sketch.\\"}; + const SvgComponent = () => {\\"Dismiss\\"}{\\"Created with Sketch.\\"}; export default SvgComponent;" `) @@ -35,7 +35,7 @@ describe('plugin', () => { { componentName: 'SvgComponent' }, ) expect(result).toMatchInlineSnapshot(` - "const SvgComponent = () => {\\"Dismiss\\"}{\\"Created with Sketch.\\"}; + "const SvgComponent = () => {\\"Dismiss\\"}{\\"Created with Sketch.\\"}; export default SvgComponent;" `) @@ -50,7 +50,7 @@ describe('plugin', () => { expect(result).toMatchInlineSnapshot(` "import { h } from \\"preact\\"; - const SvgComponent = () => {\\"Dismiss\\"}{\\"Created with Sketch.\\"}; + const SvgComponent = () => {\\"Dismiss\\"}{\\"Created with Sketch.\\"}; export default SvgComponent;" `) @@ -77,7 +77,7 @@ describe('plugin', () => { expect(result).toMatchInlineSnapshot(` "import * as React from \\"react\\"; - const SvgComponent = () => {\\"Created with Sketch.\\"}; + const SvgComponent = () => {\\"Created with Sketch.\\"}; export default SvgComponent;" `) diff --git a/packages/rollup/src/__snapshots__/index.test.ts.snap b/packages/rollup/src/__snapshots__/index.test.ts.snap index fbc3b22c..7b38b405 100644 --- a/packages/rollup/src/__snapshots__/index.test.ts.snap +++ b/packages/rollup/src/__snapshots__/index.test.ts.snap @@ -11,7 +11,8 @@ var SvgFile = function SvgFile(props) { return /*#__PURE__*/React.createElement(\\"svg\\", _extends({ width: 48, height: 1, - xmlns: \\"http://www.w3.org/2000/svg\\" + xmlns: \\"http://www.w3.org/2000/svg\\", + role: \\"img\\" }, props), _path || (_path = /*#__PURE__*/React.createElement(\\"path\\", { d: \\"M0 0h48v1H0z\\", fill: \\"#063855\\", @@ -25,7 +26,7 @@ export default SvgFile;" exports[`rollup loader should convert file with previousExport of image plugin 1`] = ` "import * as React from \\"react\\"; -const SvgFile = props => ; +const SvgFile = props => ; export { SvgFile as ReactComponent }; var img = new Image(); @@ -36,7 +37,7 @@ export default img;" exports[`rollup loader should convert file with previousExport of url plugin 1`] = ` "import * as React from \\"react\\"; -const SvgFile = props => ; +const SvgFile = props => ; export { SvgFile as ReactComponent }; export default \\"data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22UTF-8%22%3F%3E%3Csvg%20width%3D%2248px%22%20height%3D%221px%22%20viewBox%3D%220%200%2048%201%22%20version%3D%221.1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%3E%20%20%20%20%20%20%20%20%3Ctitle%3ERectangle%205%3C%2Ftitle%3E%20%20%20%20%3Cdesc%3ECreated%20with%20Sketch.%3C%2Fdesc%3E%20%20%20%20%3Cdefs%3E%3C%2Fdefs%3E%20%20%20%20%3Cg%20id%3D%22Page-1%22%20stroke%3D%22none%22%20stroke-width%3D%221%22%20fill%3D%22none%22%20fill-rule%3D%22evenodd%22%3E%20%20%20%20%20%20%20%20%3Cg%20id%3D%2219-Separator%22%20transform%3D%22translate%28-129.000000%2C%20-156.000000%29%22%20fill%3D%22%23063855%22%3E%20%20%20%20%20%20%20%20%20%20%20%20%3Cg%20id%3D%22Controls%2FSettings%22%20transform%3D%22translate%2880.000000%2C%200.000000%29%22%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cg%20id%3D%22Content%22%20transform%3D%22translate%280.000000%2C%2064.000000%29%22%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cg%20id%3D%22Group%22%20transform%3D%22translate%2824.000000%2C%2056.000000%29%22%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Cg%20id%3D%22Group-2%22%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Crect%20id%3D%22Rectangle-5%22%20x%3D%2225%22%20y%3D%2236%22%20width%3D%2248%22%20height%3D%221%22%3E%3C%2Frect%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fg%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fg%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fg%3E%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Fg%3E%20%20%20%20%20%20%20%20%3C%2Fg%3E%20%20%20%20%3C%2Fg%3E%3C%2Fsvg%3E\\";" @@ -45,7 +46,7 @@ export default \\"data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20encoding% exports[`rollup loader should convert file without babel 1`] = ` "import * as React from \\"react\\"; -const SvgFile = props => ; +const SvgFile = props => ; export default SvgFile;" `; diff --git a/packages/webpack/src/__snapshots__/index.test.ts.snap b/packages/webpack/src/__snapshots__/index.test.ts.snap index 832dd4e6..0bc21025 100644 --- a/packages/webpack/src/__snapshots__/index.test.ts.snap +++ b/packages/webpack/src/__snapshots__/index.test.ts.snap @@ -9,7 +9,8 @@ var SvgIcon = function SvgIcon() { return _svg || (_svg = /*#__PURE__*/React.createElement(\\"svg\\", { width: 88, height: 88, - xmlns: \\"http://www.w3.org/2000/svg\\" + xmlns: \\"http://www.w3.org/2000/svg\\", + role: \\"img\\" }, /*#__PURE__*/React.createElement(\\"g\\", { stroke: \\"#063855\\", strokeWidth: 2, @@ -31,7 +32,8 @@ exports[`webpack loader transforms file (babel: false) 1`] = ` const SvgIcon = () => /*#__PURE__*/React.createElement(\\"svg\\", { width: 88, height: 88, - xmlns: \\"http://www.w3.org/2000/svg\\" + xmlns: \\"http://www.w3.org/2000/svg\\", + role: \\"img\\" }, /*#__PURE__*/React.createElement(\\"g\\", { stroke: \\"#063855\\", strokeWidth: 2, @@ -56,7 +58,8 @@ var SvgIcon = function SvgIcon(props) { return /*#__PURE__*/React.createElement(\\"svg\\", _extends({ width: 88, height: 88, - xmlns: \\"http://www.w3.org/2000/svg\\" + xmlns: \\"http://www.w3.org/2000/svg\\", + role: \\"img\\" }, props), _g || (_g = /*#__PURE__*/React.createElement(\\"g\\", { stroke: \\"#063855\\", strokeWidth: 2, @@ -80,7 +83,8 @@ var SvgIcon = function SvgIcon() { return _svg || (_svg = /*#__PURE__*/React.createElement(\\"svg\\", { width: 88, height: 88, - xmlns: \\"http://www.w3.org/2000/svg\\" + xmlns: \\"http://www.w3.org/2000/svg\\", + role: \\"img\\" }, /*#__PURE__*/React.createElement(\\"g\\", { stroke: \\"#063855\\", strokeWidth: 2, @@ -104,7 +108,8 @@ var SvgIcon = function SvgIcon() { return _svg || (_svg = /*#__PURE__*/React.createElement(\\"svg\\", { width: 88, height: 88, - xmlns: \\"http://www.w3.org/2000/svg\\" + xmlns: \\"http://www.w3.org/2000/svg\\", + role: \\"img\\" }, /*#__PURE__*/React.createElement(\\"g\\", { stroke: \\"#063855\\", strokeWidth: 2,