New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

media-query-parser

Package Overview
Dependencies
Maintainers
1
Versions
14
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

media-query-parser - npm Package Compare versions

Comparing version 2.0.2 to 3.0.0-beta.0

dist/ast/ast.d.ts

113

dist/index.d.ts

@@ -1,2 +0,111 @@

export * from './parse/lexicalAnalysis';
export * from './parse/syntacticAnalysis';
/**! media-query-parser | Tom Golden <oss@tom.bio> (https://tom.bio) | @license MIT */
import { MediaQueryList, ParserError, MediaQuery, MediaCondition, MediaFeature, ValidValueToken } from "./shared.js";
/**
* creates an AST from a **media-query-list** string; parses comma-separated media queries correctly
*
* Important:
*
* - _an invalid media-query child **does not** make the media-query-list invalid_
* - can **return** a ParserError (e.g. when there is a CSS syntax error, like an invalid string)
*
* @example
* ```ts
* console.log(parseMediaQueryList(`print, invalid, (min-width: 1000px)`));
* // {
* // type: "query-list",
* // mediaQueries: [
* // {type: "query", mediaType: "print"},
* // {type: "query", mediaPrefix: "not", mediaType: "all"},
* // {type: "query", mediaType: "all", mediaCondition: ...}
* // ],
* // }
* ```
*/
export declare const parseMediaQueryList: (str: string) => MediaQueryList | ParserError;
/**
* creates an AST from a **media-query** string
* @example
* ```ts
* console.log(parseMediaQuery(`(monochrome)`));
* // {
* // type: "query",
* // mediaCondition: {
* // type: "condition",
* // children: [{ type: "feature", context: "boolean", feature: "monochrome" }],
* // },
* // mediaType: "all",
* // }
* ```
*/
export declare const parseMediaQuery: (str: string) => MediaQuery | ParserError;
/**
* creates an AST from a **media-condition** string - including parentheses
*
* @example
* ```ts
* console.log(parseMediaCondition(`((aspect-ratio > 1/2) or (monochrome))`));
* // {
* // type: "condition",
* // children: [{
* // type: "condition",
* // children: [
* // {
* // type: "feature",
* // context: "range",
* // feature: "aspect-ratio",
* // range: {
* // featureName: "aspect-ratio",
* // rightOp: ">",
* // rightToken: { denominator: 2, numerator: 1, type: "ratio" },
* // },
* // },
* // { context: "boolean", feature: "monochrome", type: "feature" },
* // ],
* // operator: "or",
* // }],
* // }
*
* ```
*/
export declare const parseMediaCondition: (str: string) => MediaCondition | ParserError;
/**
* creates an AST from a **media-feature** string - including parentheses
*
* @example
* ```ts
* console.log(parseMediaFeature(`(min-width: 768px)`));
* // {
* // type: "feature",
* // context: "value",
* // feature: "width",
* // mediaPrefix: "min",
* // value: { type: "dimension", flag: "number", unit: "px", value: 768 },
* // }
*
* ```
*/
export declare const parseMediaFeature: (str: string) => MediaFeature | ParserError;
/**
* turns an AST into an equivalent string
*
* @example
* ```ts
* console.log(stringify(parseMediaFeature(`(min-width: 768px)`)));
* // "(min-width: 768px)"
* ```
*
* @example
* ```ts
* console.log(stringify({
* type: "query",
* mediaType: "all",
* mediaCondition: {
* type: "condition",
* children: [{ type: "feature", context: "boolean", feature: "monochrome" }],
* },
* }));
* // "(monochrome)"
* ```
*/
export declare const stringify: (node: MediaQueryList | MediaQuery | MediaCondition | MediaFeature | ValidValueToken) => string;
export * from "./shared.js";

1461

dist/index.js

@@ -1,1407 +0,60 @@

