Skip to content

Commit e531251

Browse files
authored
Improve media query validation messaging (#684)
1 parent 64378b0 commit e531251

File tree

5 files changed

+86
-42
lines changed

5 files changed

+86
-42
lines changed

.changeset/orange-mirrors-shake.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@vanilla-extract/css': patch
3+
---
4+
5+
Improve media query validation messaging

packages/css/package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,17 +110,16 @@
110110
"@emotion/hash": "^0.8.0",
111111
"@vanilla-extract/private": "^1.0.3",
112112
"chalk": "^4.1.1",
113-
"css-mediaquery": "^0.1.2",
114113
"css-what": "^5.0.1",
115114
"cssesc": "^3.0.0",
116115
"csstype": "^3.0.7",
117116
"deep-object-diff": "^1.1.0",
118117
"deepmerge": "^4.2.2",
119118
"escape-string-regexp": "^4.0.0",
119+
"media-query-parser": "^2.0.2",
120120
"outdent": "^0.8.0"
121121
},
122122
"devDependencies": {
123-
"@types/css-mediaquery": "^0.1.1",
124123
"@types/cssesc": "^3.0.0"
125124
}
126125
}

packages/css/src/validateMediaQuery.test.ts

Lines changed: 55 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ describe('validateMediaQuery', () => {
1010
'(min-width: 30em) and (orientation: landscape)',
1111
'only screen and (min-width: 320px) and (max-width: 480px) and (resolution: 150dpi)',
1212
'not screen and (color), print and (color)',
13+
'(prefers-reduced-motion)',
14+
'(prefers-reduced-motion: no-preference)',
1315
];
1416

1517
validMediaQueries.forEach((query) =>
@@ -20,17 +22,59 @@ describe('validateMediaQuery', () => {
2022
});
2123

2224
describe('invalid media queries', () => {
23-
const invalidMediaQueries = [
24-
'',
25-
'random query',
26-
'(min-height: 600px',
27-
'min-width: 600px)',
28-
];
25+
it('empty query', () => {
26+
expect(() => validateMediaQuery('')).toThrowErrorMatchingInlineSnapshot(`
27+
"Invalid media query: \\"\\"
2928
30-
invalidMediaQueries.forEach((query) =>
31-
it(query, () => {
32-
expect(() => validateMediaQuery(query)).toThrow();
33-
}),
34-
);
29+
Query is empty
30+
31+
Read more on MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries"
32+
`);
33+
});
34+
35+
it('random query', () => {
36+
expect(() => validateMediaQuery('random query'))
37+
.toThrowErrorMatchingInlineSnapshot(`
38+
"Invalid media query: \\"random query\\"
39+
40+
Unknown ident 'random' in media query
41+
42+
Read more on MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries"
43+
`);
44+
});
45+
46+
it('(min-height: 600px', () => {
47+
expect(() => validateMediaQuery('(min-height: 600px'))
48+
.toThrowErrorMatchingInlineSnapshot(`
49+
"Invalid media query: \\"(min-height: 600px\\"
50+
51+
Invalid media condition
52+
Expected media condition after '('
53+
54+
Read more on MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries"
55+
`);
56+
});
57+
58+
it('min-width: 600px)', () => {
59+
expect(() => validateMediaQuery('min-width: 600px)'))
60+
.toThrowErrorMatchingInlineSnapshot(`
61+
"Invalid media query: \\"min-width: 600px)\\"
62+
63+
Unknown ident 'min-width' in media query
64+
65+
Read more on MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries"
66+
`);
67+
});
68+
69+
it('prefers-reduced-motion: no-preference', () => {
70+
expect(() => validateMediaQuery('prefers-reduced-motion: no-preference'))
71+
.toThrowErrorMatchingInlineSnapshot(`
72+
"Invalid media query: \\"prefers-reduced-motion: no-preference\\"
73+
74+
Unknown ident 'prefers-reduced-motion' in media query
75+
76+
Read more on MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries"
77+
`);
78+
});
3579
});
3680
});
Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
11
import outdent from 'outdent';
2-
import { parse } from 'css-mediaquery';
2+
import { toAST } from 'media-query-parser';
33

4-
const mediaTypes = ['all', 'print', 'screen'];
4+
const createMediaQueryError = (mediaQuery: string, msg: string) =>
5+
new Error(
6+
outdent`
7+
Invalid media query: "${mediaQuery}"
58
6-
export const validateMediaQuery = (mediaQuery: string) => {
7-
const { type, expressions } = parse(mediaQuery)?.[0];
9+
${msg}
810
9-
const isAllQuery = mediaQuery === 'all';
10-
const isValidType = mediaTypes.includes(type);
11+
Read more on MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries
12+
`,
13+
);
1114

12-
// If the parser returns all for the type, we should have expressions
13-
// or the query should match 'all' otherwise it is invalid
14-
if (!isValidType || (!isAllQuery && type === 'all' && !expressions.length)) {
15-
throw new Error(
16-
outdent`
17-
Invalid media query: ${mediaQuery}
15+
export const validateMediaQuery = (mediaQuery: string) => {
16+
if (mediaQuery === '') {
17+
throw createMediaQueryError(mediaQuery, 'Query is empty');
18+
}
1819

19-
A media query can contain an optional media type and any number of media feature expressions.
20-
21-
Read more on MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries
22-
`,
23-
);
20+
try {
21+
toAST(mediaQuery);
22+
} catch (e: any) {
23+
throw createMediaQueryError(mediaQuery, e.message);
2424
}
2525
};

pnpm-lock.yaml

Lines changed: 8 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)