• Stars
    star
    139
  • Rank 262,954 (Top 6 %)
  • Language
    Ruby
  • License
    MIT License
  • Created about 11 years ago
  • Updated 6 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A Ruby CSS parser that's fully compliant with the CSS Syntax Level 3 specification.

Crass

Crass is a Ruby CSS parser that's fully compliant with the CSS Syntax Level 3 specification.

Gem Version Tests

Links

Features

  • Pure Ruby, with no runtime dependencies other than Ruby 1.9.x or higher.

  • Tokenizes and parses CSS according to the rules defined in the 14 November 2014 editor's draft of the CSS Syntax Level 3 specification.

  • Extremely tolerant of broken or invalid CSS. If a browser can handle it, Crass should be able to handle it too.

  • Optionally includes comments in the token stream.

  • Optionally preserves certain CSS hacks, such as the IE "*" hack, which would otherwise be discarded according to CSS3 tokenizing rules.

  • Capable of serializing the parse tree back to CSS while maintaining all original whitespace, comments, and indentation.

Problems

  • Crass isn't terribly fast. I mean, it's Ruby, and it's not really slow by Ruby standards. But compared to the CSS parser in your average browser? Yeah, it's slow.

  • Crass only parses the CSS syntax; it doesn't understand what any of it means, doesn't coalesce selectors, etc. You can do this yourself by consuming the parse tree, though.

  • While any node in the parse tree (or the parse tree as a whole) can be serialized back to CSS with perfect fidelity, changes made to those nodes (except for wholesale removal of nodes) are not reflected in the serialized output.

  • Crass only supports UTF-8 input and doesn't respect @charset rules. Input in any other encoding will be converted to UTF-8.

Installing

gem install crass

Examples

Say you have a string containing some CSS:

/* Comment! */
a:hover {
  color: #0d8bfa;
  text-decoration: underline;
}

Parsing it is simple:

tree = Crass.parse(css, :preserve_comments => true)

This returns a big beautiful parse tree, which looks like this:

[{:node=>:comment, :pos=>0, :raw=>"/* Comment! */", :value=>" Comment! "},
 {:node=>:whitespace, :pos=>14, :raw=>"\n"},
 {:node=>:style_rule,
  :selector=>
   {:node=>:selector,
    :value=>"a:hover",
    :tokens=>
     [{:node=>:ident, :pos=>15, :raw=>"a", :value=>"a"},
      {:node=>:colon, :pos=>16, :raw=>":"},
      {:node=>:ident, :pos=>17, :raw=>"hover", :value=>"hover"},
      {:node=>:whitespace, :pos=>22, :raw=>" "}]},
  :children=>
   [{:node=>:whitespace, :pos=>24, :raw=>"\n  "},
    {:node=>:property,
     :name=>"color",
     :value=>"#0d8bfa",
     :children=>
      [{:node=>:whitespace, :pos=>33, :raw=>" "},
       {:node=>:hash,
        :pos=>34,
        :raw=>"#0d8bfa",
        :type=>:unrestricted,
        :value=>"0d8bfa"}],
     :important=>false,
     :tokens=>
      [{:node=>:ident, :pos=>27, :raw=>"color", :value=>"color"},
       {:node=>:colon, :pos=>32, :raw=>":"},
       {:node=>:whitespace, :pos=>33, :raw=>" "},
       {:node=>:hash,
        :pos=>34,
        :raw=>"#0d8bfa",
        :type=>:unrestricted,
        :value=>"0d8bfa"}]},
    {:node=>:semicolon, :pos=>41, :raw=>";"},
    {:node=>:whitespace, :pos=>42, :raw=>"\n  "},
    {:node=>:property,
     :name=>"text-decoration",
     :value=>"underline",
     :children=>
      [{:node=>:whitespace, :pos=>61, :raw=>" "},
       {:node=>:ident, :pos=>62, :raw=>"underline", :value=>"underline"}],
     :important=>false,
     :tokens=>
      [{:node=>:ident,
        :pos=>45,
        :raw=>"text-decoration",
        :value=>"text-decoration"},
       {:node=>:colon, :pos=>60, :raw=>":"},
       {:node=>:whitespace, :pos=>61, :raw=>" "},
       {:node=>:ident, :pos=>62, :raw=>"underline", :value=>"underline"}]},
    {:node=>:semicolon, :pos=>71, :raw=>";"},
    {:node=>:whitespace, :pos=>72, :raw=>"\n"}]}]

If you want, you can stringify the parse tree:

css = Crass::Parser.stringify(tree)

...which gives you back exactly what you put in!

/* Comment! */
a:hover {
  color: #0d8bfa;
  text-decoration: underline;
}

Wasn't that exciting?

Versioning

As of version 1.0.0, Crass adheres strictly to SemVer 2.0.

Contributing

The best way to contribute is to use Crass and create issues when you run into problems.

Pull requests that fix bugs are more than welcome as long as they include tests. Please adhere to the style and format of the surrounding code, or I might ask you to change things.

If you want to add a feature or refactor something, please get in touch first to make sure I'm on board with your idea and approach; I'm pretty picky, and I'd hate to have to turn down a pull request you spent a lot of time on.

