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

mokai

v0.6.1

Published

Tiny code editor for the web

Readme

mokai

Tiny, dependency‑free code editor for the web – minimal DOM, minimal API, fast edits.

npm version license

Why another embeddable editor? I wanted something extremely small and predictable for editing short snippets of HTML / JS / CSS / Markdown without shipping a full IDE. Mokai focuses on: tiny surface area, no virtual DOM, no workers by default, and opt‑in syntax highlighting.

Demo

Visit https://www.josemi.xyz/mokai for a live demo.

Features

  • ~1 small function: default export returns an editor object.
  • No dependencies, no build step required (ESM + CDN friendly).
  • Optional line numbers.
  • Optional auto indent + bracket / quote auto‑closing.
  • Pluggable syntax highlighting (bring your own or use mokai-syntax).
  • Theming via plain CSS classes (mokai-themes package).
  • Esc + Tab / Esc + Shift+Tab focus escape (avoid keyboard trap).

Install

Using a package manager

You can install mokai via npm or yarn:

# npm
npm install mokai

# yarn
yarn add mokai

Then import the stylesheet (ships as styles.css) and the editor:

import "mokai/styles.css";         // core layout + base token hooks (no colors)
import mokai from "mokai";

Via CDN (unpkg example)

<link rel="stylesheet" href="https://unpkg.com/mokai/styles.css">
<link rel="stylesheet" href="https://unpkg.com/mokai-themes/styles.css">
<div id="editor"></div>
<script type="module">
    import mokai from "https://unpkg.com/mokai/index.js";
    const editor = mokai(document.getElementById("editor"), {
        language: "javascript",
        className: "mokai-dark", // requires theme CSS from mokai-themes
        lineNumbers: true,
    });
    editor.set("console.log('Hello Mokai');\n");
    editor.on("change", ({ value }) => console.log("Changed:", value));
</script>

Quick start (module bundler)

import "mokai/styles.css";            // structural styles
import "mokai-themes/styles.css";     // optional: bundled themes
import mokai from "mokai";
import highlight from "mokai-syntax"; // optional highlighting

const editor = mokai(document.getElementById("editor"), {
    language: "javascript",
    highlight,
    className: "mokai-one-dark",
    lineNumbers: true,
});

editor.on("change", ({ value }) => {
    console.log("Current code:", value);
});

editor.set("function hi() {\n  console.log('hi');\n}\n");

API

mokai(parent: HTMLElement, options?: MokaiOptions): MokaiEditor

Creates the editor inside parent (Mokai appends its internal DOM). Returns an object implementing:

| Method | Description | |--------|-------------| | get() | Returns current code (always ends with a newline). | | set(code) | Replaces the entire content (adds trailing newline if missing). | | on(event, listener) | Subscribe to an event (change, keydown, keyup). For change you get { value }. Keyboard events receive the native event. | | off(event) | Unsubscribe / remove the listener for that event. |

Options (MokaiOptions)

| Option | Type | Default | Notes | |--------|------|---------|-------| | language | string | "" | Passed to your highlight function. | | readOnly | boolean | false | Disables content edits. | | lineNumbers | boolean | false | Shows a gutter with line numbers. | | indentWithTabs | boolean | false | Use \t instead of spaces. | | tabSize | number | 4 | Number of spaces per indent (ignored if tabs). | | autoIndent | boolean | true | Indent new lines and create extra line after closing braces when appropriate. | | addClosing | boolean | true | Auto insert matching (), [], {}, quotes. | | highlight | (code, lang) => string | undefined | Return HTML string (Mokai injects as innerHTML). Entire code passed (always newline‑terminated). | | className | string | "" | Extra class names applied to root .mokai element (used for themes). |

TypeScript

Types are bundled. Import them if you need compile‑time safety:

import type { MokaiOptions, MokaiEditor } from "mokai";

Syntax highlighting

Mokai does not bundle a highlighter. You can:

  1. Use the tiny companion package mokai-syntax (HTML / JS / CSS / Markdown) – predictable, minimal.
  2. Integrate a third‑party library (Prism, highlight.js, Shiki, etc.). Just ensure you return raw HTML with escaped content + token spans from your highlight function.

Example with mokai-syntax:

import highlight from "mokai-syntax";
const editor = mokai(parent, {
    language: "javascript",
    highlight: (code, lang) => highlight(code, lang),
});

editor.on("change", ({ value }) => console.log(value));

Example with highlight.js:

import hljs from "highlight.js";
const editor = mokai(parent, {
    language: "javascript",
    highlight: (code, lang) => hljs.highlight(code, { language: lang || "plaintext" }).value,
});

editor.on("change", ({ value }) => {/* handle updated code */});

Themes

Install mokai-themes for a small bundle of ready‑made themes:

npm install mokai-themes
import "mokai/styles.css";          // core editor structure
import "mokai-themes/styles.css";   // theme classes

const editor = mokai(parent, { className: "mokai-dark" });

Available themes (see mokai-themes README for details): mokai-light, mokai-dark, mokai-monoblue, mokai-one-light, mokai-one-dark.

Create your own by defining .mokai-my-theme { ... } plus token color rules (e.g. .mokai-my-theme .token-keyword { color:#c92c2c; }) and pass className: "mokai-my-theme".

Accessibility & Focus Management

Mokai is designed to avoid trapping keyboard focus within the editor, supporting accessible navigation for all users. Editor content uses contenteditable (with plaintext-only where supported) and does not permanently trap focus.

  • Move focus forward: Press Esc then Tab to shift focus to the next focusable element.
  • Move focus backward: Press Esc then Shift+Tab to shift focus to the previous focusable element.
  • Indentation: The Tab key is reserved for code indentation, as is common in code editors.

These shortcuts help prevent keyboard trap scenarios, ensuring users can easily navigate away from the editor when needed. Mokai intentionally does not provide a built-in shortcuts help UI; document any shortcuts in your host application as needed.

Design notes / limitations

  • Not a full IDE: no search panel, no multi‑file model, no undo stack persistence beyond browser default selection behavior.
  • Highlighting is whatever you provide – Mokai just injects HTML.
  • Entire document is re‑highlighted (keep code blocks modest for best performance).
  • Internally Mokai ensures the stored code ends with a newline; account for that if doing diffing.

Migration from CodeCake

If you used the earlier name codecake:

| Before (codecake) | Now (mokai) | |---------------------|---------------| | import * as CodeCake from "codecake"; | import mokai from "mokai"; | | CodeCake.create(parent, opts) | mokai(parent, opts) (default export) | | cake.getCode() / cake.setCode() | editor.get() / editor.set() | | cake.onChange(code => { ... }) | editor.on("change", ({ value }) => { ... }) | | cake.onKeyDown(fn) / cake.onKeyUp(fn) | editor.on("keydown", fn) / editor.on("keyup", fn) | | CodeCake.highlight (bundled) | Use mokai-syntax or another highlighter | | Themes codecake-light/dark | Themes now provided by mokai-themes (mokai-light, mokai-dark, etc.) | | CSS codecake.css | mokai/styles.css |

No behavioral breaking changes other than renaming and moving the optional highlighter to a separate package.

Security

If you supply a highlight function, ensure it escapes untrusted content. The companion mokai-syntax already escapes all raw characters. Only inject the resulting HTML into trusted containers (never into attributes or unsanitized contexts) to avoid XSS.

License

Mokai is released under the MIT License.

Questions / tiny improvements welcome – open an issue or PR.