MCPcopy
hub / github.com/wooorm/starry-night

github.com/wooorm/starry-night @3.10.0 sqlite

repository ↗ · DeepWiki ↗ · release 3.10.0 ↗
43 symbols 115 edges 754 files 30 documented · 70%
README

Close up of The Starry Night by Vincent van Gogh (1889)

with examples of starry-night over it

starry-night

[![Build][badge-build-image]][badge-build-url] [![Coverage][badge-coverage-image]][badge-coverage-url] [![Downloads][badge-downloads-image]][badge-downloads-url] [![Size][badge-size-image]][badge-size-url]

Syntax highlighting, like what GitHub uses to highlight code, but free and open source and JavaScript!

Contents

What is this?

This package is an open source version of GitHub’s closed-source PrettyLights project (more on that later). It supports 600+ grammars and its extremely high quality. It uses TextMate grammars which are also used in popular editors (SublimeText, Atom, VS Code, \&c). They’re heavy but high quality.

When should I use this?

starry-night is a high quality highlighter (when your readers or authors are programmers, you want this!) that can support tons of grammars (from new things like MDX to much more!) which approaches how GitHub renders code.

It has a WASM dependency, and rather big grammars, which means that starry-night might be too heavy particularly in browsers, in which case [lowlight][github-lowlight] or [refractor][github-refractor] might be more suitable.

This project is similar to the excellent [shiki][github-shiki], and it uses the same underlying dependencies, but starry-night is meant to match GitHub in that it produces classes and works with the CSS it ships, making it easier to add dark mode and other themes with CSS compared to inline styles. GitHub did some good work on accessibility around color blindness and contrast, that’s available here too.

Finally, this package produces objects (an AST), which makes it useful when you want to perform syntax highlighting in a place where serialized HTML wouldn’t work, wouldn’t work well, or isn’t solely what you want. For example, when you want to show code in a CLI by rendering to ANSI sequences, when you’re using virtual DOM frameworks (such as React or Preact) so that diffing can be performant, or when you’re working with [hast][github-hast] or [rehype][github-rehype].

Bundled, minified, and gzipped, starry-night and the WASM binary are 185 kB. There are two lists of grammars you can use: [common][api-common] (±35 languages, good for your own site) adds 250 kB and [all][api-all] (\~600 languages, useful if you are making a site like GitHub) is 1.6 MB. You can also manually choose which grammars to include (or add to common): a language is typically between 3 and 5 kB. To illustrate, Astro costs 2.1 kB and TSX costs 25.4 kB.

What is PrettyLights?

PrettyLights is the syntax highlighter that GitHub uses to turn this:

```markdown
# Hello, world!
```

…into this:

<span class="pl-mh"><span class="pl-mh">#</span><span class="pl-mh"> </span>Hello, world!</span>

…which is what starry-night does too (some small differences in markup, but essentially the same)!

PrettyLights is responsible for taking the flag markdown, looking it up in [languages.yml from github-linguist][github-linguist-languages-yml] to figure out that that means markdown, taking a corresponding grammar (in this case [wooorm/markdown-tm-language][github-markdown-tm-language]), doing some GPL magic in C, and turning it into spans with classes.

