Skip to content

Commit

Permalink
Implement parsing of media query lists
Browse files Browse the repository at this point in the history
Ref. #107
  • Loading branch information
kasperisager committed Feb 27, 2019
1 parent e7825e8 commit 36b5bb1
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 4 deletions.
34 changes: 31 additions & 3 deletions packages/alfa-css/src/grammars/media.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
import { Units } from "../units";
import { Value, Values } from "../values";

const { isArray } = Array;
const { assign } = Object;

/**
Expand Down Expand Up @@ -85,6 +86,7 @@ function mediaQuery(stream: Stream<Token>): MediaQuery | null {
}

stream.accept(token => token.type !== TokenType.Comma);

return null;
}

Expand Down Expand Up @@ -330,7 +332,11 @@ function mediaFeature(stream: Stream<Token>): MediaFeature | null {
return null;
}

type Production<T extends Token> = Lang.Production<Token, MediaQuery, T>;
type Production<T extends Token> = Lang.Production<
Token,
MediaQuery | Array<MediaQuery>,
T
>;

const ident: Production<Tokens.Ident> = {
token: TokenType.Ident,
Expand All @@ -348,7 +354,29 @@ const parenthesis: Production<Tokens.Parenthesis> = {
}
};

export const MediaGrammar: Grammar<Token, MediaQuery> = new Grammar(
[skip(TokenType.Whitespace), ident, parenthesis],
const comma: Production<Tokens.Comma> = {
token: TokenType.Comma,
infix: (token, stream, expression, left) => {
const right = expression();

if (!isArray(left)) {
left = [left];
}

if (isArray(right)) {
left.push(...right);
} else if (right !== null) {
left.push(right);
}

return left;
}
};

export const MediaGrammar: Grammar<
Token,
MediaQuery | Array<MediaQuery>
> = new Grammar(
[skip(TokenType.Whitespace), ident, parenthesis, comma],
() => null
);
20 changes: 19 additions & 1 deletion packages/alfa-css/test/grammars/media.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ import { MediaGrammar } from "../../src/grammars/media";
import { MediaOperator, MediaQuery } from "../../src/types";
import { Values } from "../../src/values";

function media(t: Assertions, input: string, expected: MediaQuery) {
function media(
t: Assertions,
input: string,
expected: MediaQuery | Array<MediaQuery>
) {
const lexer = lex(input, Alphabet);
const parser = parse(lexer.result, MediaGrammar);

Expand Down Expand Up @@ -73,6 +77,20 @@ test("Can parse a media type and feature", t => {
});
});

test("Can parse a list of media types and a feature", t => {
media(t, "typeA, typeB and (feature)", [
{
type: "typeA"
},
{
type: "typeB",
condition: {
features: [{ name: "feature" }]
}
}
]);
});

test("Can parse multiple media features separated by and", t => {
media(t, "(foo) and (bar)", {
condition: {
Expand Down
4 changes: 4 additions & 0 deletions packages/alfa-dom/test/fulfills.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,7 @@ test("Checks fulfillment of a min-width media feature", t => {
t(fulfills(device, mediaRule("(min-width: 720px)")));
t(fulfills(device, mediaRule("(min-width: 719px)")));
});

test("Checks fulfillment of a media query list", t => {
t(fulfills(device, mediaRule("print, screen and (min-width: 721px)")));
});

0 comments on commit 36b5bb1

Please sign in to comment.