npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

sommark-highlight

v1.1.1

Published

Syntax highlighting for SomMark — web and terminal, static and dynamic.

Readme

sommark-highlight

Syntax highlighting for SomMark. Works in the browser and in Node.js terminals. Supports static HTML output and a live editor powered by CodeMirror 6.


Install

npm install sommark-highlight

CDN (no bundler)

Two pre-built IIFE bundles are shipped in dist/. Load whichever fits your use case — both expose a global SomMarkHighlight object.

Static highlighting only (9 KB gzipped)

<script src="https://cdn.jsdelivr.net/npm/sommark-highlight/dist/sommark-highlight.js"></script>
<script>
  const { staticHighlight } = SomMarkHighlight;

  document.getElementById("output").innerHTML = staticHighlight(`
    [div = class: "hero"]
      [h1]Hello World[end]
    [end]
  `);
</script>

Full bundle — static + live editor (200 KB gzipped)

Includes staticHighlight, defaultTokens, and attachHighlighter. CodeMirror is bundled in — no extra scripts needed.

<script src="https://cdn.jsdelivr.net/npm/sommark-highlight/dist/sommark-highlight.full.js"></script>
<script>
  const { staticHighlight, attachHighlighter } = SomMarkHighlight;

  const editor = attachHighlighter(document.getElementById("editor"), {
    tokens: {
      IDENTIFIER: "#60a5fa",
      KEY:        "#34d399",
      END_KEYWORD: { color: "#6366f1", bold: true },
    },
    other: "#8b8fa8",
    onError: (msg) => {
      document.getElementById("errors").textContent = msg ?? "";
    },
  });

  editor.setValue(`[h1]Hello World[end]`);
</script>

Two modes

| Mode | What it does | Import | |------|-------------|--------| | Static | Turns SomMark source into highlighted HTML | sommark-highlight | | Dynamic | Mounts a live editor with real-time highlighting | sommark-highlight/dynamic |


Static highlighting

Takes a SomMark string and returns an HTML string with inline styles. Drop it into any <pre> tag.

import { staticHighlight } from "sommark-highlight";

const html = staticHighlight(`
  [div = class: "container"]
    [h1]Hello World[end]
  [end]
`);

document.getElementById("output").innerHTML = html;

With custom colors

Pass a tokens object to override colors for specific token types:

const html = staticHighlight(src, {
  tokens: {
    IDENTIFIER: "#f472b6",
    KEY:        "#34d399",
    END_KEYWORD: { color: "#6366f1", bold: true },
    COMMENT:     { color: "#4b4f68", italic: true },
  }
});

Each token entry can be:

| Format | Example | Effect | |--------|---------|--------| | A color string | "#f472b6" | Sets the text color | | { color, bold?, italic? } | { color: "#f00", bold: true } | Color with font style | | { render } | { render: (value) => \<span ...>${value}`} | Full control over the output HTML | |{ context }|{ context: ({ prev, current, next }) => ... }| Color based on surrounding tokens | |null|null` | No highlight — renders plain text |

Fallback color for all other tokens

Use other to set a color for any token that has no specific config:

const html = staticHighlight(src, {
  tokens: {
    IDENTIFIER: "#60a5fa",
  },
  other: "#8b8fa8"  // everything else gets this color
});

Full control with onToken

onToken runs before everything else. Return a string to override, or undefined to fall through to the normal priority chain:

const html = staticHighlight(src, {
  onToken: ({ prev, current, next }) => {
    if (current.type === "IDENTIFIER") {
      return `<span style="color:#60a5fa">${current.value}</span>`;
    }
    // return undefined to use normal highlighting for other tokens
  }
});

Priority order

When deciding how to render a token, staticHighlight follows this order:

  1. onToken — if it returns a value, that is used
  2. tokens[type] — the per-type config you provided
  3. other — the fallback config
  4. Built-in defaults
  5. Plain text — no highlight

Dynamic editor

Mounts a live CodeMirror 6 editor that highlights SomMark as you type. Requires @codemirror/view, @codemirror/state, and @codemirror/commands to be installed.

npm install @codemirror/view @codemirror/state @codemirror/commands
import { attachHighlighter } from "sommark-highlight/dynamic";

const editor = attachHighlighter(document.getElementById("editor"), {
  tokens: {
    IDENTIFIER: "#60a5fa",
    KEY:        "#34d399",
    END_KEYWORD: { color: "#6366f1", bold: true },
  },
  other: "#8b8fa8",
});

// Set initial content
editor.setValue(`[h1]Hello[end]`);

// Read current content
const code = editor.getValue();

// Listen for changes
editor.onUpdate((code) => {
  console.log("changed:", code);
});

// Clean up when done
editor.destroy();

Editor options

| Option | Type | Default | Description | |--------|------|---------|-------------| | tokens | object | — | Per-token color config (same as static) | | other | string | object | — | Fallback for unspecified tokens | | onToken | function | — | Full override per token | | caretColor | string | "#e8eaf0" | Color of the text cursor | | showLineNumbers | boolean | true | Show line numbers on the left | | showErrors | boolean | true | Underline syntax errors with a red wavy line | | onError | function | — | Called with the error message string on parse error, null when the document is clean |

Editor API

| Method | Description | |--------|-------------| | getValue() | Returns the current editor content as a string | | setValue(code) | Replaces the editor content | | onUpdate(fn) | Calls fn(code) every time the content changes | | destroy() | Removes the editor and cleans up |


Token types

These are all the token types you can target in your tokens config:

| Token | What it represents | |-------|--------------------| | IDENTIFIER | Block names — div, h1, Card, etc. | | KEY | Prop keys — class, id, title, etc. | | VALUE | Prop values | | END_KEYWORD | The end keyword that closes blocks | | TEXT | Plain text content inside blocks | | COMMENT | Single-line comments starting with # | | COMMENT_BLOCK | Multi-line comments wrapped in ### | | OPEN_BRACKET | [ | | CLOSE_BRACKET | ] | | EQUAL | = | | COLON | : | | COMMA | , | | QUOTE | " | | EXCLAMATION_MARK | ! in self-closing blocks [br!] | | THIN_ARROW | -> in inline elements | | OPEN_PAREN | ( in inline elements | | CLOSE_PAREN | ) in inline elements | | OPEN_AT | @_ in at-blocks | | CLOSE_AT | @ closing at-blocks | | SEMICOLON | ; in at-blocks | | PREFIX_V | v{...} local variable | | PREFIX_P | p{...} public placeholder | | PREFIX_JS | js{...} JS data value | | LOGIC | Content inside static ${}$ or runtime ${}$ | | STATIC_KEYWORD | The static keyword | | RUNTIME_KEYWORD | The runtime keyword | | FOR_EACH | The for-each keyword | | IMPORT | The import keyword | | SLOT_KEYWORD | The slot keyword | | USE_MODULE | The $use-module keyword | | ESCAPE | Escaped characters |


Default theme

If you call staticHighlight(src) with no config, built-in default colors are used. You can access them to extend or override:

import { staticHighlight, defaultTokens } from "sommark-highlight";

const html = staticHighlight(src, {
  tokens: {
    ...defaultTokens,
    IDENTIFIER: "#f472b6",  // override just this one
  }
});

License

MIT