GitHub is using PrettyLights since December 2014, when it [replaced Pygments][github-pages-pygments]. They wanted to open source it, but [were unable][github-pages-license] due to licensing issues. Recently ([Feb 2019][github-tree-sitter-tree-lights]?), GitHub has slowly started to move towards TreeLights, which is based on TreeSitter, and also closed source. If TreeLights includes a language (currently: C, C#, CSS, CodeQL, EJS, Elixir, ERB, Gleam, Go, HTML, Java, JS, Nix, PHP, Python, RegEx, Ruby, Rust, TLA, TS), that’ll be used, for everything else PrettyLights is used.

starry-night does what PrettyLights does, not what TreeLights does. I’m hopeful that that will be open sourced in the future and we can mimic both.

[][artsandculture-google-starry-night]

Install

This package is [ESM only][github-gist-esm]. In Node.js (version 16+), install with [npm][npmjs-install]:

npm install @wooorm/starry-night

In Deno with [esm.sh][esmsh]:

import {common, createStarryNight} from 'https://esm.sh/@wooorm/starry-night@3'

In browsers with [esm.sh][esmsh]:

<script type="module">
  import {common, createStarryNight} from 'https://esm.sh/@wooorm/starry-night@3?bundle'
</script>

To get the CSS in browsers, do (see [CSS][section-css] for more info):


<link rel="stylesheet" href="https://esm.sh/@wooorm/starry-night@3/style/both">

Use

import {common, createStarryNight} from '@wooorm/starry-night'

const starryNight = await createStarryNight(common)

const scope = starryNight.flagToScope('markdown')
const tree = starryNight.highlight('# hi', scope)

console.log(tree)

Yields:

{
  type: 'root',
  children: [
    {
      type: 'element',
      tagName: 'span',
      properties: {className: ['pl-mh']},
      children: [
        {type: 'text', value: '# '},
        {
          type: 'element',
          tagName: 'span',
          properties: {className: ['pl-en']},
          children: [{type: 'text', value: 'hi'}]
        }
      ]
    }
  ]
}

API

This package exports the identifiers [all][api-all], [common][api-common], and [createStarryNight][api-create-starry-night] from the main module. It exports the additional [TypeScript][] types [GetOnigurumaUrl][api-get-oniguruma-url], [Grammar][api-grammar], and [Options][api-options]. There is no default export.

It also includes grammars directly in its export map, which each expose a [Grammar][api-grammar] as the default export. Do not use the lang/ folder or the .js extension.

For CSS files, do use style/ and don’t use .css:

import sourceMdx from '@wooorm/starry-night/source.mdx' // Grammar.
import styleTritanopiaDark from '@wooorm/starry-night/style/tritanopia-dark' // CSS.

all

List of all grammars ([Array<Grammar>][api-grammar])

common

List of ±35 common grammars ([Array<Grammar>][api-grammar])

createStarryNight(grammars[, options])

Create a StarryNight that can highlight things with the given grammars. This is async to allow async loading and registering, which is currently only used for WASM.

Parameters
  • grammars ([Array<Grammar>][api-grammar]) — grammars to support
  • options ([Options][api-options], optional) — configuration
Returns

Promise that resolves to an instance which highlights with the bound grammars (Promise<StarryNight>).

starryNight.flagToScope(flag)

Get the grammar scope (such as text.md) associated with a grammar name (such as markdown) or grammar extension (such as .mdwn).

This function uses the first word (when splitting on spaces and tabs) that is used after the opening of a fenced code block:

```js
console.log(1)
```

To match GitHub, this also accepts entire paths:

```path/to/example.js
console.log(1)
```

👉 Note: languages can use the same extensions. For example, .h is reused by many languages. In those cases, you will get one scope back, but it might not be the most popular language associated with an extension.

Parameters
  • flag (string) — grammar name (such as 'markdown'), grammar extension (such as '.mdwn'), or entire file path ending in extension
Returns

Grammar scope, such as 'text.md' (string or undefined).

Example
import {common, createStarryNight} from '@wooorm/starry-night'

const starryNight = await createStarryNight(common)

console.log(starryNight.flagToScope('pandoc')) // `'text.md'`
console.log(starryNight.flagToScope('workbook')) // `'text.md'`
console.log(starryNight.flagToScope('.workbook')) // `'text.md'`
console.log(starryNight.flagToScope('path/to/example.js')) // `'source.js'`
console.log(starryNight.flagToScope('whatever')) // `undefined`

starryNight.highlight(value, scope)

Highlight programming code.

Parameters
  • value (string) — code to highlight
  • scope (string) — registered grammar scope to highlight as (such as 'text.md')
Returns

Node representing highlighted code ([Root][github-hast-root]).

Example
import sourceCss from '@wooorm/starry-night/source.css'
import {createStarryNight} from '@wooorm/starry-night'

const starryNight = await createStarryNight([sourceCss])

console.log(starryNight.highlight('em { color: red }', 'source.css'))

Yields:

{
  type: 'root',
  children: [
    {type: 'element', tagName: 'span', properties: [Object], children: [Array]},
    {type: 'text', value: ' { '},
    {type: 'element', tagName: 'span', properties: [Object], children: [Array]},
    {type: 'text', value: ': '},
    {type: 'element', tagName: 'span', properties: [Object], children: [Array]},
    {type: 'text', value: ' }'}
  ]
}

starryNight.missingScopes()

List scopes that are needed by the registered grammars but that are missing.

To illustrate, the text.xml.svg grammar needs the text.xml grammar. When you register text.xml.svg without text.xml, it will be listed here.

Returns

List of grammar scopes, such as 'text.md' (Array<string>).

Example
import textXmlSvg from '@wooorm/starry-night/text.xml.svg'
import textXml from '@wooorm/starry-night/text.xml'
import {createStarryNight} from '@wooorm/starry-night'

const svg = await createStarryNight([textXmlSvg])
console.log(svg.missingScopes()) //=> ['text.xml']

const svgAndXml = await createStarryNight([textXmlSvg, textXml])
console.log(svgAndXml.missingScopes()) //=> []

starryNight.register(grammars)

Add more grammars.

Parameters
  • grammars ([Array<Grammar>][api-grammar]) — grammars to support
Returns

Promise resolving to nothing (Promise<undefined>).

Example
import sourceCss from '@wooorm/starry-night/source.css'
import textMd from '@wooorm/starry-night/text.md'
import {createStarryNight} from '@wooorm/starry-night'
import {toHtml} from 'hast-util-to-html'

const markdown = '```css\nem { color: red }\n```'

const starryNight = await createStarryNight([textMd])

console.log(toHtml(starryNight.highlight(markdown, 'text.md')))

await starryNight.register([sourceCss])

console.log(toHtml(starryNight.highlight(markdown, 'text.md')))

Yields:

<span class="pl-s">```</span><span class="pl-en">css</span>
<span class="pl-c1">em { color: red }</span>
<span class="pl-s">```</span>
<span class="pl-s">```</span><span class="pl-en">css</span>
<span class="pl-ent">em</span> { <span class="pl-c1">color</span>: <span class="pl-c1">red</span> }
<span class="pl-s">```</span>

starryNight.scopes()

List all registered scopes.

Returns

List of grammar scopes, such as 'text.md' (Array<string>).

Example
import {common, createStarryNight} from '@wooorm/starry-night'

const starryNight = await createStarryNight(common)

console.log(starryNight.scopes())

Yields:

[
  'source.c',
  'source.c++',
  // …
  'text.xml',
  'text.xml.svg'
]

GetOnigurumaUrl

Function to get a URL to the oniguruma WASM (TypeScript type).

👉 Note: this must currently result in a version 2 URL of onig.wasm from [vscode-oniguruma][github-vscode-oniguruma].

⚠️ Danger: when you use this functionality, your project might break at any time (when reinstalling dependencies), except when you make sure that the WASM binary you load manually is what our internally used vscode-oniguruma dependency expects. To solve this, you could for example use an npm script called [dependencies][npmjs-using-npm-script-dependencies] (which runs everytime node_modules is changed) which copies vscode-oniguruma/release/onig.wasm to

Extension points exported contracts — how you extend this code

Grammar (Interface)
(no doc)
lib/types.d.ts
Options (Interface)
(no doc)
lib/types.d.ts
RuleDefinition (Interface)
(no doc)
lib/types.d.ts
RuleInclude (Interface)
(no doc)
lib/types.d.ts
RuleName (Interface)
(no doc)
lib/types.d.ts

Core symbols most depended-on inside this repo

createStarryNight
called by 18
lib/index.js
cleanMapOfRules
called by 6
script/build.js
map
called by 6
script/build.js
visit
called by 3
script/build.js
normalizeLinguistName
called by 3
script/build.js
generate
called by 3
script/preview.js
delveIfClassName
called by 3
lib/parse.js
readOrFetch
called by 2
script/list.js

Shape

Function 38
Interface 5

Languages

TypeScript100%

Modules by API surface

script/build.js14 symbols
lib/index.js9 symbols
lib/types.d.ts5 symbols
lib/parse.js5 symbols
script/css.js3 symbols
script/list.js2 symbols
test.js1 symbols
script/support.js1 symbols
script/preview.js1 symbols
lib/get-oniguruma.fs.js1 symbols
lib/get-oniguruma.default.js1 symbols

Dependencies from manifests, versioned

@types/css0.0.38 · 1×
@types/hast3.0.0 · 1×
@types/json-stable-stringify1.0.0 · 1×
@types/mdast4.0.0 · 1×
@types/node25.0.0 · 1×
c811.0.0 · 1×
css3.0.0 · 1×
generate-github-markdown-css6.0.0 · 1×
globals17.0.0 · 1×
hast-util-to-html9.0.0 · 1×
import-meta-resolve4.0.0 · 1×
json-stable-stringify1.0.0 · 1×

For agents

$ claude mcp add starry-night \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact