Giter VIP home page Giter VIP logo

shady-css-parser's Introduction

Shady CSS Parser

The motivation for Shady CSS Parser is to provide a fast, small and flexible CSS parser suitable for facilitating runtime parsing and transformation of CSS. The Polymer library and the Polymer Designer tool are both example cases where fast and flexible CSS parsing and transformation is a critical feature.

Goals

  • Feasibility of being used in conjunction with Polymer or Polymer Designer.
  • Parse CSS loosely and flexibly. This parser is not spec-compliant, however it will parse all spec-compliant CSS.
  • Parse CSS quickly and efficiently. This parser is a suitable tool to aide in the design and implementation of runtime transformations.
  • Graceful error recovery. Malformed CSS will be parsed by this parser as closely as possible to the way a browser would parse it.

Installing

With node and npm installed, run the following command:

npm install shady-css-parser

Building

Run the following commands from the project root:

npm install
gulp

This will create a dist directory containing distributable artifacts.

Usage

Basic parsing

var css = 'body { color: red; }';
var parser = new shadyCss.Parser();
var ast = parser.parse(css);

Custom parsing

/* Step 1: Inherit from NodeFactory */
function CustomNodeFactory() {
  shadyCss.NodeFactory.apply(this, arguments);
}

CustomNodeFactory.prototype = Object.create(shadyCss.NodeFactory.prototype);

/* Step 2: Implement a custom node factory method. Here we override the default
 * factory for Expression nodes */
CustomNodeFactory.prototype.expression = function(text) {
  if (/^darken\(/.test(text)) {
    return {
      type: 'darkenExpression',
      color: text.replace(/^darken\(/, '').replace(/\)$/, '')
    };
  } else {
    return shadyCss.NodeFactory.prototype.expression.apply(this, arguments);
  }
}

var css = 'body { color: darken(red); }';
/* Step 3: Instantiate a Parser with an instance of the specialized
 * CustomNodeFactory */
var parser = new shadyCss.Parser(new CustomNodeFactory());
var ast = parser.parse(css);

Basic stringification

var stringifier = new shadyCss.Stringifier();
stringifier.stringify(ast);

Note: the built-in Parser and Stringifier discard most insignficiant whitespace from parsed CSS.

Custom stringification

/* Step 1: Inherit from Stringifier. */
function CustomStringifier() {
  shadyCss.Stringifier.apply(this, arguments);
}

CustomStringifier.prototype = Object.create(shadyCss.Stringifier.prototype);

/* Step 2: Implement a stringification method named after the type of the node
 * you are interested in stringifying. In this case, we are implementing
 * stringification for the Darken Expression nodes we implemented parsing for
 * above. */
CustomStringifier.prototype.darkenExpression = function(darkenExpression) {
  // For the sake of brevity, please assume that the darken function returns
  // a darker version of the color parameter:
  return darken(darkenExpression.color);
};

/* Step 3: Use the custom stringifer: */
var stringifier = new CustomStringifier();
var css = stringifier.stringify(ast);

Example ASTs

Custom property declaration

.container {
  --nog: blue;
}
{
  "type": 1, /* stylesheet */
  "rules": [
    {
      "type": 4, /* ruleset */
      "selector": ".container",
      "rulelist": {
        "type": 7, /* rulelist */
        "rules": [
          {
            "type": 6, /* declaration */
            "name": "--nog",
            "value": {
              "type": 5, /* expression */
              "text": "blue"
            }
          }
        ]
      }
    }
  ]
}

Mixin declaration

ruleset {
  --mixin-name: {
    /* rules */
  };
}
{
  "type": 1, /* stylesheet */
  "rules": [
    {
      "type": 4, /* ruleset */
      "selector": "ruleset",
      "rulelist": {
        "type": 7, /* rulelist */
        "rules": [
          {
            "type": 6, /* declaration */
            "name": "--mixin-name",
            "value": {
              "type": 7, /* rulelist */
              "rules": [
                {
                  "type": 2, /* comment */
                  "value": "\/* rules *\/"
                }
              ]
            }
          }
        ]
      }
    }
  ]
}

Mixin application

.title {
  @apply(--my-toolbar-title-theme);
}
{
  "type": 1, /* stylesheet */
  "rules": [
    {
      "type": 4, /* ruleset */
      "selector": ".title",
      "rulelist": {
        "type": 7, /* rulelist */
        "rules": [
          {
            "type": 3, /* at rule */
            "name": "apply",
            "parameters": "(--my-toolbar-title-theme)",
            "rulelist": null
          }
        ]
      }
    }
  ]
}

Pathological comments

/* unclosed
@fiz {
  --huk: {
    /* buz */
    baz: lur;
  };
}
{
  "type": 1, /* stylesheet */
  "rules": [
    {
      "type": 2, /* comment */
      "value": "\/* unclosed\n@fiz {\n  --huk: {\n    \/* buz *\/"
    },
    {
      "type": 6, /* declaration */
      "name": "baz",
      "value": {
        "type": 5, /* expression */
        "text": "lur"
      }
    },
    {
      "type": 8, /* discarded */
      "text": "};\n"
    },
    {
      "type": 8, /* discarded */
      "text": "}"
    }
  ]
}

Example stringification

Basic ruleset

/* before */
body {
  margin: 0;
  padding: 0px
}
/* after */
body{margin:0;padding:0px;}

At rules

/* before */
@import url('foo.css');

@font-face {
  font-family: foo;
}

@charset 'foo';
/* after */
@import url('foo.css');@font-face{font-family:foo;}@charset 'foo';

Custom properties

/* before */
:root {
  --qux: vim;
  --foo: {
    bar: baz;
  };
}

#target {
  gak: var(--qux);
  @apply(--foo);
}
/* after */
:root{--qux:vim;--foo:{bar:baz;};}#target{gak:var(--qux);@apply (--foo);}

shady-css-parser's People

Contributors

cdata avatar

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.