{"id":13508485,"url":"https://github.com/ccampbell/rainbow","last_synced_at":"2025-05-14T08:08:09.213Z","repository":{"id":2827045,"uuid":"3829352","full_name":"ccampbell/rainbow","owner":"ccampbell","description":"Simple syntax highlighting library written in javascript","archived":false,"fork":false,"pushed_at":"2023-09-24T21:33:32.000Z","size":1139,"stargazers_count":3306,"open_issues_count":70,"forks_count":464,"subscribers_count":46,"default_branch":"master","last_synced_at":"2025-04-11T02:51:42.765Z","etag":null,"topics":["javascript","syntax-highlighting"],"latest_commit_sha":null,"homepage":"http://rainbowco.de","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ccampbell.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2012-03-26T03:19:21.000Z","updated_at":"2025-03-26T14:16:32.000Z","dependencies_parsed_at":"2022-08-06T12:31:35.071Z","dependency_job_id":"a8273d57-4a43-4546-a2c7-06a5985932f4","html_url":"https://github.com/ccampbell/rainbow","commit_stats":{"total_commits":670,"total_committers":33,"mean_commits":"20.303030303030305","dds":"0.19253731343283587","last_synced_commit":"05892a8ebe7689ab3b9ab96cfc77414d8467e749"},"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ccampbell%2Frainbow","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ccampbell%2Frainbow/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ccampbell%2Frainbow/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ccampbell%2Frainbow/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ccampbell","download_url":"https://codeload.github.com/ccampbell/rainbow/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254101558,"owners_count":22014908,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["javascript","syntax-highlighting"],"created_at":"2024-08-01T02:00:53.767Z","updated_at":"2025-05-14T08:08:09.186Z","avatar_url":"https://github.com/ccampbell.png","language":"JavaScript","readme":"# Rainbow\n\nRainbow is a code syntax highlighting library written in Javascript.\n\nIt was designed to be lightweight (~2.5kb), easy to use, and extendable.\n\nIt is completely themable via CSS.\n\n## Demo\n\nYou can see rainbow in action at [http://rainbowco.de](http://rainbowco.de).\n\nYou can also build/download custom packages from there.\n\n## Contents\n\n* [Quick Start](#quick-start)\n    * [Browser](#browser)\n    * [Node.js](#nodejs)\n      * [Install rainbow](#install-rainbow)\n      * [Highlight some code](#highlight-some-code)\n  * [Supported Browsers](#supported-browsers)\n  * [Supported Languages](#supported-languages)\n  * [Specifying a language](#specifying-a-language)\n  * [Themes](#themes)\n    * [Rendering code blocks](#rendering-code-blocks)\n    * [Adding custom rules for specific languages](#adding-custom-rules-for-specific-languages)\n  * [JavaScript API Documentation](#javascript-api-documentation)\n    * [Rainbow.color](#rainbowcolor)\n      * [Preventing automatic highlighting on page load](#preventing-automatic-highlighting-on-page-load)\n      * [Extra options for color](#extra-options-for-color)\n        * [globalClass](#globalclass)\n    * [Rainbow.extend](#rainbowextend)\n      * [Extending existing languages](#extending-existing-languages)\n      * [How code is highlighted](#how-code-is-highlighted)\n        * [Match by name](#match-by-name)\n        * [Match by group](#match-by-group)\n        * [Match by array of sub-patterns](#match-by-array-of-sub-patterns)\n        * [Match using another language](#match-using-another-language)\n      * [Extending an existing language](#extending-an-existing-language)\n      * [How Rainbow chooses a match](#how-rainbow-chooses-a-match)\n      * [Known limitations](#known-limitations)\n        * [Regular expressions lookbehind assertions](#regular-expressions-lookbehind-assertions)\n        * [Regular expression subgroup matches](#regular-expression-subgroup-matches)\n    * [Rainbow.addAlias](#rainbowaddalias)\n    * [Rainbow.onHighlight](#rainbowonhighlight)\n    * [Rainbow.remove](#rainbowremove)\n  * [Building](#building)\n    * [Getting a local environment set up](#getting-a-local-environment-set-up)\n    * [Build commands](#build-commands)\n      * [gulp build](#gulp-build)\n      * [gulp lint](#gulp-lint)\n      * [gulp pack](#gulp-pack)\n      * [gulp sass](#gulp-sass)\n      * [gulp test](#gulp-test)\n      * [gulp watch](#gulp-watch)\n  * [More Info](#more-info)\n\n## Quick Start\n\n### Browser\n\n1. Include some markup for code you want to be highlighted:\n\n    ```html\n    \u003cpre\u003e\u003ccode data-language=\"python\"\u003edef openFile(path):\n        file = open(path, \"r\")\n        content = file.read()\n        file.close()\n        return content\u003c/code\u003e\u003c/pre\u003e\n    ```\n\n2. Include a CSS theme file in the ``\u003chead\u003e``:\n\n    ```html\n    \u003clink href=\"/assets/css/theme.css\" rel=\"stylesheet\" type=\"text/css\"\u003e\n    ```\n\n3. Include rainbow.js and whatever languages you want before the closing ``\u003c/body\u003e``:\n\n    ```html\n    \u003cscript src=\"/assets/js/rainbow.js\"\u003e\u003c/script\u003e\n    \u003cscript src=\"/assets/js/language/generic.js\"\u003e\u003c/script\u003e\n    \u003cscript src=\"/assets/js/language/python.js\"\u003e\u003c/script\u003e\n    ```\n\nBy default `dist/rainbow.min.js` comes with some popular languages bundled together with it.\n\n### Node.js\n\nRainbow 2.0 introduced support for node.js. All of the existing API methods should work, but there is also a new `Rainbow.colorSync` method for synchronous highlighting.\n\n#### Install rainbow\n\n```\nnpm install --save rainbow-code\n```\n\n#### Highlight some code\n\n```javascript\nvar rainbow = require('rainbow-code');\nvar highlighted = rainbow.colorSync('// So meta\\nrainbow.colorSync(\\'var helloWorld = true;\\');', 'javascript');\nconsole.log(highlighted);\n```\n\n## Supported Browsers\n\nRainbow 2.0 should work in the following browsers:\n\n| Chrome | Firefox | IE | Safari |\n| ------ | ------- | --- | ------ |\n| 20+ | 13+ | 10+ | 6+ |\n\nFor older browsers you can download the legacy [1.2.0](https://github.com/ccampbell/rainbow/archive/1.2.0.zip) release.\n\n## Supported Languages\n\nCurrently supported languages are:\n- C\n- C#\n- Coffeescript\n- CSS\n- D\n- Go\n- Haskell\n- HTML\n- Java\n- JavaScript\n- JSON\n- Lua\n- PHP\n- Python\n- R\n- Ruby\n- Scheme\n- Shell\n- Smalltalk\n\n## Specifying a language\n\nIn your markup the `data-language` attribute is used to specify what language to use for highlighting. For example:\n\n```html\n\u003cpre\u003e\u003ccode data-language=\"javascript\"\u003evar testing = true;\u003c/code\u003e\u003c/pre\u003e\n```\n\nRainbow also supports the HTML5 style for specifying languages:\n\n```html\n\u003cpre\u003e\u003ccode class=\"language-javascript\"\u003evar testing = true;\u003c/code\u003e\u003c/pre\u003e\n```\n\nAnd the Google prettify style:\n\n```html\n\u003cpre class=\"lang-javascript\"\u003e\u003ccode\u003evar testing = true;\u003c/code\u003e\u003c/pre\u003e\n```\n\n## Themes\n\nThemes are located in the `themes/sass` directory. They are written using sass so that common logic can be shared among all themes without having to duplicate it in each theme file. You should not edit the css files directly.\n\n`_base.sass` includes some default styles shared by almost every theme. `_init.sass` contains mixins and initialization logic that is shared by every theme.\n\n### Rendering code blocks\n\nAs of version 2.0 the themes use a clever trick to display the highlighted code. All code blocks default to `opacity: 0`, but an animation is triggered on page load to happen after a 2 second delay.\n\nThis means for users who do not have JavaScript enabled the code will fade in after 2 seconds. If JavaScript is enabled, the animation is stopped on load and the delay is reset to `0s`. That ensures that as soon as the code is done being highlighted it will be able to show up instantly. This is used to prevent a flash of unstyled text on page load and ensure that the code blocks only show up after they have been highlighted.\n\nThere is also a preload animation that will show up for any code block that takes longer than 300ms to load.\n\n### Adding custom rules for specific languages\n\nA SASS mixin was added to simplify defining styles that should only apply for a specific language. Using it looks like this:\n\n```sass\n@include language(\"html\")\n    .support.operator\n        color: #fff\n\n@include language((\"javascript\", \"js\"))\n    .variable.super\n        color: #66D9EF\n```\n\nYou can pass a single language or a list of languages.\n\n## JavaScript API Documentation\n\nRainbow has four public methods:\n\n- [Rainbow.color](#rainbowcolor)\n- [Rainbow.extend](#rainbowextend)\n- [Rainbow.addAlias](#rainbowaddalias)\n- [Rainbow.onHighlight](#rainbowonhighlight)\n- [Rainbow.remove](#rainbowremove)\n\n### Rainbow.color\n\nRainbow.color is used to highlight blocks of code.\n\nFor convenience, this method is called automatically to highlight all code blocks on the page when `DOMContentLoaded` fires.  If you would like to highlight stuff that is not in the DOM you can use it on its own.  There are three ways to use it.\n\n1. The first option is calling the color method on its own:\n\n    ```javascript\n    Rainbow.color();\n    ```\n\n    Each time this is called, Rainbow will look for matching `pre` blocks on the page that have not yet been highlighted and highlight them.\n\n    You can optionally pass a callback function that will fire when all the blocks have been highlighted.\n\n    ```javascript\n    Rainbow.color(function() {\n        console.log('The new blocks are now highlighted!');\n    });\n    ```\n\n2. The second option is passing a specific element to the color method.\n\n    In this example we are creating a code block, highlighting it, then inserting it into the DOM:\n\n    ```javascript\n    var div = document.createElement('div');\n    div.innerHTML = '\u003cpre\u003e\u003ccode data-language=\"javascript\"\u003evar foo = true;\u003c/code\u003e\u003c/pre\u003e';\n    Rainbow.color(div, function() {\n        document.getElementById('something-else').appendChild(div;)\n    });\n    ```\n\n3. The final option is passing in your code as a string to `Rainbow.color`.\n\n    ```javascript\n    Rainbow.color('var foo = true;', 'javascript', function(highlightedCode) {\n        console.log(highlightedCode);\n    });\n    ```\n\n#### Preventing automatic highlighting on page load\n\nIf you want to prevent code on the page from being highlighted when the page loads you can set the `defer` property to `true`.\n\n```javascript\nRainbow.defer = true;\n```\n\nNote that you have to set this before `DOMContentLoaded` fires or else it will not do anything.\n\n#### Extra options for color\n\nAs of right now there is one extra option for color.\n\n##### globalClass\n\nThis option allows you to have an extra class added to every span that Rainbow renders. This can be useful if you want to remove the classes in order to trigger a special effect of some sort.\n\nTo apply a global class you can add it in your markup:\n\n```html\n\u003cpre\u003e\u003ccode data-language=\"javascript\" data-global-class=\"animate\"\u003evar hello = true;\u003c/code\u003e\u003c/pre\u003e\n```\n\nOr you can pass it into a `Rainbow.color` call like this:\n\n```javascript\nRainbow.color('var hello = true;', {\n    language: 'javascript',\n    globalClass: 'animate'\n});\n```\n\n### Rainbow.extend\n\nRainbow.extend is used to define language grammars which are used to highlight the code you pass in. It can be used to define new languages or to extend existing languages.\n\nA very simple language grammer looks something like this:\n\n```javascript\nRainbow.extend('example', [\n    {\n        name: 'keyword',\n        pattern: /function|return|continue|break/g\n    }\n]);\n```\n\nAny 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.\n\nFor example if you were to call\n\n```javascript\nRainbow.extend('example', [\n    {\n        name: 'keyword.magic',\n        pattern: /function/g\n    }\n]);\n```\n\nThis would mean that function will be highlighted as `\u003cspan class=\"keyword magic\"\u003efunction\u003c/span\u003e`, but `return`, `continue`, and `break` will still be highlighted as just `\u003cspan class=\"keyword\"\u003ereturn\u003c/span\u003e`, etc.\n\n#### Extending existing languages\n\nBy default languages are considered to be standalone, but if you specify an optional third parameter you can have your language inherit from another one.\n\nFor example the python language grammars inherit from the generic ones:\n\n```javascript\nRainbow.extend('python', [\n    {\n        name: 'constant.language',\n        pattern: /True|False|None/g\n    }\n], 'generic');\n```\n\nIf you wanted to remove the default boolean values you should be able to do something like this:\n\n```javascript\nRainbow.extend('python', [\n    {\n        name: '',\n        pattern: /true|false/g\n    }\n]);\n```\n\n#### How code is highlighted\n\nThe `name` value determines what classes will be added to a span that matches the pattern you specify. For example, if you name a pattern `constant.hex-color` the code that matches that pattern will be wrapped in `\u003cspan class=\"constant hex-color\u003e\u003c/span\u003e`. This allows you to share common base styles but add more customization in your themes for more specific matches.\n\n#### How grammars are defined\n\n##### Match by name\n\nThe simplest way to define a grammar is to define a regular expression and a name to go along with that.\n\n```javascript\nRainbow.extend([\n    {\n        name: 'constant.boolean',\n        pattern: /true|false/g\n    }\n]);\n```\n\n##### Match by group\n\nThis allows you to take a more complicated regular expression and map certain parts of it to specific scopes.\n\n```javascript\nRainbow.extend([\n    {\n        matches: {\n            1: 'constant.boolean.true',\n            2: 'constant.boolean.false'\n        },\n        pattern: /(true)|(false)/g\n    }\n]);\n```\n\n##### Match by array of sub-patterns\n\nFor more complicated matches you may want to process code within another match group.\n\n```javascript\nRainbow.extend([\n    {\n        matches: [\n            {\n                name: 'constant.boolean.true',\n                pattern: /true/\n            },\n            {\n                name: 'constant.boolean.false',\n                pattern: /false/\n            }\n        ],\n        pattern: /true|false/g\n    }\n]);\n```\n\n##### Match using another language\n\nSometimes a language supports other languages being embedded inside of it such as JavaScript inside HTML. Rainbow supports that out of the box. Here is an example of how you would highlight PHP tags inside of HTML code.\n\n```javascript\nRainbow.extend('html', [\n    {\n        name: 'source.php.embedded',\n        matches: {\n            2: {\n                language: 'php'\n            }\n        },\n        pattern: /\u0026lt;\\?(php)?([\\s\\S]*?)(\\?\u0026gt;)/gm\n    }\n]);\n```\n\nYou should be able to nest sub-patterns as many levels deep as you would like.\n\n#### Extending an existing language\n\nIf you have a language specific pattern that you want highlighted, but it does not exist in the language syntax rules, you can add a rule in your own javascript.\n\nLet's say for example you want to highlight PHP's apc functions.\nYou can include the php language then in the markup on your page add:\n\n```html\n\u003cscript\u003e\n    Rainbow.extend('php', [\n        {\n            'matches': {\n                1: 'support.function'\n            },\n            'pattern': /\\b(apc_(store|fetch|add|inc))(?=\\()/g\n        }\n    ]);\n\u003c/script\u003e\n```\n\n#### How Rainbow chooses a match\n\nIn general the best practice is to make your patterns as specific as possible (for example targetting specific keywords).\n\nWhen you create a new language it gets pushed to the front of whatever language it is inheriting from.  This means whatever rules are added last will be checked against first.\n\nRainbow 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.\n\nThere 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.\n\nThat 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.\n\n#### Known limitations\n\n##### Regular expressions lookbehind assertions\n\nJavascript 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. That allows the same character to be used at the start of another match group without overlapping.\n\n##### Regular expression subgroup matches\n\nYou cannot match part of a subgroup directly to a scope. For example if you have:\n\n```javascript\n{\n    matches: {\n        1: 'name.attribute',\n        2: 'value'\n    },\n    pattern: /(name=\\\"(.*?)\\\")/g\n}\n```\n\nThis will result in code `name=\"value\"` being highlighted as:\n\n```html\n\u003cspan class=\"name attribute\"\u003ename=\"value\"\u003c/span\u003e\n```\n\nYou see the value class never gets applied.\n\nTo achieve what you really want you would have to use a subpattern like this:\n\n```javascript\n{\n    name: 'name.attribute',\n    matches: [{\n        matches: {\n            1: 'value'\n        },\n        pattern: /\\\"(.*?)\\\"/g\n    }],\n    pattern: /(name=\\\"(.*?)\\\")/g\n}\n```\n\nThis means the entire block is wrapped with `name.attribute` scope and then within that any part in double quotes will be wrapped as `value`.\n\nThat means the entire block will behighlighted as\n\n```html\n\u003cspan class=\"name attribute\"\u003ename=\"\u003cspan class=\"value\"\u003evalue\u003c/span\u003e\"\u003c/span\u003e\n```\n\nIn this example you could avoid subpatterns completely by using a regex like this to begin with:\n\n```javascript\n/(name=)\\\"(.*?)\\\"/g\n```\n\n### Rainbow.addAlias\n\nThe addAlias function allows you to map a different name to a language. For example:\n\n```javascript\nRainbow.addAlias('js', 'javascript');\n```\n\nThis allows you to highlight javascript code by using the language `js` instead of `javascript`.\n\n### Rainbow.onHighlight\n\nThis method notifies you as soon as a block of code has been highlighted.\n\n```javascript\nRainbow.onHighlight(function(block, language) {\n    console.log(block, 'for language', language, 'was highlighted');\n});\n```\n\nThe first parameter returns a reference to that code block in the DOM. The second parameter returns a string of the language being highlighted.\n\n### Rainbow.remove\n\nThis method allows you to remove syntax rules for a specific language. It is only really useful for development if you want to be able to reload language grammars on the fly without having to refresh the page.\n\n```javascript\n// Remove all the javascript patterns\nRainbow.remove('javascript');\n```\n\n## Building\n\nRainbow is compiled using [rollup](https://github.com/rollup/rollup) and [buble](https://gitlab.com/Rich-Harris/buble).\n\n[Gulp](https://github.com/gulpjs/gulp) is used for all build related tasks.\n\n### Getting a local environment set up\n\n```shell\ngit clone git@github.com:ccampbell/rainbow.git\ncd rainbow\nnpm install\n```\n\n### Build commands\n\n#### gulp build\n\nThe build command is used to build a custom version of rainbow.js. If you run\n\n```shell\ngulp build\n```\n\nA file will be created at `dist/rainbow-custom.min.js` containing rainbow.js as well as popular languages. If you want to specify specific languages you can use:\n\n```shell\ngulp build --languages=html,css,php,javascript\n```\n\nIf you want a minimized version of rainbow without any languages you can pass\n\n```shell\ngulp build --languages=none\n```\n\nIf you want a minimized version with all languages you can pass\n\n```shell\ngulp build --languages=all\n```\n\n#### gulp lint\n\nThe lint command will check all the javascript files for things that do not match the styleguide from the `.eslintrc` file.\n\n#### gulp pack\n\nThe pack command will run a buble + rollup build and save the resulting file to `dist/rainbow.js`\n\n#### gulp sass\n\nThe sass command will compile all the rainbow themes\n\n#### gulp test\n\nThe test command will run the unit tests. You can pass the `--watch` flag to keep the tests running and have them rerun when you make changes. That is a little buggy though which has something to do with karma + rollup.\n\nYou can also use the `--browsers` flag to specify a browser to run the tests in. Currently only `PhantomJS` and `Chrome` are supported.\n\n#### gulp watch\n\nThe watch command will look at sass files and src js files and build the css or js (using `gulp sass` and `gulp pack`) every time you make a change.\n\n## More Info\n\nIf you are looking for line number support you can try one of the following:\n- https://github.com/Blender3D/rainbow.linenumbers.js\n- https://github.com/Sjeiti/rainbow.linenumbers\n\nYou can check out demos and build custom packages at [rainbowco.de](http://rainbowco.de).\n","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fccampbell%2Frainbow","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fccampbell%2Frainbow","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fccampbell%2Frainbow/lists"}