Acknowledgments

I'm deeply grateful to Simon Sapin for his wonderfully comprehensive CSS parsing tests, which I adapted to create many of Crass's tests. They've been invaluable in helping me fix bugs and handle weird edge cases, and Crass would be much crappier without them.

I'm also grateful to Tab Atkins-Bittner and Simon Sapin (again!) for their work on the CSS Syntax Level 3 specification, which defines the tokenizing and parsing rules that Crass implements.

More Repositories

1

rawgit

Served files from raw.githubusercontent.com, but with the correct content types. No longer actively developed.
JavaScript
2,390
star
2

sanitize

Ruby HTML and CSS sanitizer.
HTML
2,020
star
3

lazyload

💀 An ancient tiny JS and CSS loader from the days before everyone had written one. Unmaintained.
JavaScript
1,391
star
4

larch

💀 Larch copies messages from one IMAP server to another. No longer maintained.
Ruby
616
star
5

jsmin-php

💀 PHP port of Douglas Crockford's JSMin JavaScript minifier. No longer maintained.
PHP
423
star
6

parse-xml

A fast, safe, compliant XML parser for Node.js and browsers.
JavaScript
259
star
7

combohandler

A simple Yahoo!-style combo handler in Node.js.
JavaScript
116
star
8

node-elastical

💀 Elastical has moved to https://github.com/ramv/node-elastical and this repo is no longer maintained. Please update your bookmarks!
JavaScript
101
star
9

thoth

💀 An unmaintained and probably broken Ruby blog engine.
Ruby
67
star
10

emergencykitten

Sometimes you just need a kitten.
JavaScript
66
star
11

jsmin

💀 Ruby library for minifying JavaScript. Based on Douglas Crockford's jsmin.c. Unmaintained.
JavaScript
51
star
12

textual-sulaco

Sulaco, a style for the Textual IRC client
HTML
44
star
13

synchrotron

Watches a local directory and syncs files to another directory or a remote destination using rsync whenever changes occur.
JavaScript
40
star
14

cssmin

💀 Ruby library for minifying CSS. Unmaintained.
Ruby
38
star
15

selleck

💀 Now maintained at https://github.com/yui/selleck
JavaScript
38
star
16

storage-lite

💀 Lightweight YUI 3 API for persistent cross-browser key/value storage similar to the HTML5 localStorage API. Unmaintained.
JavaScript
29
star
17

pie.gd

Config files, scripts, and documentation for the pie.gd Mastodon instance.
Dockerfile
23
star
18

lectroid

💀 A really boring blog engine. Unmaintained.
JavaScript
17
star
19

cachetest

💀 A Sinatra app for testing browser cache characteristics. Unmaintained.
Ruby
16
star
20

trogdor

💀 A fast, simple search-as-you-type implementation in JavaScript using the Yahoo! Search BOSS API. Unmaintained.
JavaScript
16
star
21

jslib-stats

💀 Node.js-based crawler that gathers JavaScript library usage stats by executing and inspecting JS. Unmaintained.
JavaScript
12
star
22

vim-yui3

💀 Vim syntax for YUI3. Unmaintained.
JavaScript
11
star
23

yuitweets

💀 A Bayesian tweet classifier that can learn the difference between tweets about the YUI Library and tweets about J-pop idols named Yui. Unmaintained.
Ruby
10
star
24

node-tokeninput

💀 YUI 3 Node plugin that turns a text input field into a tokenized input field similar to Cocoa's NSTokenField control. Unmaintained.
JavaScript
6
star
25

javascript-yui3.tmbundle

💀 TextMate bundle for YUI 3. Unmaintained.
JavaScript
6
star
26

denyssh

💀 Blocks SSH brute force attacks using PF. Unmaintained.
Ruby
5
star
27

tweetslurp

💀 Backs up tweets to a JSON file. Unmaintained.
JavaScript
4
star
28

jshint

💀 The Kinder, Gentler JavaScript Code Quality Tool
JavaScript
3
star
29

crackup

💀 Crappy remote backup. Unmaintained.
Ruby
3
star
30

sanitize-web

A super simple web interface to Sanitize, mostly for testing purposes.
HTML
3
star
31

sandbox

💀 YUI 3 module that simplifies the process of creating isolated iframe sandboxes in which to evaluate JavaScript code for tasks like profiling or unit testing. Unmaintained.
JavaScript
2
star
32

jetpants

💀
JavaScript
2
star
33

weld

💀 Combines and minifies CSS and JavaScript files at runtime and build time. Unmaintained.
Ruby
2
star
34

sniffle

💀 CLI app that learns and identifies user agent strings using a Redis-backed naive Bayes classifier. Just a silly experiment. Unmaintained.
JavaScript
2
star
35

denyspam

💀 Monitors a mail server log file and uses a firewall to temporarily block or redirect incoming packets from hosts that display spammer-like behavior. Unmaintained.
1
star
36

parse-xml-benchmark

Benchmarks for @rgrove/parse-xml
JavaScript
1
star