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

draftly

v2.1.0

Published

Core library for draftly

Readme


Overview

Draftly is a powerful, pluggable markdown editor and preview toolkit built on top of CodeMirror 6. It provides a seamless "rich text" editing experience while preserving standard markdown syntax. Draftly also includes a static HTML renderer that produces output visually identical to the editor, making it perfect for blogs, documentation sites, and content management systems.

Why Draftly?

  • 🚀 Modern Architecture: Built on CodeMirror 6 with incremental Lezer parsing.
  • 🎨 Rich Editing: WYSIWYG-like experience with full markdown control.
  • 🔌 Extensible Plugin System: Add custom rendering, keymaps, and syntax.
  • 🖼️ Static Preview: Render markdown to semantic HTML with visual parity.
  • 🌗 Theming: First-class support for light and dark modes.
  • 📦 Modular Exports: Import only what you need (draftly/editor, draftly/preview, draftly/plugins).

Installation

Install the package via your preferred package manager:

# npm
npm install draftly

# yarn
yarn add draftly

# pnpm
pnpm add draftly

# bun
bun add draftly

Peer Dependencies

Draftly requires the following CodeMirror packages as peer dependencies. Make sure they are installed in your project:

npm install @codemirror/commands @codemirror/lang-markdown @codemirror/language @codemirror/language-data @codemirror/state @codemirror/view

Quick Start

Get up and running in seconds.

import { EditorView } from "@codemirror/view";
import { EditorState } from "@codemirror/state";
import { draftly } from "draftly";

const view = new EditorView({
  state: EditorState.create({
    doc: "# Hello, Draftly!",
    extensions: [draftly()],
  }),
  parent: document.getElementById("editor")!,
});

Usage

Draftly is designed for flexibility. Use it as a CodeMirror extension for interactive editing or as a standalone renderer for static previews.

Editor Integration

Here's a complete example using @uiw/react-codemirror:

import CodeMirror from "@uiw/react-codemirror";
import { draftly, allPlugins, ThemeEnum } from "draftly";
import { githubDark } from "@uiw/codemirror-theme-github";

function MarkdownEditor() {
  return (
    <CodeMirror
      value="# Welcome to Draftly\n\nStart writing..."
      height="500px"
      extensions={[
        draftly({
          theme: ThemeEnum.DARK,
          themeStyle: githubDark,
          plugins: allPlugins,
          lineWrapping: true,
          history: true,
          indentWithTab: true,
          onNodesChange: (nodes) => console.log("AST:", nodes),
        }),
      ]}
    />
  );
}

Editor Configuration (DraftlyConfig)

| Option | Type | Default | Description | | --------------------- | -------------------------------- | ---------------- | -------------------------------------------------------- | | theme | ThemeEnum | ThemeEnum.AUTO | Theme mode: LIGHT, DARK, or AUTO. | | themeStyle | Extension | undefined | CodeMirror theme extension (e.g., githubDark). | | plugins | DraftlyPlugin[] | [] | Plugins to enable for rendering and parsing. | | baseStyles | boolean | true | Load default base styles. | | disableViewPlugin | boolean | false | Disable rich rendering (raw markdown mode). | | defaultKeybindings | boolean | true | Enable default CodeMirror keybindings. | | history | boolean | true | Enable undo/redo history. | | indentWithTab | boolean | true | Use Tab for indentation. | | highlightActiveLine | boolean | true | Highlight the current line (in raw mode). | | lineWrapping | boolean | true | Enable line wrapping. | | onNodesChange | (nodes: DraftlyNode[]) => void | undefined | Callback fired on every document update with parsed AST. | | markdown | MarkdownConfig[] | [] | Additional Lezer markdown parser extensions. | | extensions | Extension[] | [] | Additional CodeMirror extensions. | | keymap | KeyBinding[] | [] | Additional keybindings. |


Static Preview

Render markdown to semantic HTML for server-side rendering, static site generation, or read-only views.

import { preview, generateCSS, allPlugins, ThemeEnum } from "draftly";
import { githubLight } from "@uiw/codemirror-theme-github";

const markdown = `
# Hello World

This is a **bold** statement with some \`inline code\`.

- Item 1
- Item 2
- Item 3
`;

// Generate HTML
const html = preview(markdown, {
  theme: ThemeEnum.LIGHT,
  plugins: allPlugins,
  sanitize: true,
  wrapperClass: "prose",
});

// Generate matching CSS
const css = generateCSS({
  theme: ThemeEnum.LIGHT,
  plugins: allPlugins,
  wrapperClass: "prose",
  includeBase: true,
  syntaxTheme: githubLight,
});

// Use in your app
function ArticlePreview() {
  return (
    <>
      <style>{css}</style>
      <article dangerouslySetInnerHTML={{ __html: html }} />
    </>
  );
}

Preview Configuration (PreviewConfig)