/*! @license MediaQueryParser - MIT License - Tom Golden (github@tbjgolden.com) */
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
var __assign = function() {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
function __rest(s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
/**! media-query-parser | Tom Golden <oss@tom.bio> (https://tom.bio) | @license MIT */
import {
readMediaQueryList as r,
readMediaQuery as e,
readMediaCondition as t,
readMediaFeature as o
} from './ast/ast.js'
import {
flattenMediaQueryList as s,
flattenMediaQuery as n,
flattenMediaCondition as a
} from './flatten/flatten.js'
import {
generateMediaQueryList as i,
generateMediaQuery as u,
generateMediaCondition as c,
generateMediaFeature as p,
generateValidValueToken as f
} from './generator/generator.js'
import {lexer as m} from './lexer/lexer.js'
import {isParserError as d} from './shared.js'
export const parseMediaQueryList = e => {
const t = m(e)
return d(t) ? t : s(r(t))
}
function __values(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m) return m.call(o);
if (o && typeof o.length === "number") return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
export const parseMediaQuery = r => {
const t = m(r)
if (d(t)) return t
{
const r = e(t)
return d(r) ? r : n(r)
}
}
function __read(o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
export const parseMediaCondition = r => {
const e = m(r)
if (d(e)) return e
{
const r = t(e, !0)
return d(r) ? r : a(r)
}
}
var weirdNewlines = /(\u000D|\u000C|\u000D\u000A)/g;
var nullOrSurrogates = /[\u0000\uD800-\uDFFF]/g;
var commentRegex = /(\/\*)[\s\S]*?(\*\/)/g;
var lexicalAnalysis = function lexicalAnalysis(str, index) {
if (index === void 0) {
index = 0;
}
str = str.replace(weirdNewlines, '\n').replace(nullOrSurrogates, "\uFFFD");
str = str.replace(commentRegex, '');
var tokens = [];
for (; index < str.length; index += 1) {
var code = str.charCodeAt(index);
if (code === 0x0009 || code === 0x0020 || code === 0x000a) {
var code_1 = str.charCodeAt(++index);
while (code_1 === 0x0009 || code_1 === 0x0020 || code_1 === 0x000a) {
code_1 = str.charCodeAt(++index);
}
index -= 1;
tokens.push({
type: '<whitespace-token>'
});
} else if (code === 0x0022) {
var result = consumeString(str, index);
if (result === null) {
return null;
}
var _a = __read(result, 2),
lastIndex = _a[0],
value = _a[1];
tokens.push({
type: '<string-token>',
value: value
});
index = lastIndex;
} else if (code === 0x0023) {
if (index + 1 < str.length) {
var nextCode = str.charCodeAt(index + 1);
if (nextCode === 0x005f || nextCode >= 0x0041 && nextCode <= 0x005a || nextCode >= 0x0061 && nextCode <= 0x007a || nextCode >= 0x0080 || nextCode >= 0x0030 && nextCode <= 0x0039 || nextCode === 0x005c && index + 2 < str.length && str.charCodeAt(index + 2) !== 0x000a) {
var flag = wouldStartIdentifier(str, index + 1) ? 'id' : 'unrestricted';
var result = consumeIdentUnsafe(str, index + 1);
if (result !== null) {
var _b = __read(result, 2),
lastIndex = _b[0],
value = _b[1];
tokens.push({
type: '<hash-token>',
value: value.toLowerCase(),
flag: flag
});
index = lastIndex;
continue;
}
}
}
tokens.push({
type: '<delim-token>',
value: code
});
} else if (code === 0x0027) {
var result = consumeString(str, index);
if (result === null) {
return null;
}
var _c = __read(result, 2),
lastIndex = _c[0],
value = _c[1];
tokens.push({
type: '<string-token>',
value: value
});
index = lastIndex;
} else if (code === 0x0028) {
tokens.push({
type: '<(-token>'
});
} else if (code === 0x0029) {
tokens.push({
type: '<)-token>'
});
} else if (code === 0x002b) {
var plusNumeric = consumeNumeric(str, index);
if (plusNumeric === null) {
tokens.push({
type: '<delim-token>',
value: code
});
} else {
var _d = __read(plusNumeric, 2),
lastIndex = _d[0],
tokenTuple = _d[1];
if (tokenTuple[0] === '<dimension-token>') {
tokens.push({
type: '<dimension-token>',
value: tokenTuple[1],
unit: tokenTuple[2].toLowerCase(),
flag: 'number'
});
} else if (tokenTuple[0] === '<number-token>') {
tokens.push({
type: tokenTuple[0],
value: tokenTuple[1],
flag: tokenTuple[2]
});
} else {
tokens.push({
type: tokenTuple[0],
value: tokenTuple[1],
flag: 'number'
});
}
index = lastIndex;
}
} else if (code === 0x002c) {
tokens.push({
type: '<comma-token>'
});
} else if (code === 0x002d) {
var minusNumeric = consumeNumeric(str, index);
if (minusNumeric !== null) {
var _e = __read(minusNumeric, 2),
lastIndex = _e[0],
tokenTuple = _e[1];
if (tokenTuple[0] === '<dimension-token>') {
tokens.push({
type: '<dimension-token>',
value: tokenTuple[1],
unit: tokenTuple[2].toLowerCase(),
flag: 'number'
});
} else if (tokenTuple[0] === '<number-token>') {
tokens.push({
type: tokenTuple[0],
value: tokenTuple[1],
flag: tokenTuple[2]
});
} else {
tokens.push({
type: tokenTuple[0],
value: tokenTuple[1],
flag: 'number'
});
}
index = lastIndex;
continue;
}
if (index + 2 < str.length) {
var nextCode = str.charCodeAt(index + 1);
var nextNextCode = str.charCodeAt(index + 2);
if (nextCode === 0x002d && nextNextCode === 0x003e) {
tokens.push({
type: '<CDC-token>'
});
index += 2;
continue;
}
}
var result = consumeIdentLike(str, index);
if (result !== null) {
var _f = __read(result, 3),
lastIndex = _f[0],
value = _f[1],
type = _f[2];
tokens.push({
type: type,
value: value
});
index = lastIndex;
continue;
}
tokens.push({
type: '<delim-token>',
value: code
});
} else if (code === 0x002e) {
var minusNumeric = consumeNumeric(str, index);
if (minusNumeric === null) {
tokens.push({
type: '<delim-token>',
value: code
});
} else {
var _g = __read(minusNumeric, 2),
lastIndex = _g[0],
tokenTuple = _g[1];
if (tokenTuple[0] === '<dimension-token>') {
tokens.push({
type: '<dimension-token>',
value: tokenTuple[1],
unit: tokenTuple[2].toLowerCase(),
flag: 'number'
});
} else if (tokenTuple[0] === '<number-token>') {
tokens.push({
type: tokenTuple[0],
value: tokenTuple[1],
flag: tokenTuple[2]
});
} else {
tokens.push({
type: tokenTuple[0],
value: tokenTuple[1],
flag: 'number'
});
}
index = lastIndex;
continue;
}
} else if (code === 0x003a) {
tokens.push({
type: '<colon-token>'
});
} else if (code === 0x003b) {
tokens.push({
type: '<semicolon-token>'
});
} else if (code === 0x003c) {
if (index + 3 < str.length) {
var nextCode = str.charCodeAt(index + 1);
var nextNextCode = str.charCodeAt(index + 2);
var nextNextNextCode = str.charCodeAt(index + 3);
if (nextCode === 0x0021 && nextNextCode === 0x002d && nextNextNextCode === 0x002d) {
tokens.push({
type: '<CDO-token>'
});
index += 3;
continue;
}
}
tokens.push({
type: '<delim-token>',
value: code
});
} else if (code === 0x0040) {
var result = consumeIdent(str, index + 1);
if (result !== null) {
var _h = __read(result, 2),
lastIndex = _h[0],
value = _h[1];
tokens.push({
type: '<at-keyword-token>',
value: value.toLowerCase()
});
index = lastIndex;
continue;
}
tokens.push({
type: '<delim-token>',
value: code
});
} else if (code === 0x005b) {
tokens.push({
type: '<[-token>'
});
} else if (code === 0x005c) {
var result = consumeEscape(str, index);
if (result === null) {
return null;
}
var _j = __read(result, 2),
lastIndex = _j[0],
value = _j[1];
str = str.slice(0, index) + value + str.slice(lastIndex + 1);
index -= 1;
} else if (code === 0x005d) {
tokens.push({
type: '<]-token>'
});
} else if (code === 0x007b) {
tokens.push({
type: '<{-token>'
});
} else if (code === 0x007d) {
tokens.push({
type: '<}-token>'
});
} else if (code >= 0x0030 && code <= 0x0039) {
var result = consumeNumeric(str, index);
var _k = __read(result, 2),
lastIndex = _k[0],
tokenTuple = _k[1];
if (tokenTuple[0] === '<dimension-token>') {
tokens.push({
type: '<dimension-token>',
value: tokenTuple[1],
unit: tokenTuple[2].toLowerCase(),
flag: 'number'
});
} else if (tokenTuple[0] === '<number-token>') {
tokens.push({
type: tokenTuple[0],
value: tokenTuple[1],
flag: tokenTuple[2]
});
} else {
tokens.push({
type: tokenTuple[0],
value: tokenTuple[1],
flag: 'number'
});
}
index = lastIndex;
} else if (code === 0x005f || code >= 0x0041 && code <= 0x005a || code >= 0x0061 && code <= 0x007a || code >= 0x0080) {
var result = consumeIdentLike(str, index);
if (result === null) {
return null;
}
var _l = __read(result, 3),
lastIndex = _l[0],
value = _l[1],
type = _l[2];
tokens.push({
type: type,
value: value
});
index = lastIndex;
} else {
tokens.push({
type: '<delim-token>',
value: code
});
}
}
tokens.push({
type: '<EOF-token>'
});
return tokens;
};
var consumeString = function consumeString(str, index) {
if (str.length <= index + 1) return null;
var firstCode = str.charCodeAt(index);
var charCodes = [];
for (var i = index + 1; i < str.length; i += 1) {
var code = str.charCodeAt(i);
if (code === firstCode) {
return [i, String.fromCharCode.apply(null, charCodes)];
} else if (code === 0x005c) {
var result = consumeEscape(str, i);
if (result === null) return null;
var _a = __read(result, 2),
lastIndex = _a[0],
charCode = _a[1];
charCodes.push(charCode);
i = lastIndex;
} else if (code === 0x000a) {
return null;
} else {
charCodes.push(code);
}
}
return null;
};
var wouldStartIdentifier = function wouldStartIdentifier(str, index) {
if (str.length <= index) return false;
var code = str.charCodeAt(index);
if (code === 0x002d) {
if (str.length <= index + 1) return false;
var nextCode = str.charCodeAt(index + 1);
if (nextCode === 0x002d || nextCode === 0x005f || nextCode >= 0x0041 && nextCode <= 0x005a || nextCode >= 0x0061 && nextCode <= 0x007a || nextCode >= 0x0080) {
return true;
} else if (nextCode === 0x005c) {
if (str.length <= index + 2) return false;
var nextNextCode = str.charCodeAt(index + 2);
return nextNextCode !== 0x000a;
} else {
return false;
}
} else if (code === 0x005f || code >= 0x0041 && code <= 0x005a || code >= 0x0061 && code <= 0x007a || code >= 0x0080) {
return true;
} else if (code === 0x005c) {
if (str.length <= index + 1) return false;
var nextCode = str.charCodeAt(index + 1);
return nextCode !== 0x000a;
} else {
return false;
}
};
var consumeEscape = function consumeEscape(str, index) {
if (str.length <= index + 1) return null;
if (str.charCodeAt(index) !== 0x005c) return null;
var code = str.charCodeAt(index + 1);
if (code === 0x000a) {
return null;
} else if (code >= 0x0030 && code <= 0x0039 || code >= 0x0041 && code <= 0x0046 || code >= 0x0061 && code <= 0x0066) {
var hexCharCodes = [code];
var min = Math.min(index + 7, str.length);
var i = index + 2;
for (; i < min; i += 1) {
var code_2 = str.charCodeAt(i);
if (code_2 >= 0x0030 && code_2 <= 0x0039 || code_2 >= 0x0041 && code_2 <= 0x0046 || code_2 >= 0x0061 && code_2 <= 0x0066) {
hexCharCodes.push(code_2);
} else {
break;
}
}
if (i < str.length) {
var code_3 = str.charCodeAt(i);
if (code_3 === 0x0009 || code_3 === 0x0020 || code_3 === 0x000a) {
i += 1;
}
}
return [i - 1, parseInt(String.fromCharCode.apply(null, hexCharCodes), 16)];
} else {
return [index + 1, code];
}
};
var consumeNumeric = function consumeNumeric(str, index) {
var numberResult = consumeNumber(str, index);
if (numberResult === null) return null;
var _a = __read(numberResult, 3),
numberEndIndex = _a[0],
numberValue = _a[1],
numberFlag = _a[2];
var identResult = consumeIdent(str, numberEndIndex + 1);
if (identResult !== null) {
var _b = __read(identResult, 2),
identEndIndex = _b[0],
identValue = _b[1];
return [identEndIndex, ['<dimension-token>', numberValue, identValue]];
}
if (numberEndIndex + 1 < str.length && str.charCodeAt(numberEndIndex + 1) === 0x0025) {
return [numberEndIndex + 1, ['<percentage-token>', numberValue]];
}
return [numberEndIndex, ['<number-token>', numberValue, numberFlag]];
};
var consumeNumber = function consumeNumber(str, index) {
if (str.length <= index) return null;
var flag = 'integer';
var numberChars = [];
var firstCode = str.charCodeAt(index);
if (firstCode === 0x002b || firstCode === 0x002d) {
index += 1;
if (firstCode === 0x002d) numberChars.push(0x002d);
}
while (index < str.length) {
var code = str.charCodeAt(index);
if (code >= 0x0030 && code <= 0x0039) {
numberChars.push(code);
index += 1;
} else {
break;
}
}
if (index + 1 < str.length) {
var nextCode = str.charCodeAt(index);
var nextNextCode = str.charCodeAt(index + 1);
if (nextCode === 0x002e && nextNextCode >= 0x0030 && nextNextCode <= 0x0039) {
numberChars.push(nextCode, nextNextCode);
flag = 'number';
index += 2;
while (index < str.length) {
var code = str.charCodeAt(index);
if (code >= 0x0030 && code <= 0x0039) {
numberChars.push(code);
index += 1;
} else {
break;
}
}
}
}
if (index + 1 < str.length) {
var nextCode = str.charCodeAt(index);
var nextNextCode = str.charCodeAt(index + 1);
var nextNextNextCode = str.charCodeAt(index + 2);
if (nextCode === 0x0045 || nextCode === 0x0065) {
var nextNextIsDigit = nextNextCode >= 0x0030 && nextNextCode <= 0x0039;
if (nextNextIsDigit || (nextNextCode === 0x002b || nextNextCode === 0x002d) && nextNextNextCode >= 0x0030 && nextNextNextCode <= 0x0039) {
flag = 'number';
if (nextNextIsDigit) {
numberChars.push(0x0045, nextNextCode);
index += 2;
} else if (nextNextCode === 0x002d) {
numberChars.push(0x0045, 0x002d, nextNextNextCode);
index += 3;
} else {
numberChars.push(0x0045, nextNextNextCode);
index += 3;
}
while (index < str.length) {
var code = str.charCodeAt(index);
if (code >= 0x0030 && code <= 0x0039) {
numberChars.push(code);
index += 1;
} else {
break;
}
}
}
}
}
var numberString = String.fromCharCode.apply(null, numberChars);
var value = flag === 'number' ? parseFloat(numberString) : parseInt(numberString);
if (value === -0) value = 0;
return Number.isNaN(value) ? null : [index - 1, value, flag];
};
var consumeIdentUnsafe = function consumeIdentUnsafe(str, index) {
if (str.length <= index) {
return null;
}
var identChars = [];
for (var code = str.charCodeAt(index); index < str.length; code = str.charCodeAt(++index)) {
if (code === 0x002d || code === 0x005f || code >= 0x0041 && code <= 0x005a || code >= 0x0061 && code <= 0x007a || code >= 0x0080 || code >= 0x0030 && code <= 0x0039) {
identChars.push(code);
continue;
} else {
var result = consumeEscape(str, index);
if (result !== null) {
var _a = __read(result, 2),
lastIndex = _a[0],
code_4 = _a[1];
identChars.push(code_4);
index = lastIndex;
continue;
}
}
break;
}
return index === 0 ? null : [index - 1, String.fromCharCode.apply(null, identChars)];
};
var consumeIdent = function consumeIdent(str, index) {
if (str.length <= index || !wouldStartIdentifier(str, index)) {
return null;
}
var identChars = [];
for (var code = str.charCodeAt(index); index < str.length; code = str.charCodeAt(++index)) {
if (code === 0x002d || code === 0x005f || code >= 0x0041 && code <= 0x005a || code >= 0x0061 && code <= 0x007a || code >= 0x0080 || code >= 0x0030 && code <= 0x0039) {
identChars.push(code);
continue;
} else {
var result = consumeEscape(str, index);
if (result !== null) {
var _a = __read(result, 2),
lastIndex = _a[0],
code_5 = _a[1];
identChars.push(code_5);
index = lastIndex;
continue;
}
}
break;
}
return [index - 1, String.fromCharCode.apply(null, identChars)];
};
var consumeUrl = function consumeUrl(str, index) {
var code = str.charCodeAt(index);
while (code === 0x0009 || code === 0x0020 || code === 0x000a) {
code = str.charCodeAt(++index);
}
var urlChars = [];
var hasFinishedWord = false;
while (index < str.length) {
if (code === 0x0029) {
return [index, String.fromCharCode.apply(null, urlChars)];
} else if (code === 0x0022 || code === 0x0027 || code === 0x0028) {
return null;
} else if (code === 0x0009 || code === 0x0020 || code === 0x000a) {
if (!hasFinishedWord && urlChars.length !== 0) hasFinishedWord = true;
} else if (code === 0x005c) {
var result = consumeEscape(str, index);
if (result === null || hasFinishedWord) return null;
var _a = __read(result, 2),
lastIndex = _a[0],
value = _a[1];
urlChars.push(value);
index = lastIndex;
} else {
if (hasFinishedWord) return null;
urlChars.push(code);
}
code = str.charCodeAt(++index);
}
return null;
};
var consumeIdentLike = function consumeIdentLike(str, index) {
var result = consumeIdent(str, index);
if (result === null) return null;
var _a = __read(result, 2),
lastIndex = _a[0],
value = _a[1];
if (value.toLowerCase() === 'url') {
if (str.length > lastIndex + 1) {
var nextCode = str.charCodeAt(lastIndex + 1);
if (nextCode === 0x0028) {
for (var offset = 2; lastIndex + offset < str.length; offset += 1) {
var nextNextCode = str.charCodeAt(lastIndex + offset);
if (nextNextCode === 0x0022 || nextNextCode === 0x0027) {
return [lastIndex + 1, value.toLowerCase(), '<function-token>'];
} else if (nextNextCode !== 0x0009 && nextNextCode !== 0x0020 && nextNextCode !== 0x000a) {
var result_1 = consumeUrl(str, lastIndex + offset);
if (result_1 === null) return null;
var _b = __read(result_1, 2),
lastUrlIndex = _b[0],
value_1 = _b[1];
return [lastUrlIndex, value_1, '<url-token>'];
}
}
return [lastIndex + 1, value.toLowerCase(), '<function-token>'];
}
}
} else if (str.length > lastIndex + 1) {
var nextCode = str.charCodeAt(lastIndex + 1);
if (nextCode === 0x0028) {
return [lastIndex + 1, value.toLowerCase(), '<function-token>'];
}
}
return [lastIndex, value.toLowerCase(), '<ident-token>'];
};
var simplifyAST = function simplifyAST(ast) {
for (var i = ast.length - 1; i >= 0; i--) {
ast[i] = simplifyMediaQuery(ast[i]);
}
return ast;
};
var simplifyMediaQuery = function simplifyMediaQuery(mediaQuery) {
if (mediaQuery.mediaCondition === null) return mediaQuery;
var mediaCondition = simplifyMediaCondition(mediaQuery.mediaCondition);
if (mediaCondition.operator === null && mediaCondition.children.length === 1 && 'children' in mediaCondition.children[0]) {
mediaCondition = mediaCondition.children[0];
}
return {
mediaPrefix: mediaQuery.mediaPrefix,
mediaType: mediaQuery.mediaType,
mediaCondition: mediaCondition
};
};
var simplifyMediaCondition = function simplifyMediaCondition(mediaCondition) {
for (var i = mediaCondition.children.length - 1; i >= 0; i--) {
var unsimplifiedChild = mediaCondition.children[i];
if (!('context' in unsimplifiedChild)) {
var child = simplifyMediaCondition(unsimplifiedChild);
if (child.operator === null && child.children.length === 1) {
mediaCondition.children[i] = child.children[0];
} else if (child.operator === mediaCondition.operator && (child.operator === 'and' || child.operator === 'or')) {
var spliceArgs = [i, 1];
for (var i_1 = 0; i_1 < child.children.length; i_1++) {
spliceArgs.push(child.children[i_1]);
}
mediaCondition.children.splice.apply(mediaCondition.children, spliceArgs);
}
}
}
return mediaCondition;
};
var createError = function createError(message, err) {
if (err instanceof Error) {
return new Error("".concat(err.message.trim(), "\n").concat(message.trim()));
} else {
return new Error(message.trim());
}
};
var toAST = function toAST(str) {
return simplifyAST(toUnflattenedAST(str));
};
var toUnflattenedAST = function toUnflattenedAST(str) {
var tokenList = lexicalAnalysis(str.trim());
if (tokenList === null) {
throw createError('Failed tokenizing');
}
var startIndex = 0;
var endIndex = tokenList.length - 1;
if (tokenList[0].type === '<at-keyword-token>' && tokenList[0].value === 'media') {
if (tokenList[1].type !== '<whitespace-token>') {
throw createError('Expected whitespace after media');
}
startIndex = 2;
for (var i = 2; i < tokenList.length - 1; i++) {
var token = tokenList[i];
if (token.type === '<{-token>') {
endIndex = i;
break;
} else if (token.type === '<semicolon-token>') {
throw createError("Expected '{' in media query but found ';'");
}
}
}
tokenList = tokenList.slice(startIndex, endIndex);
return syntacticAnalysis(tokenList);
};
var removeWhitespace = function removeWhitespace(tokenList) {
var newTokenList = [];
var before = false;
for (var i = 0; i < tokenList.length; i++) {
if (tokenList[i].type === '<whitespace-token>') {
before = true;
if (newTokenList.length > 0) {
newTokenList[newTokenList.length - 1].wsAfter = true;
}
} else {
newTokenList.push(__assign(__assign({}, tokenList[i]), {
wsBefore: before,
wsAfter: false
}));
before = false;
}
}
return newTokenList;
};
var syntacticAnalysis = function syntacticAnalysis(tokenList) {
var e_1, _a;
var mediaQueryList = [[]];
for (var i = 0; i < tokenList.length; i++) {
var token = tokenList[i];
if (token.type === '<comma-token>') {
mediaQueryList.push([]);
} else {
mediaQueryList[mediaQueryList.length - 1].push(token);
}
}
var mediaQueries = mediaQueryList.map(removeWhitespace);
if (mediaQueries.length === 1 && mediaQueries[0].length === 0) {
return [{
mediaCondition: null,
mediaPrefix: null,
mediaType: 'all'
}];
} else {
var mediaQueryTokens = mediaQueries.map(function (mediaQueryTokens) {
if (mediaQueryTokens.length === 0) {
return null;
} else {
return tokenizeMediaQuery(mediaQueryTokens);
}
});
var nonNullMediaQueryTokens = [];
try {
for (var mediaQueryTokens_1 = __values(mediaQueryTokens), mediaQueryTokens_1_1 = mediaQueryTokens_1.next(); !mediaQueryTokens_1_1.done; mediaQueryTokens_1_1 = mediaQueryTokens_1.next()) {
var mediaQueryToken = mediaQueryTokens_1_1.value;
if (mediaQueryToken !== null) {
nonNullMediaQueryTokens.push(mediaQueryToken);
}
}
} catch (e_1_1) {
e_1 = {
error: e_1_1
};
} finally {
try {
if (mediaQueryTokens_1_1 && !mediaQueryTokens_1_1.done && (_a = mediaQueryTokens_1["return"])) _a.call(mediaQueryTokens_1);
} finally {
if (e_1) throw e_1.error;
}
}
if (nonNullMediaQueryTokens.length === 0) {
throw createError('No valid media queries');
}
return nonNullMediaQueryTokens;
}
};
var tokenizeMediaQuery = function tokenizeMediaQuery(tokens) {
var firstToken = tokens[0];
if (firstToken.type === '<(-token>') {
try {
return {
mediaPrefix: null,
mediaType: 'all',
mediaCondition: tokenizeMediaCondition(tokens, true)
};
} catch (err) {
throw createError("Expected media condition after '('", err);
}
} else if (firstToken.type === '<ident-token>') {
var mediaPrefix = null;
var mediaType = void 0;
var value = firstToken.value;
if (value === 'only' || value === 'not') {
mediaPrefix = value;
}
var firstIndex = mediaPrefix === null ? 0 : 1;
if (tokens.length <= firstIndex) {
throw createError("Expected extra token in media query");
}
var firstNonUnaryToken = tokens[firstIndex];
if (firstNonUnaryToken.type === '<ident-token>') {
var value_1 = firstNonUnaryToken.value;
if (value_1 === 'all') {
mediaType = 'all';
} else if (value_1 === 'print' || value_1 === 'screen') {
mediaType = value_1;
} else if (value_1 === 'tty' || value_1 === 'tv' || value_1 === 'projection' || value_1 === 'handheld' || value_1 === 'braille' || value_1 === 'embossed' || value_1 === 'aural' || value_1 === 'speech') {
mediaPrefix = mediaPrefix === 'not' ? null : 'not';
mediaType = 'all';
} else {
throw createError("Unknown ident '".concat(value_1, "' in media query"));
}
} else if (mediaPrefix === 'not' && firstNonUnaryToken.type === '<(-token>') {
var tokensWithParens = [{
type: '<(-token>',
wsBefore: false,
wsAfter: false
}];
tokensWithParens.push.apply(tokensWithParens, tokens);
tokensWithParens.push({
type: '<)-token>',
wsBefore: false,
wsAfter: false
});
try {
return {
mediaPrefix: null,
mediaType: 'all',
mediaCondition: tokenizeMediaCondition(tokensWithParens, true)
};
} catch (err) {
throw createError("Expected media condition after '('", err);
}
} else {
throw createError('Invalid media query');
}
if (firstIndex + 1 === tokens.length) {
return {
mediaPrefix: mediaPrefix,
mediaType: mediaType,
mediaCondition: null
};
} else if (firstIndex + 4 < tokens.length) {
var secondNonUnaryToken = tokens[firstIndex + 1];
if (secondNonUnaryToken.type === '<ident-token>' && secondNonUnaryToken.value === 'and') {
try {
return {
mediaPrefix: mediaPrefix,
mediaType: mediaType,
mediaCondition: tokenizeMediaCondition(tokens.slice(firstIndex + 2), false)
};
} catch (err) {
throw createError("Expected media condition after 'and'", err);
}
} else {
throw createError("Expected 'and' after media prefix");
}
} else {
throw createError('Expected media condition after media prefix');
}
} else {
throw createError('Expected media condition or media prefix');
}
};
var tokenizeMediaCondition = function tokenizeMediaCondition(tokens, mayContainOr, previousOperator) {
if (previousOperator === void 0) {
previousOperator = null;
}
if (tokens.length < 3 || tokens[0].type !== '<(-token>' || tokens[tokens.length - 1].type !== '<)-token>') {
throw new Error('Invalid media condition');
}
var endIndexOfFirstFeature = tokens.length - 1;
var maxDepth = 0;
var count = 0;
for (var i = 0; i < tokens.length; i++) {
var token = tokens[i];
if (token.type === '<(-token>') {
count += 1;
maxDepth = Math.max(maxDepth, count);
} else if (token.type === '<)-token>') {
count -= 1;
}
if (count === 0) {
endIndexOfFirstFeature = i;
break;
}
}
if (count !== 0) {
throw new Error('Mismatched parens\nInvalid media condition');
}
var child;
var featureTokens = tokens.slice(0, endIndexOfFirstFeature + 1);
if (maxDepth === 1) {
child = tokenizeMediaFeature(featureTokens);
} else {
if (featureTokens[1].type === '<ident-token>' && featureTokens[1].value === 'not') {
child = tokenizeMediaCondition(featureTokens.slice(2, -1), true, 'not');
} else {
child = tokenizeMediaCondition(featureTokens.slice(1, -1), true);
}
}
if (endIndexOfFirstFeature === tokens.length - 1) {
return {
operator: previousOperator,
children: [child]
};
} else {
var nextToken = tokens[endIndexOfFirstFeature + 1];
if (nextToken.type !== '<ident-token>') {
throw new Error('Invalid operator\nInvalid media condition');
} else if (previousOperator !== null && previousOperator !== nextToken.value) {
throw new Error("'".concat(nextToken.value, "' and '").concat(previousOperator, "' must not be at same level\nInvalid media condition"));
} else if (nextToken.value === 'or' && !mayContainOr) {
throw new Error("Cannot use 'or' at top level of a media query\nInvalid media condition");
} else if (nextToken.value !== 'and' && nextToken.value !== 'or') {
throw new Error("Invalid operator: '".concat(nextToken.value, "'\nInvalid media condition"));
}
var siblings = tokenizeMediaCondition(tokens.slice(endIndexOfFirstFeature + 2), mayContainOr, nextToken.value);
return {
operator: nextToken.value,
children: [child].concat(siblings.children)
};
}
};
var tokenizeMediaFeature = function tokenizeMediaFeature(rawTokens) {
if (rawTokens.length < 3 || rawTokens[0].type !== '<(-token>' || rawTokens[rawTokens.length - 1].type !== '<)-token>') {
throw new Error('Invalid media feature');
}
var tokens = [rawTokens[0]];
for (var i = 1; i < rawTokens.length; i++) {
if (i < rawTokens.length - 2) {
var a = rawTokens[i];
var b = rawTokens[i + 1];
var c = rawTokens[i + 2];
if (a.type === '<number-token>' && a.value > 0 && b.type === '<delim-token>' && b.value === 0x002f && c.type === '<number-token>' && c.value > 0) {
tokens.push({
type: '<ratio-token>',
numerator: a.value,
denominator: c.value,
wsBefore: a.wsBefore,
wsAfter: c.wsAfter
});
i += 2;
continue;
}
}
tokens.push(rawTokens[i]);
}
var nextToken = tokens[1];
if (nextToken.type === '<ident-token>' && tokens.length === 3) {
return {
context: 'boolean',
feature: nextToken.value
};
} else if (tokens.length === 5 && tokens[1].type === '<ident-token>' && tokens[2].type === '<colon-token>') {
var valueToken = tokens[3];
if (valueToken.type === '<number-token>' || valueToken.type === '<dimension-token>' || valueToken.type === '<ratio-token>' || valueToken.type === '<ident-token>') {
var feature = tokens[1].value;
var prefix = null;
var slice = feature.slice(0, 4);
if (slice === 'min-') {
prefix = 'min';
feature = feature.slice(4);
} else if (slice === 'max-') {
prefix = 'max';
feature = feature.slice(4);
}
valueToken.wsBefore;
valueToken.wsAfter;
var value = __rest(valueToken, ["wsBefore", "wsAfter"]);
return {
context: 'value',
prefix: prefix,
feature: feature,
value: value
};
}
} else if (tokens.length >= 5) {
try {
var range = tokenizeRange(tokens);
return {
context: 'range',
feature: range.featureName,
range: range
};
} catch (err) {
throw createError('Invalid media feature', err);
}
}
throw new Error('Invalid media feature');
};
var tokenizeRange = function tokenizeRange(tokens) {
var _a, _b, _c, _d;
if (tokens.length < 5 || tokens[0].type !== '<(-token>' || tokens[tokens.length - 1].type !== '<)-token>') {
throw new Error('Invalid range');
}
var range = {
leftToken: null,
leftOp: null,
featureName: '',
rightOp: null,
rightToken: null
};
var hasLeft = tokens[1].type === '<number-token>' || tokens[1].type === '<dimension-token>' || tokens[1].type === '<ratio-token>' || tokens[1].type === '<ident-token>' && tokens[1].value === 'infinite';
if (tokens[2].type === '<delim-token>') {
if (tokens[2].value === 0x003c) {
if (tokens[3].type === '<delim-token>' && tokens[3].value === 0x003d && !tokens[3].wsBefore) {
range[hasLeft ? 'leftOp' : 'rightOp'] = '<=';
} else {
range[hasLeft ? 'leftOp' : 'rightOp'] = '<';
}
} else if (tokens[2].value === 0x003e) {
if (tokens[3].type === '<delim-token>' && tokens[3].value === 0x003d && !tokens[3].wsBefore) {
range[hasLeft ? 'leftOp' : 'rightOp'] = '>=';
} else {
range[hasLeft ? 'leftOp' : 'rightOp'] = '>';
}
} else if (tokens[2].value === 0x003d) {
range[hasLeft ? 'leftOp' : 'rightOp'] = '=';
} else {
throw new Error('Invalid range');
}
if (hasLeft) {
range.leftToken = tokens[1];
} else if (tokens[1].type === '<ident-token>') {
range.featureName = tokens[1].value;
} else {
throw new Error('Invalid range');
}
var tokenIndexAfterFirstOp = 2 + ((_b = (_a = range[hasLeft ? 'leftOp' : 'rightOp']) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0);
var tokenAfterFirstOp = tokens[tokenIndexAfterFirstOp];
if (hasLeft) {
if (tokenAfterFirstOp.type === '<ident-token>') {
range.featureName = tokenAfterFirstOp.value;
if (tokens.length >= 7) {
var secondOpToken = tokens[tokenIndexAfterFirstOp + 1];
var followingToken = tokens[tokenIndexAfterFirstOp + 2];
if (secondOpToken.type === '<delim-token>') {
var charCode = secondOpToken.value;
if (charCode === 0x003c) {
if (followingToken.type === '<delim-token>' && followingToken.value === 0x003d && !followingToken.wsBefore) {
range.rightOp = '<=';
} else {
range.rightOp = '<';
}
} else if (charCode === 0x003e) {
if (followingToken.type === '<delim-token>' && followingToken.value === 0x003d && !followingToken.wsBefore) {
range.rightOp = '>=';
} else {
range.rightOp = '>';
}
} else {
throw new Error('Invalid range');
}
var tokenAfterSecondOp = tokens[tokenIndexAfterFirstOp + 1 + ((_d = (_c = range.rightOp) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : 0)];
range.rightToken = tokenAfterSecondOp;
} else {
throw new Error('Invalid range');
}
} else if (tokenIndexAfterFirstOp + 2 !== tokens.length) {
throw new Error('Invalid range');
}
} else {
throw new Error('Invalid range');
}
} else {
range.rightToken = tokenAfterFirstOp;
}
var validRange = null;
var lt = range.leftToken,
leftOp = range.leftOp,
featureName = range.featureName,
rightOp = range.rightOp,
rt = range.rightToken;
var leftToken = null;
if (lt !== null) {
if (lt.type === '<ident-token>') {
var type = lt.type,
value = lt.value;
if (value === 'infinite') {
leftToken = {
type: type,
value: value
};
}
} else if (lt.type === '<number-token>' || lt.type === '<dimension-token>' || lt.type === '<ratio-token>') {
lt.wsBefore;
lt.wsAfter;
var ltNoWS = __rest(lt, ["wsBefore", "wsAfter"]);
leftToken = ltNoWS;
}
}
var rightToken = null;
if (rt !== null) {
if (rt.type === '<ident-token>') {
var type = rt.type,
value = rt.value;
if (value === 'infinite') {
rightToken = {
type: type,
value: value
};
}
} else if (rt.type === '<number-token>' || rt.type === '<dimension-token>' || rt.type === '<ratio-token>') {
rt.wsBefore;
rt.wsAfter;
var rtNoWS = __rest(rt, ["wsBefore", "wsAfter"]);
rightToken = rtNoWS;
}
}
if (leftToken !== null && rightToken !== null) {
if ((leftOp === '<' || leftOp === '<=') && (rightOp === '<' || rightOp === '<=')) {
validRange = {
leftToken: leftToken,
leftOp: leftOp,
featureName: featureName,
rightOp: rightOp,
rightToken: rightToken
};
} else if ((leftOp === '>' || leftOp === '>=') && (rightOp === '>' || rightOp === '>=')) {
validRange = {
leftToken: leftToken,
leftOp: leftOp,
featureName: featureName,
rightOp: rightOp,
rightToken: rightToken
};
} else {
throw new Error('Invalid range');
}
} else if (leftToken === null && leftOp === null && rightOp !== null && rightToken !== null) {
validRange = {
leftToken: leftToken,
leftOp: leftOp,
featureName: featureName,
rightOp: rightOp,
rightToken: rightToken
};
} else if (leftToken !== null && leftOp !== null && rightOp === null && rightToken === null) {
validRange = {
leftToken: leftToken,
leftOp: leftOp,
featureName: featureName,
rightOp: rightOp,
rightToken: rightToken
};
}
return validRange;
} else {
throw new Error('Invalid range');
}
};
exports.consumeEscape = consumeEscape;
exports.consumeIdent = consumeIdent;
exports.consumeIdentLike = consumeIdentLike;
exports.consumeIdentUnsafe = consumeIdentUnsafe;
exports.consumeNumber = consumeNumber;
exports.consumeNumeric = consumeNumeric;
exports.consumeString = consumeString;
exports.consumeUrl = consumeUrl;
exports.lexicalAnalysis = lexicalAnalysis;
exports.removeWhitespace = removeWhitespace;
exports.syntacticAnalysis = syntacticAnalysis;
exports.toAST = toAST;
exports.toUnflattenedAST = toUnflattenedAST;
exports.tokenizeMediaCondition = tokenizeMediaCondition;
exports.tokenizeMediaFeature = tokenizeMediaFeature;
exports.tokenizeMediaQuery = tokenizeMediaQuery;
exports.tokenizeRange = tokenizeRange;
exports.wouldStartIdentifier = wouldStartIdentifier;
//# sourceMappingURL=index.js.map
export const parseMediaFeature = r => {
const e = m(r)
return d(e) ? e : o(e)
}
export const stringify = r => {
switch (r.type) {
case 'query-list':
return i(r)
case 'query':
return u(r)
case 'condition':
return c(r)
case 'feature':
return p(r)
default:
return f(r)
}
}
export * from './shared.js'
{
"name": "media-query-parser",
"version": "2.0.2",
"description": "Parse CSS media queries and merge",
"main": "dist/index.js",
"module": "dist/media-query-parser.esm.js",
"umd": "dist/media-query-parser.umd.js",
"typings": "dist/index.d.ts",
"files": [
"dist",
"coverage"
"description": "Parse CSS media queries (spec-compliant)",
"version": "3.0.0-beta.0",
"license": "MIT",
"keywords": [
"media",
"query",
"parser",
"compiler",
"token",
"typescript"
],
"author": {
"name": "Tom Golden",
"email": "github@tbjgolden.com",
"url": "https://github.com/tbjgolden"
},
"type": "module",
"main": "./dist/index.js",
"exports": "./dist/index.js",
"types": "./dist/index.d.ts",
"sideEffects": false,
"homepage": "https://github.com/tbjgolden/media-query-parser",

@@ -23,109 +24,78 @@ "repository": {

},
"scripts": {
"build": "yarn run clean && tsc -p tsconfig.build.json && rollup -c ./config/rollup.config.js && del compiled",
"clean": "concurrently \"del compiled\" \"del coverage\" \"del dist\"",
"coverage": "jest --config ./config/jest/config.src.ts",
"ctrl": "ctrl",
"lint": "eslint . --ext .ts,.tsx",
"start": "yarn watch",
"test": "concurrently \"yarn:lint\" \"yarn:build\" && concurrently \"jest --config ./config/jest/config.cjs.ts\" \"jest --config ./config/jest/config.es.ts\" \"jest --config ./config/jest/config.src.ts\" \"jest --config ./config/jest/config.umd.ts\"",
"typedoc": "typedoc --out docs/api --theme markdown --readme none --entryPoints \"src/index.ts\"",
"watch": "jest --config ./config/jest/config.src.ts --coverage=false --watch"
"author": {
"name": "Tom Golden",
"email": "oss@tom.bio",
"url": "https://tom.bio"
},
"husky": {
"hooks": {
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS",
"pre-commit": "pretty-quick --staged"
}
"engines": {
"node": ">=16.0.0 || ^14.13.1"
},
"keywords": [
"typescript"
],
"license": "MIT",
"bugs": {
"url": "github:tbjgolden/media-query-parser/issues"
"scripts": {
"build": "xnr ./.scripts/build.ts",
"check-build": "xnr ./.scripts/checkBuild.ts",
"test": "NODE_OPTIONS='--experimental-vm-modules --no-warnings' npx jest",
"prepare": "simple-git-hooks"
},
"peerDependencies": {},
"dependencies": {
"@babel/runtime": "^7.12.5"
},
"devDependencies": {
"@babel/core": "^7.12.10",
"@babel/plugin-proposal-class-properties": "7.16.7",
"@babel/plugin-transform-runtime": "7.16.8",
"@babel/preset-env": "7.16.8",
"@commitlint/cli": "^16.0.2",
"@commitlint/config-conventional": "^16.0.0",
"@rollup/plugin-babel": "^5.2.2",
"@rollup/plugin-commonjs": "^21.0.1",
"@rollup/plugin-json": "^4.1.0",
"@rollup/plugin-node-resolve": "^13.1.3",
"@types/dedent": "^0.7.0",
"@types/jest": "27.4.0",
"@types/mkdirp": "^1.0.1",
"@typescript-eslint/eslint-plugin": "5.9.1",
"@typescript-eslint/parser": "5.9.1",
"babel-core": "6.26.3",
"babel-loader": "^8.2.2",
"classnames": "^2.2.6",
"commitizen": "^4.2.3",
"concurrently": "^7.0.0",
"cp-cli": "2.0.0",
"cross-env": "7.0.3",
"ctrl-scripts": "^0.1.0",
"dedent": "^0.7.0",
"del-cli": "4.0.1",
"enquirer": "^2.3.6",
"eslint": "8.6.0",
"eslint-config-prettier": "8.3.0",
"eslint-plugin-jest": "^26.1.1",
"fast-glob": "^3.2.5",
"fork-ts-checker-webpack-plugin": "^6.1.0",
"fs-extra": "^10.0.0",
"husky": "^7.0.4",
"jest": "27.4.7",
"mkdirp": "^1.0.4",
"prettier": "2.5.1",
"pretty-quick": "^3.1.0",
"regenerator-runtime": "0.13.9",
"rollup": "2.63.0",
"rollup-plugin-filesize": "9.1.2",
"rollup-plugin-terser": "7.0.2",
"run-parallel": "^1.1.10",
"semantic-release": "^18.0.1",
"ts-jest": "27.1.2",
"ts-loader": "^9.2.6",
"ts-node": "^10.4.0",
"typedoc": "^0.22.10",
"typedoc-plugin-markdown": "^3.4.3",
"typescript": "4.6.2"
"@types/eslint": "^8.37.0",
"@types/jest": "^29.5.1",
"@typescript-eslint/eslint-plugin": "^5.59.5",
"@typescript-eslint/parser": "^5.59.5",
"eslint": "^8.40.0",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-security": "^1.7.1",
"eslint-plugin-unicorn": "^47.0.0",
"jest": "^29.5.0",
"lint-time": "^0.1.1",
"msg-time": "^0.1.0",
"prettier": "2.8.8",
"pub-time": "^0.1.0",
"simple-git-hooks": "^2.8.1",
"terser": "^5.17.7",
"typescript": ">=5.0.4",
"xnr": "^1.1.2"
},
"commitlint": {
"extends": [
"@commitlint/config-conventional"
]
"files": [
"dist"
],
"simple-git-hooks": {
"commit-msg": "npx msg-time",
"pre-commit": "npx lint-time",
"pre-push": "npx jest -o --coverage=false --passWithNoTests"
},
"release": {
"branches": [
"main"
]
},
"prettier": {
"semi": false,
"singleQuote": true,
"printWidth": 80,
"tabWidth": 2,
"useTabs": false,
"quoteProps": "consistent",
"trailingComma": "none",
"bracketSpacing": true,
"jsxBracketSameLine": false,
"arrowParens": "always",
"proseWrap": "always",
"htmlWhitespaceSensitivity": "strict"
"printWidth": 100,
"proseWrap": "always"
},
"eslintConfig": {
"root": true,
"extends": "./config/eslint.config.js"
"lint-time": [
[
"*.ts",
"npx eslint -c .eslintrc.cjs --cache --fix --max-warnings=0"
],
[
"*.{ts,js,cjs,mjs,json}",
"npx prettier --ignore-path .gitignore --write"
]
],
"jest": {
"clearMocks": true,
"coverageReporters": [
"json-summary",
"text"
],
"errorOnDeprecated": true,
"extensionsToTreatAsEsm": [
".ts",
".mts"
],
"resolver": "<rootDir>/.scripts/jestResolver.cjs",
"testEnvironment": "node",
"testMatch": [
"<rootDir>/lib/**/*.test.[tj]s"
],
"transform": {
"\\.ts$": "<rootDir>/node_modules/xnr/jest.js"
}
}
}
# `media-query-parser`
[![npm version](https://img.shields.io/npm/v/media-query-parser.svg?style=flat-square)](https://www.npmjs.com/package/media-query-parser)
![npm bundle size](https://img.shields.io/bundlephobia/minzip/media-query-parser?style=flat-square)
[![test coverage](https://img.shields.io/badge/dynamic/json?style=flat-square&color=brightgreen&label=coverage&query=%24.total.branches.pct&url=https%3A%2F%2Fraw.githubusercontent.com%2Ftbjgolden%2Fmedia-query-parser%2Fmain%2Fcoverage%2Fcoverage-summary.json)](https://www.npmjs.com/package/media-query-parser)
[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/tbjgolden/media-query-parser/Release?style=flat-square)](https://github.com/tbjgolden/media-query-parser/actions?query=workflow%3ARelease)
> This package's v3 (currently in beta) involves a complete overhaul from v2 to a more sustainable
> shape.
> [See v2 API docs instead](https://github.com/tbjgolden/media-query-parser/tree/v2.0.2/docs/api#functions)
- [x] **Parses correct CSS media queries**
- [x] **Fails on invalid CSS media queries**
- [x] **Spec-compliant** - https://www.w3.org/TR/mediaqueries-4/
- [x] **Zero-dependencies**
- [x] **TypeScript friendly**
- [x] **All valid queries parsed, even newer ones like
`@media (100px < width < 200px)`**
![npm](https://img.shields.io/npm/v/media-query-parser)
![npm type definitions](https://img.shields.io/npm/types/media-query-parser)
![license](https://img.shields.io/npm/l/media-query-parser)
![npm downloads](https://img.shields.io/npm/dw/media-query-parser)
[![install size](https://packagephobia.com/badge?p=media-query-parser)](https://packagephobia.com/result?p=media-query-parser)
## Quickfire examples
- **Create a JS object from a CSS media queries**
- **Create a CSS media query from a JS object**
- **Returns a ParserError for invalid CSS media queries**
- **Spec-compliant** - https://www.w3.org/TR/mediaqueries-5/
- **All valid queries parsed; e.g. `(100px < width < 200px)`**
- **Zero-dependencies**
- **Well tested**
- **TypeScript friendly**
```js
import { toAST } from 'media-query-parser'
> This repo/package contains only the parser, stringify and isParserError.
>
> `media-query-fns` uses this library internally to achieve common use-cases.
// Simple responsive media query
console.log(toAST('(max-width: 768px)'))
/* [
{
"mediaPrefix":null,
"mediaType":"all",
"mediaCondition":{
"operator":null,
"children":[
{"context":"value",
"prefix":"max",
"feature":"width",
"value":{"type":"<dimension-token>","value":768,"unit":"px","flag":"number"}
}
]
}
}
] */
**_[You can try it out!](https://tbjgolden.github.io/media-query-parser/)_**
// Supports comma separated media-query lists
console.log(toAST('print, (not (color))'))
// Trims the `@media` if it starts with it, the `{` and anything that follows
console.log(toAST('@media screen { body { background: #000 } }'))
// Full support for new range syntax
console.log(toAST('(100px < width < 200px)'))
// ...which was no mean feat...
console.log(toAST('(4/3 <= aspect-ratio <= 16/9)'))
// Throws an Error with invalid media query syntax
console.log(toAST('clearly this is not a valid media query')) // => Error
// ...even the normal looking but invalid ones:
{
console.log(toAST('(max-width: 768px) and screen')) // => Error
// explanation: screen must be on left hand side
console.log(toAST('screen and (max-width: 768px) or (hover)')) // => Error
// explanation: spec disallows `and` and `or` on same level as ambiguous
![banner](banner.svg)
## Install
This package is available from the `npm` registry.
```sh
npm install media-query-parser
```
## Usage
Supports JavaScript + TypeScript:
```ts
import { parseMediaQuery } from "media-query-parser";
const mediaQuery = parseMediaQuery("screen and (width <= 768px)");
if (!isParserError(mediaQuery)) {
console.log(mediaQuery);
// {
// type: "query",
// mediaType: "screen",
// mediaCondition: {
// type: "condition",
// children: [
// {
// type: "feature",
// feature: "width",
// context: "range",
// range: {
// featureName: "width",
// rightOp: "<=",
// rightToken: {
// type: "dimension",
// value: 768,
// unit: "px",
// flag: "number"
// },
// },
// },
// ],
// },
// }
console.log(stringify(mediaQuery.mediaCondition.children[0]));
// "(width <= 768px)"
}
```
Can also be imported via `require("media-query-parser")`.
## Considerations & Caveats
This library does:
This library **does**:
- follow the spec's CSS syntax / media query parsing rules
- remove extra layers from unnecessary parentheses `(((((max-width: 768px)))))`
- parses units, numbers and other values to the spec
- handle unusual whitespace anywhere that the spec allows it
- contain many a unit test
This library does not:
This library **will not**:
- sanity check the actual media features or their types `(max-power: infinite)`
is as valid as `(hover: none)`
- normalize the media query features (e.g. `(max-width: -100px)` is always
`false`)
- sanity check the actual media features or their types beyond the parser rules; so
`(max-power: infinite)` is as valid as `(min-width: 768px)`
- support `calc()` or `var()` - functions are disallowed by the spec, even though some browsers seem
to support them. If/when the spec allows them they'll be added in a new major version
Note that:
## Contributing
- **Handling individual media features is being developed in a separate project:
[media-query-fns](https://github.com/tbjgolden/media-query-fns)**
- PRs welcome and accepted, simply fork and create
- Issues also very welcome
- Treat others with common courtesy and respect 🤝
## Installation
Dev environment (for contributing) requires:
```sh
npm install media-query-parser --save
# yarn add media-query-parser
```
- node >= 16.14.0
- npm >= 6.8.0
- git >= 2.11
Alternatively, there are also client web builds available:
## Licence
```html
<!-- window.MediaQueryParser -->
<script src="https://unpkg.com/media-query-parser/dist/media-query-parser.umd.js"></script>
```
## [`API`](docs/api)
## License
MIT
<!-- Original starter readme: https://github.com/tbjgolden/create-typescript-react-library -->
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc