Rainbow

// your code is beautiful — show it off

Fork me on GitHub
×

Download

Select what languages you want to include to build a custom package.

Languages select all

Rainbow.js v1.1.8

CSS themes are included when you download the development version.
Otherwise they are available here.

  1. Download

    What is this?

    Rainbow is a code syntax highlighting library written in Javascript.

    It was designed to be lightweight (1.4kb), easy to use, and extendable.

    It is completely themable via CSS.

  2. What does it look like?

    /*
     * do some jQuery magic on load
     */
    $(document).ready(function() {
        function showHiddenParagraphs() {
            $("p.hidden").fadeIn(500);
        }
        setTimeout(showHiddenParagraphs, 1000);
    });
  3. How do I use it?

    First include some markup for code you want to be highlighted:

    <!-- you can use a code tag or a pre tag* -->
    <pre><code data-language="python">def openFile(path):
        file = open(path, "r")
        content = file.read()
        file.close()
        return content</code></pre>

    After this all you have to do is include a css theme file

    <!-- this should go in your <head> -->
    <link href="/assets/css/theme.css" rel="stylesheet" type="text/css">

    And include rainbow js + whatever languages you want

    <!-- you can create a custom build with specific languages
    this should go before the closing </body> -->
    <script src="/assets/js/rainbow.min.js"></script>
    <script src="/assets/js/language/generic.js"></script>
    <script src="/assets/js/language/python.js"></script>

    * Please note that the CSS themes for highlighting depend on having a <pre> block present. If you want to highlight inline code with language specific patterns then you will have to modify your CSS to support this.

  4. How does it work?

    Rainbow on its own is very simple. It goes through code blocks, processes regex patterns, and wraps matching patterns in <span> tags. All the theming is left up to CSS.

    A simple set of language patterns looks like this:

    Rainbow.extend('css', [
        {
            'name': 'comment',
            'pattern': /\/\*[\s\S]*?\*\//gm
        },
        {
            'name': 'constant.hex-color',
            'pattern': /#([a-f0-9]{3}|[a-f0-9]{6})(?=;|\s)/gi
        },
        {
            'matches': {
                1: 'constant.numeric',
                2: 'keyword.unit'
            },
            'pattern': /(\d+)(px|cm|s|%)?/g
        }
    ], true);
  5. Documentation

    Specifying a language

    In your markup the data-language attribute is used to specify what language to use for highlighting.

    <pre><code data-language="javascript">var testing = true;</code></pre>

    On sites such as Tumblr where <code> tags get stripped you can set the attribute to the <pre> tag.

    Rainbow API methods

    Rainbow has four public methods:

    Rainbow.color

    This method is called to highlight all the blocks on the page on load. If you would like to highlight stuff that is not in the DOM you can call it on its own. There are three ways to use it.

    One option is adding new code blocks to the DOM and then calling the method again:

    // alone
    Rainbow.color();
    
    // or with a call back
    Rainbow.color(function() {
        console.log('the new blocks are now highlighted!');
    });

    Another option is wrapping the code blocks in a div and highlighting before adding it to the DOM:

    var div = document.createElement('div');
    div.innerHTML = '<p>code:</p><pre><code data-language="javascript">var foo = true;</code></pre>';
    Rainbow.color(div, function() {
        document.getElementById('other_div').appendChild(div);
    });

    The third option is to pass a string directly:

    Rainbow.color('var foo = true;', 'javascript', function(highlighted_code) {
        console.log(highlighted_code);
    });
    Rainbow.addClass

    This method allows you to specify a global CSS class that will be applied to every span that gets created by Rainbow:

    Rainbow.addClass('from-rainbow');
    Rainbow.onHighlight

    This method notifies you as soon as a block of code has been highlighted.

    Rainbow.onHighlight(function(block, language) {
        console.log(block, 'for language', language, 'was highlighted');
    });

    The first parameter returns a reference to that code block in the DOM. The second parameter returns a string of the language being highlighted

    Rainbow.extend

    This method is used to define custom language patterns and to extend existing patterns.

    Rainbow.extend('language-name', [
        {
            'name': 'keyword',
            'pattern': /function|return|continue|break/g
        }
    ], true);

    Any pattern used with extend will take precedence over an existing pattern that matches the same block. It will also take precedence over any pattern that is included as part of the generic patterns.

    Passing true as the third parameter will make it so this language does not inherit any rules from the generic language patterns.

    If you would like to remove the default boolean values you could do something like this:

    Rainbow.extend([
        {
            'name': '',
            'pattern': /true|false/g
        }
    ]);

    When you don't pass in a language name as the first argument in Rainbow.extend() the patterns are treated as extending the default patterns.

    The "name" value determines what classes will be added to the span. For example if you name a pattern 'constant.hex-color' the code that matches will be wrapped in <span class="constant hex-color"></span>. This allows you to share common base style but add more customization in your themes for more specific matches.

    There are four different ways to match a pattern:

    Match by name
    Rainbow.extend([
        {
            'name': 'constant.boolean',
            'pattern': /true|false/g
        }
    ]);
    Match by group
    Rainbow.extend([
        {
            'matches': {
                1: 'constant.boolean.true',
                2: 'constant.boolean.false'
            },
            'pattern': /(true)|(false)/g
        }
    ]);
    Match by array of sub-patterns
    Rainbow.extend([
        {
            'matches': [
                {
                    'name': 'constant.boolean.true',
                    'pattern': /true/
                },
                {
                    'name': 'constant.boolean.false',
                    'pattern': /false/
                }
            ],
            'pattern': /true|false/g
        }
    ]);
    Match using another language

    The following allows php code to be embedded into an HTML block:

    Rainbow.extend('html', [
        {
            'name': 'source.php.embedded',
            'matches': {
                2: {
                    'language': 'php'
                }
            },
            'pattern': /<\?(php)?([\s\S]*?)(\?>)/gm
        }
    ], true);

    You should be able to nest sub-patterns as many levels deep as you would like.

    How Rainbow chooses a match

    In general the best practice is to make your patterns as specific as possible (for example targetting specific keywords).

    When you create a new language it gets pushed to the front of the generic patterns (unless you bypass them). This means your language rules will always be processed first.

    Rainbow chooses the first match it finds for a block. If another pattern overlaps with a pattern that has already been chosen then it is ignored

    There is one exception to this. If a match that comes later is more specific (the start AND end points stretch beyond another pattern already matched) then the new match will take precedence and the old one will be discarded.

    That means if you have a pattern that matches function test() and you add a pattern that matches public function test() the new one will be used instead.

    Known issues

    Javascript does not allow positive or negative lookbehind assertions so this means it is possible to have conflicts with the starting and end positions of matches. If you want to match a pattern that ends with a specific character it is recommended that you use a positive lookahead for that character instead of including it in the regex. This means that character can be included in the start of another pattern without overlapping.

    You cannot currently match using subgroups. You can include subgroups in your regex, and it will work, but you can't explicitly map them to certain classes without using sub-patterns.

  6. How can I contribute?

    If you would like to contribute or submit a bug check out the project on GitHub.