| Option | Type | Default | Description | | -------------- | ------------------ | ------------------- | ------------------------------------- | | plugins | DraftlyPlugin[] | [] | Plugins for rendering. | | theme | ThemeEnum | ThemeEnum.AUTO | Theme mode. | | sanitize | boolean | true | Sanitize HTML output (via DOMPurify). | | wrapperClass | string | "draftly-preview" | CSS class for the wrapper element. | | wrapperTag | string | "article" | HTML tag for the wrapper element. | | markdown | MarkdownConfig[] | [] | Additional parser extensions. |

CSS Configuration (GenerateCSSConfig)

| Option | Type | Default | Description | | -------------- | -------------------------------------------- | ------------------- | ----------------------------------------------------------------------------- | | plugins | DraftlyPlugin[] | [] | Plugins to collect preview styles from. | | theme | ThemeEnum | ThemeEnum.AUTO | Theme mode for plugin preview styles. | | wrapperClass | string | "draftly-preview" | Wrapper class used for CSS scoping. | | includeBase | boolean | true | Include Draftly base preview layout styles. | | syntaxTheme | HighlightStyle \| Extension \| Extension[] | undefined | CodeMirror syntax theme/extensions used to generate tok-* syntax token CSS. |


Features

🎯 Rich Text Editing

Draftly's ViewPlugin decorates the editor to hide markdown syntax and render styled content inline. This provides a WYSIWYG-like experience while keeping the source as plain markdown.

  • Inline Formatting: Bold, italic, strikethrough, and code are styled in-place.
  • Headings: Rendered with proper sizes and weights.
  • Lists: Ordered and unordered lists with custom bullets.
  • Images: Displayed inline with alt text and captions.
  • Links: Clickable with visual distinction.
  • Code Blocks: Syntax highlighted with language detection.

🔌 Plugin Architecture

Every feature in Draftly is a plugin. Plugins can provide:

  • CodeMirror Extensions: Custom decorations, widgets, and behaviors.
  • Markdown Parser Extensions: Extend the Lezer parser for custom syntax.
  • Keymaps: Add keyboard shortcuts.
  • Themes: Inject custom styles based on the current theme.
  • Preview Renderers: Define how elements are rendered to static HTML.
import { DraftlyPlugin } from "draftly/editor";

class MyCustomPlugin extends DraftlyPlugin {
  name = "my-custom-plugin";

  onRegister(context) {
    console.log("Plugin registered!", context.config);
  }

  getExtensions() {
    return [
      /* CodeMirror extensions */
    ];
  }

  getKeymap() {
    return [
      /* KeyBinding[] */
    ];
  }

  getMarkdownConfig() {
    return {
      /* MarkdownConfig */
    };
  }

  theme(mode) {
    return {
      /* Theme spec */
    };
  }
}

🌲 AST Access

Access the parsed document structure via the onNodesChange callback. Perfect for building:

  • Table of Contents
  • Document Outlines
  • Navigation Breadcrumbs
  • Word/Line Counters
type DraftlyNode = {
  from: number; // Start position
  to: number; // End position
  name: string; // Node type (e.g., "Heading", "Paragraph")
  children: DraftlyNode[];
  isSelected: boolean; // True if cursor is within this node
};

🌗 Theming

Draftly provides seamless theming with automatic light/dark mode support:

  • Auto Detection: Follows system preference with ThemeEnum.AUTO.
  • Manual Control: Force ThemeEnum.LIGHT or ThemeEnum.DARK.
  • Custom Themes: Pass any CodeMirror theme via themeStyle.
  • Preview Parity: CSS generation ensures preview matches editor styling.

📦 Modular Imports

Import only what you need to minimize bundle size:

// Full package
import { draftly, preview, allPlugins } from "draftly";

// Editor only
import { draftly, DraftlyPlugin } from "draftly/editor";

// Preview only
import { preview, generateCSS } from "draftly/preview";

// Individual plugins
import { HeadingPlugin, ListPlugin } from "draftly/plugins";

API Reference

Exports

| Export | Path | Description | | --------------- | ----------------- | ----------------------------------------------- | | draftly | draftly/editor | Main editor extension factory. | | DraftlyPlugin | draftly/editor | Base class for creating plugins. | | ThemeEnum | draftly/editor | Enum for theme modes (AUTO, LIGHT, DARK). | | DraftlyNode | draftly/editor | Type for AST nodes. | | preview | draftly/preview | Function to render markdown to HTML. | | generateCSS | draftly/preview | Function to generate CSS for preview styling. | | allPlugins | draftly/plugins | Array of all built-in plugins. |


Browser Support

Draftly supports all modern browsers:

| Browser | Version | | ------- | ------- | | Chrome | 88+ | | Firefox | 78+ | | Safari | 14+ | | Edge | 88+ |


Contributing

Contributions are welcome! Please read our Contributing Guide before submitting a pull request.


License

MIT © NeuroNexul