Is given string a valid media descriptor (including media query)?

§ Quick Take

import { strict as assert } from "assert";
import isMediaD from "dist/is-media-descriptor.esm";

assert.deepEqual(isMediaD("screeen"), [
    idxFrom: 0,
    idxTo: 7,
    message: `Did you mean "screen"?`,
    fix: {
      ranges: [[0, 7, "screen"]],

§ Purpose

We are talking about so-called media descriptors (older spec opens in a new tab, newer spec - CSS MQ Level 4, draft at the moment opens in a new tab), for example, the part screen and (color), projection and (color) in both HTML and CSS:

<link media="screen and (color), projection and (color)" rel="stylesheet" href="example.css">

<link media="screen and (color), projection and (color)" rel="stylesheet" href="example.css" />

<?xml-stylesheet media="screen and (color), projection and (color)" rel="stylesheet" href="example.css" ?>

@import url(example.css) screen and (color), projection and (color);

@media screen and (color), projection and (color) { ... }

We plan to catch as many errors as possible:

  • typos
  • unclosed brackets
  • redundant characters
  • untangle the boolean logic
  • ... anything that can happen to media queries and media selectors in general.

This is not a replacement for the validator; this is a linting tool. We will use it in emlint.

Conceptually, CSS spec is very permissive, if it doesn't like something it invalidates that part and moves on. In this light, linting needs to be the opposite.

§ API - Input

isMediaD(str, opts)

In other words, a function which takes a string and options, a plain object.

Input argumentTypeObligatory?Description
strStringnoThe extracted value of HTML media attribute or CSS media query without @media or opening bracket.
optsPlain objectnoOptional options go here.

For example, all the calls below will yield an empty array (no errors):

isMediaD("screen", {});
isMediaD("screen", null);
isMediaD("screen", { offset: 0 });
isMediaD("screen", { offset: 51 });

⚠️ A bad example is below - don't put @media, please extract the value:

// program won't work with `@media` - extract the value first!
"@media only (screen) and (min-width: 320px) and (max-width: 500px) {"

Feed function with extracted value, with no @media:

isMediaD("only (screen) and (min-width: 320px) and (max-width: 500px)");

If an input is not a string or an empty string, an empty array will be returned.

§ Options object

options object's keyTypeObligatory?DefaultDescription
offsetIntegerno0All reported indexes will be incremented by this much.

Falsy opt.offset is fine but something truthy which is not a natural number will throw.

§ API - Output

The program returns an array of zero or more plain objects, each meaning an error. Each object's notation is the same as in emlint (except there's no ruleId):

idxFrom: 21,
idxTo: 22,
message: `Rogue bracket.`,
fix: {
ranges: [[21, 22]]

Quick basics: idxFrom and idxTo are the same as in String.slice, just used for marking.

The fix key is either null or has value — plain object — with key ranges. ESLint uses singular, range, EMLint uses ranges, plural, because EMLint uses Ranges notation — where ESLint marks "to add" thing separately, EMLint puts it as the third element in ranges array.

Ranges are always either null or array of arrays.

EMLint and ranges arrays here follow Ranges notation and all Ranges packages can be used to process them — merging, inverting, resolving/applying and so on.

§ Competition

There are capable CSS parsers out there, but they are all oriented at parsing the correct code and strictly pure HTML or CSS. Code validators built upon such parsers are not really serious validators.

Conceptually, code checking tools should use advanced but slow parsers, likely scanerless-ones to find and fix errors. Then, for general parsing (like syntax highlighting), parsers which can't recognise many errors but are fast should be used.

We're talking about two different levels of the "food-chain". Currently, there is not much competition for this program in this sense.

§ Licence

MIT opens in a new tab

Copyright © 2010–2020 Roy Revelt and other contributors

Related packages:

📦 emlint 2.18.17
Pluggable email template code linter
📦 html-crush 2.0.9
Minifies HTML/CSS: valid or broken, pure or mixed with other languages
📦 string-strip-html 6.0.4
Strips HTML tags from strings. No parser, accepts mixed sources.
📦 detect-is-it-html-or-xhtml 3.10.0
Answers, is the string input string more an HTML or XHTML (or neither)
📦 html-table-patcher 2.0.12
Visual helper to place templating code around table tags into correct places
📦 is-html-tag-opening 1.8.3
Is given opening bracket a beginning of a tag?
📦 is-html-attribute-closing 1.2.8
Is a character on a given index a closing of an HTML attribute?