├── .editorconfig ├── .eslintrc ├── .gitattributes ├── .gitignore ├── .jscsrc ├── .jshintrc ├── .npmignore ├── .travis.yml ├── CONTRIBUTING.md ├── LICENSE.txt ├── README.md ├── bower.json ├── index.js ├── package.json └── test └── unit-tests.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 4 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "eslint:recommended", 3 | "env": { 4 | "es6": true 5 | }, 6 | "ecmaFeatures": { 7 | "modules": true 8 | }, 9 | "rules": { 10 | "array-bracket-spacing": [2, "never"], 11 | "arrow-parens": 2, 12 | "arrow-spacing": [2, {"before": true, "after": true}], 13 | "block-scoped-var": 2, 14 | "block-spacing": [2, "always"], 15 | "brace-style": [2, "stroustrup"], 16 | "camelcase": 2, 17 | "constructor-super": 2, 18 | "comma-spacing": [2, {"before": false, "after": true}], 19 | "comma-style": [2, "last"], 20 | "computed-property-spacing": [2, "never"], 21 | "consistent-this": [2, "self"], 22 | "curly": 2, 23 | "dot-location": [2, "property"], 24 | "eol-last": 2, 25 | "eqeqeq": 2, 26 | "key-spacing": [2, {"beforeColon": false, "afterColon": true}], 27 | "linebreak-style": [2, "unix"], 28 | "new-cap": 2, 29 | "new-parens": 2, 30 | "no-array-constructor": 2, 31 | "no-bitwise": 2, 32 | "no-const-assign": 2, 33 | "no-constant-condition": 0, 34 | "no-dupe-args": 2, 35 | "no-dupe-class-members": 2, 36 | "no-duplicate-case": 2, 37 | "no-empty-character-class": 2, 38 | "no-eval": 2, 39 | "no-floating-decimal": 2, 40 | "no-implied-eval": 2, 41 | "no-inline-comments": 0, 42 | "no-irregular-whitespace": 2, 43 | "no-mixed-spaces-and-tabs": 2, 44 | "no-multi-spaces": 2, 45 | "no-multiple-empty-lines": 0, 46 | "no-new-object": 2, 47 | "no-param-reassign": 0, 48 | "no-process-env": 2, 49 | "no-restricted-syntax": [2, "WithStatement"], 50 | "no-self-compare": 2, 51 | "no-spaced-func": 2, 52 | "no-this-before-super": 2, 53 | "no-throw-literal": 2, 54 | "no-trailing-spaces": 2, 55 | "no-underscore-dangle": 0, 56 | "no-unexpected-multiline": 2, 57 | "no-unneeded-ternary": 2, 58 | "no-useless-call": 2, 59 | "no-void": 2, 60 | "one-var": [2, "never"], 61 | "object-curly-spacing": [2, "never"], 62 | "object-shorthand": [2, "always"], 63 | "operator-assignment": [2, "always"], 64 | "operator-linebreak": [2, "after"], 65 | "padded-blocks": 0, 66 | "prefer-const": 2, 67 | "prefer-spread": 2, 68 | "quote-props": [2, "as-needed", {"keywords": true}], 69 | "quotes": 0, 70 | "radix": 2, 71 | "require-jsdoc": 2, 72 | "semi": [2, "always"], 73 | "semi-spacing": [2, {"before": false, "after": true}], 74 | "space-after-keywords": [2, "always"], 75 | "space-before-blocks": [2, "always"], 76 | "space-before-function-paren": [2, {"anonymous": "always", "named": "never"}], 77 | "space-before-keywords": [2, "always"], 78 | "space-in-parens": [2, "never"], 79 | "space-return-throw-case": 2, 80 | "space-unary-ops": [2, {"words": true, "nonwords": false}], 81 | "spaced-comment": [2, "always"], 82 | "strict": [2, "global"], 83 | "vars-on-top": 0, 84 | "wrap-iife": [2, "inside"], 85 | "yoda": [2, "never"] 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Enforce Unix newlines 2 | *.css text eol=lf 3 | *.html text eol=lf 4 | *.js text eol=lf 5 | *.json text eol=lf 6 | *.md text eol=lf 7 | *.yml text eol=lf 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | coverage/ 2 | node_modules/ 3 | npm-debug.log 4 | -------------------------------------------------------------------------------- /.jscsrc: -------------------------------------------------------------------------------- 1 | { 2 | "disallowEmptyBlocks": true, 3 | "disallowMixedSpacesAndTabs": true, 4 | "disallowMultipleLineStrings": true, 5 | "disallowMultipleSpaces": true, 6 | "disallowMultipleVarDecl": true, 7 | "disallowSpaceAfterPrefixUnaryOperators": ["++", "--", "+", "-", "~", "!"], 8 | "disallowSpaceBeforeComma": true, 9 | "disallowSpaceBeforePostfixUnaryOperators": ["++", "--"], 10 | "disallowSpaceBeforeSemicolon": true, 11 | "disallowSpacesInCallExpression": true, 12 | "disallowSpacesInsideBrackets": true, 13 | "disallowTabs": true, 14 | "disallowTrailingWhitespace": true, 15 | "requireCapitalizedConstructors": true, 16 | "requireCommaBeforeLineBreak": true, 17 | "requireCurlyBraces": ["if", "else", "for", "while", "do", "try", "catch", "case", "default"], 18 | "requireLineFeedAtFileEnd": true, 19 | "requireNumericLiterals": true, 20 | "requireObjectKeysOnNewLine": true, 21 | "requireOperatorBeforeLineBreak": ["+", "-", "/", "*", "=", "==", "===", "!=", "!==", ">", "<", ">=", "<="], 22 | "requireParenthesesAroundIIFE": true, 23 | "requireSemicolons": true, 24 | "requireSpaceAfterBinaryOperators": ["+", "-", "/", "*", "=", "==", "===", "!=", "!==", ">", "<", ">=", "<="], 25 | "requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch", "return", "try", "catch"], 26 | "requireSpaceBeforeBinaryOperators": ["+", "-", "/", "*", "=", "==", "===", "!=", "!==", ">", "<", ">=", "<="], 27 | "requireSpacesInConditionalExpression": true, 28 | "requireSpacesInFunctionExpression": { "beforeOpeningCurlyBrace": true }, 29 | "requireSpacesInForStatement": true, 30 | "requireSpread": true, 31 | "validateIndentation": 4, 32 | "validateLineBreaks": "LF", 33 | "validateNewlineAfterArrayElements": true, 34 | "validateParameterSeparator": ", " 35 | } 36 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "bitwise": true, 3 | "curly": true, 4 | "eqeqeq": true, 5 | "forin": true, 6 | "futurehostile": true, 7 | "immed": true, 8 | "latedef": true, 9 | "newcap": true, 10 | "noarg": true, 11 | "node": true, 12 | "noempty": true, 13 | "plusplus": false, 14 | "predef": ["exports"], 15 | "sub": true, 16 | "undef": true 17 | } 18 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .gitignore 3 | .travis.yml 4 | coverage/ 5 | node_modules/ 6 | test/ 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | { 2 | "language": "node_js", 3 | "sudo": false, 4 | "node_js": ["5"], 5 | "after_script": [ 6 | "npm run coverage", 7 | "cat ./coverage/lcov.info | npm run coveralls" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | ### Code style 4 | The project's coding style is laid out in the JSHint, ESLint, and JSCS configurations. 5 | 6 | ### Chai unit tests 7 | The included [Chai-based](https://github.com/chaijs/chai) unit tests can be run via `npm run unit`. 8 | 9 | ## Modifying the code 10 | First, ensure that you have the latest [Node.js](http://nodejs.org/) and [npm](http://npmjs.org/) installed. 11 | 12 | 1. Fork and clone the repo. 13 | 2. Run `npm install` to install all build dependencies. 14 | 3. Run `npm test` to lint & test this project. 15 | 16 | Assuming that you don't see any red, you're ready to go. Just be sure to run `npm test` after making any changes, to ensure that nothing is broken. 17 | 18 | ## Submitting pull requests 19 | 20 | 1. Create a new branch, please don't work in your `master` branch directly. 21 | 2. Add failing tests for the change you want to make. Run `npm test` to see the tests fail. 22 | 3. Fix stuff. 23 | 4. Run `npm test` to see if the tests pass. Repeat steps 2-4 until done. 24 | 5. Update the documentation to reflect any changes. 25 | 6. Push to your fork and submit a pull request. 26 | 27 | ## Licensing 28 | By contributing, you agree to license your contribution under [the New/Revised BSD License](https://github.com/cvrebert/css-mq-parser/blob/master/LICENSE.txt). 29 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2014 Yahoo! Inc. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the Yahoo! Inc. nor the 15 | names of its contributors may be used to endorse or promote products 16 | derived from this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL YAHOO! INC. BE LIABLE FOR ANY 22 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | 30 | Copyright (c) 2015, Christopher Rebert 31 | All rights reserved. 32 | 33 | Redistribution and use in source and binary forms, with or without 34 | modification, are permitted provided that the following conditions are met: 35 | 36 | * Redistributions of source code must retain the above copyright notice, this 37 | list of conditions and the following disclaimer. 38 | 39 | * Redistributions in binary form must reproduce the above copyright notice, 40 | this list of conditions and the following disclaimer in the documentation 41 | and/or other materials provided with the distribution. 42 | 43 | * Neither the name of the copyright holder nor the names of its 44 | contributors may be used to endorse or promote products derived from 45 | this software without specific prior written permission. 46 | 47 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 48 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 49 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 50 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 51 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 52 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 53 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 54 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 55 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 56 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 57 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CSS Media Query Parser 2 | [![npm version](https://img.shields.io/npm/v/css-mq-parser.svg)](https://www.npmjs.com/package/css-mq-parser) 3 | [![Build Status](https://img.shields.io/travis/cvrebert/css-mq-parser/master.svg)](https://travis-ci.org/cvrebert/css-mq-parser) 4 | [![Coverage Status](https://img.shields.io/coveralls/cvrebert/css-mq-parser.svg?branch=master)](https://coveralls.io/r/cvrebert/css-mq-parser) 5 | [![devDependency Status](https://img.shields.io/david/dev/cvrebert/css-mq-parser.svg)](https://david-dm.org/cvrebert/css-mq-parser#info=devDependencies) 6 | 7 | Parses CSS media query expressions. 8 | 9 | ## Installation 10 | 11 | Install via npm: 12 | 13 | ```shell 14 | $ npm install css-mq-parser 15 | ``` 16 | 17 | ## Usage 18 | 19 | This package exports one function, which can parse CSS media query expressions and return an AST. 20 | The parser tolerates several known CSS media query browser hacks, but will throw a `SyntaxError` if the media query expression is severely malformed. 21 | Note that this module implements a lax/liberal/non-validating parser; even modulo browser hacks, the fact that it parses a given expression successfully does not guarantee that the expression is valid per the relevant CSS specifications. 22 | 23 | ```javascript 24 | var parseMediaQuery = require('css-mq-parser'); 25 | var ast = parseMediaQuery('screen and (min-width: 48em)'); 26 | ``` 27 | 28 | The `ast` variable will have the following payload: 29 | 30 | ```json 31 | [ 32 | { 33 | "inverse": false, 34 | "preTypeHack": "", 35 | "type": "screen", 36 | "postTypeHack": "", 37 | "expressions": [ 38 | { 39 | "modifier": "min", 40 | "feature": "width", 41 | "value": "48em" 42 | } 43 | ] 44 | } 45 | ] 46 | ``` 47 | 48 | 49 | ## License & Acknowledgements 50 | 51 | This project is a fork of [css-mediaquery](https://www.npmjs.com/package/css-mediaquery). 52 | This software is free to use under the New/Revised BSD License. 53 | See the [LICENSE file](https://github.com/cvrebert/css-mq-parser/blob/master/LICENSE.txt) for license text and copyright information. 54 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | @$% Not a Bower package. Use a better package management tool instead. ^&* 2 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015, Christopher Rebert. 3 | Copyright (c) 2014, Yahoo! Inc. All rights reserved. 4 | Copyrights licensed under the New BSD License. 5 | See the accompanying LICENSE file for terms. 6 | */ 7 | /* eslint-env node */ 8 | 9 | var RE_MEDIA_QUERY = /^(?:(only|not)?\s*(\\?\\0(?:\s*))?([_a-z][_a-z0-9-]*)(\\9?)?|(\([^\)]+\)))(?:\s*and\s*(.*))?$/i; 10 | var RE_MQ_EXPRESSION = /^\(\s*([_a-z-][_a-z0-9-]*)\s*(?:\:\s*([^\)]+))?\s*\)$/; 11 | var RE_MQ_FEATURE = /^(?:(min|max)-)?(.+)/; 12 | 13 | module.exports = function parseQuery(mediaQuery) { 14 | return mediaQuery.split(',').map(function (query) { 15 | query = query.trim(); 16 | 17 | var captures = query.match(RE_MEDIA_QUERY); 18 | 19 | // Media Query must be valid. 20 | if (!captures) { 21 | throw new SyntaxError('Invalid CSS media query: "' + query + '"'); 22 | } 23 | 24 | var modifier = captures[1]; 25 | var type = captures[3]; 26 | var expressions = ((captures[5] || '') + (captures[6] || '')).trim(); 27 | var parsed = { 28 | inverse: !!modifier && modifier.toLowerCase() === 'not', 29 | preTypeHack: captures[2] || '', 30 | postTypeHack: captures[4] || '', 31 | type: type ? type.toLowerCase() : 'all' 32 | }; 33 | 34 | // Check for media query expressions. 35 | if (!expressions) { 36 | parsed.expressions = []; 37 | return parsed; 38 | } 39 | 40 | // Split expressions into a list. 41 | expressions = expressions.match(/\([^\)]+\)/g); 42 | 43 | // Media Query must be valid. 44 | if (!expressions) { 45 | throw new SyntaxError('Invalid CSS media query: "' + query + '"'); 46 | } 47 | 48 | parsed.expressions = expressions.map(function (expression) { 49 | var exprCaptures = expression.match(RE_MQ_EXPRESSION); 50 | 51 | // Media Query must be valid. 52 | if (!exprCaptures) { 53 | throw new SyntaxError('Invalid CSS media query: "' + query + '"'); 54 | } 55 | 56 | var feature = exprCaptures[1].toLowerCase().match(RE_MQ_FEATURE); 57 | 58 | return { 59 | modifier: feature[1], 60 | feature: feature[2], 61 | value: exprCaptures[2] 62 | }; 63 | }); 64 | 65 | return parsed; 66 | }); 67 | }; 68 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "css-mq-parser", 3 | "version": "0.0.3", 4 | "description": "Parses CSS media queries", 5 | "main": "index.js", 6 | "scripts": { 7 | "unit": "mocha --reporter spec", 8 | "coverage": "istanbul cover ./node_modules/mocha/bin/_mocha -- --reporter spec", 9 | "coveralls": "coveralls", 10 | "eslint": "eslint *.js test/", 11 | "jshint": "jshint *.js test/", 12 | "jscs": "jscs *.js test/", 13 | "lint": "npm run jshint && npm run eslint && npm run jscs", 14 | "test": "npm run lint && npm run unit" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "git://github.com/cvrebert/css-mq-parser.git" 19 | }, 20 | "keywords": [ 21 | "css", 22 | "media", 23 | "query", 24 | "parse" 25 | ], 26 | "author": "Chris Rebert ", 27 | "contributors": [ 28 | "Eric Ferraiuolo ", 29 | "Tilo Mitra " 30 | ], 31 | "license": "BSD-3-Clause", 32 | "bugs": { 33 | "url": "https://github.com/cvrebert/css-mq-parser/issues" 34 | }, 35 | "homepage": "https://github.com/cvrebert/css-mq-parser", 36 | "devDependencies": { 37 | "chai": "^3.2.0", 38 | "coveralls": "^2.11.2", 39 | "eslint": "^1.5.1", 40 | "istanbul": "^0.3.14", 41 | "jscs": "^2.2.1", 42 | "jshint": "^2.7.0", 43 | "mocha": "^2.2.5", 44 | "mocha-lcov-reporter": "^1.0.0" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /test/unit-tests.js: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | /* eslint no-unused-expressions:0, require-jsdoc:0 */ 3 | /* global describe, it */ 4 | /* jshint -W030 */ 5 | 6 | var expect = require('chai').expect; 7 | var parseMediaQuery = require('../'); 8 | 9 | describe('parseQuery()', function () { 10 | it('should parse media queries without expressions', function () { 11 | expect(parseMediaQuery('screen')).to.eql([ 12 | { 13 | inverse: false, 14 | preTypeHack: '', 15 | type: 'screen', 16 | postTypeHack: '', 17 | expressions: [] 18 | } 19 | ]); 20 | 21 | expect(parseMediaQuery('not screen')).to.eql([ 22 | { 23 | inverse: true, 24 | preTypeHack: '', 25 | type: 'screen', 26 | postTypeHack: '', 27 | expressions: [] 28 | } 29 | ]); 30 | }); 31 | 32 | it('should parse common retina media query list', function () { 33 | var parsed = parseMediaQuery( 34 | 'only screen and (-webkit-min-device-pixel-ratio: 2),\n' + 35 | 'only screen and ( min--moz-device-pixel-ratio: 2),\n' + 36 | 'only screen and ( -o-min-device-pixel-ratio: 2/1),\n' + 37 | 'only screen and ( min-device-pixel-ratio: 2),\n' + 38 | 'only screen and ( min-resolution: 192dpi),\n' + 39 | 'only screen and ( min-resolution: 2dppx)' 40 | ); 41 | 42 | expect(parsed).to.be.an.array; 43 | expect(parsed).to.have.length(6); 44 | expect(parsed[0].expressions[0].feature).to.equal('-webkit-min-device-pixel-ratio'); 45 | expect(parsed[1].expressions[0].modifier).to.equal('min'); 46 | }); 47 | 48 | it('should parse media queries that use browser hacks', function () { 49 | // http://browserhacks.com/#hack-36e9719b0244c5806423ca3c8ce02bdc 50 | expect(parseMediaQuery('all and (min-resolution: 3e1dpcm)')).to.eql([ 51 | { 52 | inverse: false, 53 | preTypeHack: '', 54 | type: 'all', 55 | postTypeHack: '', 56 | expressions: [ 57 | { 58 | modifier: 'min', 59 | feature: 'resolution', 60 | value: '3e1dpcm' 61 | } 62 | ] 63 | } 64 | ]); 65 | 66 | // http://browserhacks.com/#hack-a60b03e301a67f76a5a22221c739dc64 67 | expect(parseMediaQuery('screen and (min-width:0\\0)')).to.eql([ 68 | { 69 | inverse: false, 70 | preTypeHack: '', 71 | type: 'screen', 72 | postTypeHack: '', 73 | expressions: [ 74 | { 75 | modifier: 'min', 76 | feature: 'width', 77 | value: '0\\0' 78 | } 79 | ] 80 | } 81 | ]); 82 | 83 | // http://browserhacks.com/#hack-411240e387db3ac5b87da57714e25d22 84 | expect(parseMediaQuery('\\0 all')).to.eql([ 85 | { 86 | inverse: false, 87 | preTypeHack: '\\0 ', 88 | type: 'all', 89 | postTypeHack: '', 90 | expressions: [] 91 | } 92 | ]); 93 | 94 | // http://browserhacks.com/#hack-c9242a5ec3f073257e275102be15d95f 95 | expect(parseMediaQuery('\\0screen')).to.eql([ 96 | { 97 | inverse: false, 98 | preTypeHack: '\\0', 99 | type: 'screen', 100 | postTypeHack: '', 101 | expressions: [] 102 | } 103 | ]); 104 | 105 | // http://browserhacks.com/#hack-a13653e3599eb6e6c11ba7f1a859193e 106 | expect(parseMediaQuery('\\\\0 screen')).to.eql([ 107 | { 108 | inverse: false, 109 | preTypeHack: '\\\\0 ', 110 | type: 'screen', 111 | postTypeHack: '', 112 | expressions: [] 113 | } 114 | ]); 115 | 116 | // http://browserhacks.com/#hack-6615a4a5434dc55fc1c01736edb32cb7 117 | expect(parseMediaQuery('screen\\9')).to.eql([ 118 | { 119 | inverse: false, 120 | preTypeHack: '', 121 | type: 'screen', 122 | postTypeHack: '\\9', 123 | expressions: [] 124 | } 125 | ]); 126 | 127 | // http://browserhacks.com/#hack-7e41bb4d3e33ad5da4d7d737b7bf3981 128 | expect(parseMediaQuery('\\0screen\\,screen\\9')).to.eql([ 129 | { 130 | inverse: false, 131 | preTypeHack: '\\0', 132 | type: 'screen', 133 | postTypeHack: '\\', 134 | expressions: [] 135 | }, 136 | { 137 | inverse: false, 138 | preTypeHack: '', 139 | type: 'screen', 140 | postTypeHack: '\\9', 141 | expressions: [] 142 | } 143 | ]); 144 | }); 145 | 146 | it('should throw a SyntaxError when a media query is completely invalid', function () { 147 | function parse(query) { 148 | return function () { 149 | parseMediaQuery(query); 150 | }; 151 | } 152 | 153 | expect(parse('some crap')).to.throw(SyntaxError); 154 | expect(parse('48em')).to.throw(SyntaxError); 155 | expect(parse('screen and crap')).to.throw(SyntaxError); 156 | expect(parse('screen and (48em)')).to.throw(SyntaxError); 157 | expect(parse('screen and (foo:)')).to.throw(SyntaxError); 158 | expect(parse('()')).to.throw(SyntaxError); 159 | expect(parse('(foo) (bar)')).to.throw(SyntaxError); 160 | expect(parse('(foo:) and (bar)')).to.throw(SyntaxError); 161 | }); 162 | }); 163 | --------------------------------------------------------------------------------