Skip to content

Commit

Permalink
Validate duplicate @media in media queries (#723)
Browse files Browse the repository at this point in the history
  • Loading branch information
mattcompiles authored Jun 7, 2022
1 parent 6a5b209 commit 8467fc2
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 23 deletions.
5 changes: 5 additions & 0 deletions .changeset/forty-swans-fail.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@vanilla-extract/css': patch
---

Validate duplicate '@media' in media queries
6 changes: 4 additions & 2 deletions packages/css/src/transformCss.ts
Original file line number Diff line number Diff line change
Expand Up @@ -329,9 +329,11 @@ class Stylesheet {
);

forEach(rules, (mediaRule, query) => {
validateMediaQuery(query);
const mediaQuery = `@media ${query}`;

const conditions = [...parentConditions, `@media ${query}`];
validateMediaQuery(mediaQuery);

const conditions = [...parentConditions, mediaQuery];

this.addConditionalRule(
{
Expand Down
54 changes: 34 additions & 20 deletions packages/css/src/validateMediaQuery.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ import { validateMediaQuery } from './validateMediaQuery';
describe('validateMediaQuery', () => {
describe('valid selectors', () => {
const validMediaQueries = [
'screen',
'screen, print',
'screen and (max-width: 600px)',
'(min-width: 5rem)',
'(min-width: 30em) and (orientation: landscape)',
'only screen and (min-width: 320px) and (max-width: 480px) and (resolution: 150dpi)',
'not screen and (color), print and (color)',
'(prefers-reduced-motion)',
'(prefers-reduced-motion: no-preference)',
'@media screen',
'@media screen, print',
'@media screen and (max-width: 600px)',
'@media (min-width: 5rem)',
'@media (min-width: 30em) and (orientation: landscape)',
'@media only screen and (min-width: 320px) and (max-width: 480px) and (resolution: 150dpi)',
'@media not screen and (color), print and (color)',
'@media (prefers-reduced-motion)',
'@media (prefers-reduced-motion: no-preference)',
];

validMediaQueries.forEach((query) =>
Expand All @@ -23,8 +23,9 @@ describe('validateMediaQuery', () => {

describe('invalid media queries', () => {
it('empty query', () => {
expect(() => validateMediaQuery('')).toThrowErrorMatchingInlineSnapshot(`
"Invalid media query: \\"\\"
expect(() => validateMediaQuery('@media '))
.toThrowErrorMatchingInlineSnapshot(`
"Invalid media query: \\"@media \\"
Query is empty
Expand All @@ -33,9 +34,9 @@ describe('validateMediaQuery', () => {
});

it('random query', () => {
expect(() => validateMediaQuery('random query'))
expect(() => validateMediaQuery('@media random query'))
.toThrowErrorMatchingInlineSnapshot(`
"Invalid media query: \\"random query\\"
"Invalid media query: \\"@media random query\\"
Unknown ident 'random' in media query
Expand All @@ -44,9 +45,9 @@ describe('validateMediaQuery', () => {
});

it('(min-height: 600px', () => {
expect(() => validateMediaQuery('(min-height: 600px'))
expect(() => validateMediaQuery('@media (min-height: 600px'))
.toThrowErrorMatchingInlineSnapshot(`
"Invalid media query: \\"(min-height: 600px\\"
"Invalid media query: \\"@media (min-height: 600px\\"
Invalid media condition
Expected media condition after '('
Expand All @@ -56,9 +57,9 @@ describe('validateMediaQuery', () => {
});

it('min-width: 600px)', () => {
expect(() => validateMediaQuery('min-width: 600px)'))
expect(() => validateMediaQuery('@media min-width: 600px)'))
.toThrowErrorMatchingInlineSnapshot(`
"Invalid media query: \\"min-width: 600px)\\"
"Invalid media query: \\"@media min-width: 600px)\\"
Unknown ident 'min-width' in media query
Expand All @@ -67,14 +68,27 @@ describe('validateMediaQuery', () => {
});

it('prefers-reduced-motion: no-preference', () => {
expect(() => validateMediaQuery('prefers-reduced-motion: no-preference'))
.toThrowErrorMatchingInlineSnapshot(`
"Invalid media query: \\"prefers-reduced-motion: no-preference\\"
expect(() =>
validateMediaQuery('@media prefers-reduced-motion: no-preference'),
).toThrowErrorMatchingInlineSnapshot(`
"Invalid media query: \\"@media prefers-reduced-motion: no-preference\\"
Unknown ident 'prefers-reduced-motion' in media query
Read more on MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries"
`);
});

it('Double media: @media @media screen and (min-width: 640px)', () => {
expect(() =>
validateMediaQuery('@media @media screen and (min-width: 640px)'),
).toThrowErrorMatchingInlineSnapshot(`
"Invalid media query: \\"@media @media screen and (min-width: 640px)\\"
Expected media condition or media prefix
Read more on MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries"
`);
});
});
});
3 changes: 2 additions & 1 deletion packages/css/src/validateMediaQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ const createMediaQueryError = (mediaQuery: string, msg: string) =>
);

export const validateMediaQuery = (mediaQuery: string) => {
if (mediaQuery === '') {
// Empty queries will start with '@media '
if (mediaQuery === '@media ') {
throw createMediaQueryError(mediaQuery, 'Query is empty');
}

Expand Down

0 comments on commit 8467fc2

Please sign in to comment.