Git Product home page Git Product logo

postcss-media-query-parser's Introduction

postcss-media-query-parser

NPM version Build Status

Media query parser with very simple traversing functionality.

Installation and usage

First install it via NPM:

npm install postcss-media-query-parser

Then in your Node.js application:

import mediaParser from "postcss-media-query-parser";

const mediaQueryString = "(max-width: 100px), not print";
const result = mediaParser(mediaQueryString);

The result will be this object:

{
  type: 'media-query-list',
  value: '(max-width: 100px), not print',
  after: '',
  before: '',
  sourceIndex: 0,

  // the first media query
  nodes: [{
    type: 'media-query',
    value: '(max-width: 100px)',
    before: '',
    after: '',
    sourceIndex: 0,
    parent: <link to parent 'media-query-list' node>,
    nodes: [{
      type: 'media-feature-expression',
      value: '(max-width: 100px)',
      before: '',
      after: '',
      sourceIndex: 0,
      parent: <link to parent 'media-query' node>,
      nodes: [{
        type: 'media-feature',
        value: 'max-width',
        before: '',
        after: '',
        sourceIndex: 1,
        parent: <link to parent 'media-feature-expression' node>,
      }, {
        type: 'colon',
        value: ':',
        before: '',
        after: ' ',
        sourceIndex: 10,
        parent: <link to parent 'media-feature-expression' node>,
      }, {
        type: 'value',
        value: '100px',
        before: ' ',
        after: '',
        sourceIndex: 12,
        parent: <link to parent 'media-feature-expression' node>,
      }]
    }]
  },
  // the second media query
  {
    type: 'media-query',
    value: 'not print',
    before: ' ',
    after: '',
    sourceIndex: 20,
    parent: <link to parent 'media-query-list' node>,
    nodes: [{
      type: 'keyword',
      value: 'not',
      before: ' ',
      after: ' ',
      sourceIndex: 20,
      parent: <link to parent 'media-query' node>,
    }, {
      type: 'media-type',
      value: 'print',
      before: ' ',
      after: '',
      sourceIndex: 24,
      parent: <link to parent 'media-query' node>,
    }]
  }]
}

One of the likely sources of a string to parse would be traversing a PostCSS container node and getting the params property of nodes with the name of "atRule":

import postcss from "postcss";
import mediaParser from "postcss-media-query-parser";

const root = postcss.parse(<contents>);
// ... or any other way to get sucn container

root.walkAtRules("media", (atRule) => {
  const mediaParsed = mediaParser(atRule.params);
  // Do something with "mediaParsed" object
});

Nodes

Node is a very generic item in terms of this parser. It's is pretty much everything that ends up in the parsed result. Each node has these properties:

  • type: the type of the node (see below);
  • value: the node's value stripped of trailing whitespaces;
  • sourceIndex: 0-based index of the node start relative to the source start (excluding trailing whitespaces);
  • before: a string that contain a whitespace between the node start and the previous node end/source start;
  • after: a string that contain a whitespace between the node end and the next node start/source end;
  • parent: a link to this node's parent node (a container).

A node can have one of these types (according to the 2012 CSS3 standard):

  • media-query-list: that is the root level node of the parsing result. A container; its children can have types of url and media-query.
  • url: if a source is taken from a CSS @import rule, it will have a url(...) function call. The value of such node will be url(http://uri-address), it is to be parsed separately.
  • media-query: such nodes correspond to each media query in a comma separated list. In the exapmle above there are two. Nodes of this type are containers.
  • media-type: screen, tv and other media types.
  • keyword: only, not or and keyword.
  • media-feature-expression: an expression in parentheses that checks for a condition of a particular media feature. The value would be like this: (max-width: 1000px). Such nodes are containers. They always have a media-feature child node, but might not have a value child node (like in screen and (color)).
  • media-feature: a media feature, e.g. max-width.
  • colon: present if a media feature expression has a colon (e.g. (min-width: 1000px), compared to (color)).
  • value: a media feature expression value, e.g. 100px in (max-width: 1000px).

Parsing details

postcss-media-query-parser allows for cases of some non-standard syntaxes and tries its best to work them around. For example, in a media query from a code with SCSS syntax:

@media #{$media-type} and ( #{"max-width" + ": 10px"} ) { ... }

#{$media-type} will be the node of type media-type, alghough $media-type's value can be only screen. And inside media-feature-expression there will only be a media-feature type node with the value of #{"max-width" + ": 10px"} (this example doesn't make much sense, it's for demo purpose).

But the result of parsing malformed media queries (such as with incorrect amount of closing parens, curly braces, etc.) can be unexpected. For exapmle, parsing:

@media ((min-width: -100px)

would return a media query list with the single media-query node that has no child nodes.

Containers

Containers are nodes that have other nodes as children. Container nodes have an additional property nodes which is an array of their child nodes. And also these methods:

  • each(callback) - traverses the direct child nodes of a container, calling callback function for each of them. Returns false if traversing has stopped by means of callback returning false, and true otherwise.
  • walk([filter, ]callback) - traverses ALL descendant nodes of a container, calling callback function for each of them. Returns false if traversing has stopped by means of callback returning false, and true otherwise.

In both cases callback takes these parameters:

  • node - the current node (one of the container's descendats, that the callback has been called against).
  • i - 0-based index of the node in an array of its parent's children.
  • nodes - array of child nodes of node's parent.

If callback returns false, the traversing stops.

License

MIT

postcss-media-query-parser's People

Contributors

dryoma avatar olegskl avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

postcss-media-query-parser's Issues

Modify media query

Hi!

Do you want to make the ability to modify media queries?

Add methods for adding media queries and media feature expressions, add method for generate css code from object?

I see that now the package can only read media queries structures.

Terminology query

@dryoma Thanks again for this module! We're already putting it to work in a new rule :)

I had a query around the terminology used for media features.

media-type, media-query and keyword seem aligned with these links. However, the media-query-expression and media-feature appear misaligned. Should they be?:

  • media-feature-expressionmedia-feature
  • media-featurename
  • valuevalue

Handle comments

Currently, comments are not considered during parsing. I'd propose adding a new node type media-query-comment for them. Both standard CSS comments (/* */) and single-line SCSS comments (//) should be handled.

Since this would constitute a breaking change, I'd propose adding an option to the parse method for whether to handle comments or not (defaulting to not).

Would you be interested in a PR that implements this?

This relates to prettier/prettier#8915

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.