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

@atlarafirm/quillkit

v1.3.4

Published

A Javascript library for adding rich-text functionality to HTML textareas

Readme

QuillKit

A powerful JavaScript library that transforms basic HTML textareas into full-featured rich-text editors with toolbar support, multiple view modes, and mathematical expression rendering.

Features

  • Rich Text Editing: Full WYSIWYG editor with formatting capabilities
  • Page View: Render content on a virtual piece of paper (8.5" x 11") with realistic margins, similar to Microsoft Word
  • Comprehensive Toolbar:
    • Text formatting (Bold, Italic, Underline, Strikethrough)
    • Text alignment (Left, Center, Right)
    • Lists:
      • Bullet lists (Unordered)
      • Numbered lists (Ordered)
      • Multiple bullet styles (disc, circle, square)
      • Multiple numbering styles (1,2,3 | a,b,c | i,ii,iii | etc.)
      • Edit individual list item numbers with custom values
    • Headings (H1, H2, H3) and Paragraph styles
    • Insert links, images, and icons
    • Undo/Redo functionality
    • Page view toggle
  • Advanced Image Support:
    • Insert images with URL
    • Specify pixel dimensions (width/height) when inserting
    • Drag corner handles to resize images
    • Proportional resizing maintains aspect ratio
    • Visual resize handles on all images
  • Advanced Table Support:
    • Create tables with custom rows and columns
    • Resizable columns (drag to resize)
    • Resizable rows (drag to resize)
    • Auto-fit columns to content (double-click column edge)
    • Custom border colors with color picker
    • Add/remove rows and columns dynamically
    • Full manipulation toolbar
  • Column Layout Support:
    • Multi-column layouts (newspaper-style columns)
    • 1-column, 2-column, and 3-column layouts
    • Automatic text flow across columns
    • Visual column dividers
    • Easy toggle between layouts
  • Multiple View Modes:
    • Rich Text Mode: Visual editing with formatting toolbar
    • HTML Mode: Direct HTML code editing
    • CSS Mode: View and edit extracted inline styles
  • Mathematical Expression Support:
    • LaTeX rendering using KaTeX
    • Native MathML support
    • Configurable default font size for all math elements
  • Custom HTML Snippets:
    • Define custom snippet groups for reusable HTML content
    • Browse and insert snippets via toolbar buttons
    • Perfect for frequently used templates, components, or formulas
  • Icon Support:
    • Bootstrap Icons library with 1,800+ icons
    • Font Awesome library with 30,000+ icons
    • Custom icon URLs for your own images
    • Easy-to-use icon browser modal
  • Circle Annotation Plugin:
    • Select words by double-clicking or dragging to select
    • Add circular annotations around words with customizable notes
    • Add parts of speech labels above circled words
    • Add custom notes below circled words
    • Perfect for language learning, document review, and educational materials
    • Integrated deletion and cleanup on click-away
  • History Management: Undo/redo with configurable history limit
  • Keyboard Shortcuts:
    • Ctrl/Cmd + B (Bold)
    • Ctrl/Cmd + I (Italic)
    • Ctrl/Cmd + U (Underline)
    • Ctrl/Cmd + Z (Undo)
    • Ctrl/Cmd + Shift + Z / Ctrl/Cmd + Y (Redo)
  • Plugin System:
    • Modular architecture - load only what you need
    • Reduce JavaScript bundle size by selecting specific features
    • Create custom plugins to extend functionality
    • Dynamic plugin loading/unloading at runtime
    • All features are now plugins (backward compatible)
  • Flexible Configuration: Customizable toolbar, mode switching, and editor height
  • Easy Integration: Simple API for getting and setting content
  • Backend API (NEW!):
    • Complete REST API for productization and distribution
    • API key management with usage tracking
    • Feature access control based on subscription plans
    • Stripe payment integration
    • Docker and Docker Compose support for easy deployment
    • Heroku deployment ready - Deploy backend, frontend, editor library, and examples in one unified container
    • See backend/README.md for API details
    • See DOCKER.md for Docker deployment instructions
    • See QUICK_HEROKU_DEPLOY.md for Heroku deployment (or HEROKU_DEPLOYMENT_REWORK.md for details)

Installation

⚠️ API Key Required

QuillKit requires a valid API key to function. Get your API key from the QuillKit service.

Without an API key, the editor will not be functional.

Using npm

npm install @atlarafirm/quillkit

Using CDN

You can include QuillKit directly in your HTML using a CDN link. This is the easiest way to get started without any build tools.

unpkg

<!-- Latest version -->
<script src="https://unpkg.com/@atlarafirm/quillkit/dist/quillkit.js"></script>

<!-- Or use the latest version (always up-to-date, but may break with major updates) -->
<script src="https://unpkg.com/@atlarafirm/quillkit/dist/quillkit.js"></script>

jsDelivr

<!-- Latest version -->
<script src="https://cdn.jsdelivr.net/npm/@atlarafirm/quillkit/dist/quillkit.js"></script>

<!-- Or use the latest version -->
<script src="https://cdn.jsdelivr.net/npm/@atlarafirm/quillkit/dist/quillkit.js"></script>

📺 Interactive Demo

See demo-api-cdn-integration.html for a complete, interactive demo that shows:

  • How to use QuillKit with CDN links
  • How to integrate with the backend API using API keys
  • Feature access control based on subscription plans
  • Live editor with all features demonstrated
  • Step-by-step guide with code examples

Usage

⚠️ IMPORTANT: API Key Required

QuillKit requires a valid API key to function. You must provide an API key when initializing the editor. Get your API key from the QuillKit service.

Without a valid API key, the editor will display a blocking modal and will not be functional.

QuillKit supports two initialization patterns: the Global API pattern (recommended for new projects) and the traditional constructor pattern (for backward compatibility).

Global API Pattern (Recommended)

The new global API provides instance management and a global event system:

<!DOCTYPE html>
<html>
<head>
  <title>QuillKit Example</title>
</head>
<body>
  <textarea id="my-editor">
    <h1>Hello World!</h1>
    <p>Start editing here...</p>
  </textarea>

  <script src="dist/quillkit.js"></script>
  <script>
    // Initialize using global API with REQUIRED API key
    const editor = QuillKit.init('#my-editor', {
      apiKey: 'ak_your_api_key_here'  // REQUIRED - Get from QuillKit service
    });

    // Access from anywhere on the page
    const editor = QuillKit.getInstance('my-editor');
  </script>
</body>
</html>

Traditional Constructor Pattern

<script src="dist/quillkit.js"></script>
<script>
  // Traditional way (still fully supported) with REQUIRED API key
  const editor = new QuillKit('#my-editor', {
    apiKey: 'ak_your_api_key_here'  // REQUIRED - Get from QuillKit service
  });
</script>

With Options

Both patterns support the same options:

// Global API
const editor = QuillKit.init('#my-editor', {
  apiKey: 'ak_your_api_key_here',  // REQUIRED - Your API key from QuillKit service
  toolbar: true,          // Show toolbar (default: true)
  modeSwitching: true,    // Enable mode switching tabs (default: true)
  mathSupport: true,      // Enable LaTeX and MathML support (default: true)
  mathFontSize: null,     // Default font size for math (e.g., '20pt', '1.5em') (default: null)
  height: '500px',        // Custom editor height (default: '400px')
  pageView: true,         // Enable page view mode (default: true)
  customSnippets: {}      // Custom HTML snippet groups (default: {})
});

// Or traditional constructor
const editor = new QuillKit('#my-editor', {
  apiKey: 'ak_your_api_key_here',  // REQUIRED - Your API key from QuillKit service
  toolbar: true,
  modeSwitching: true,
  // ... same options
});

Minimal Editor (No Toolbar)

const editor = QuillKit.init('#my-editor', {
  apiKey: 'ak_your_api_key_here',  // REQUIRED - Your API key from QuillKit service
  toolbar: false,
  modeSwitching: false
});

Editor with Custom HTML Snippets

const editor = new QuillKit('#my-editor', {
  apiKey: 'ak_your_api_key_here',  // REQUIRED - Your API key from QuillKit service
  customSnippets: {
    'math-components': [
      {
        name: 'Einstein Equation',
        html: '<div class="equation">E = mc²</div>'
      },
      {
        name: 'Pythagorean Theorem',
        html: '<div class="equation">a² + b² = c²</div>'
      }
    ],
    'text-templates': [
      {
        name: 'Info Box',
        html: '<div class="info">Important information here</div>'
      }
    ]
  }
});

Plugin System

QuillKit features a modular plugin system that allows you to load only the features you need, significantly reducing bundle size.

Note: All examples require a valid API key. See the Usage section for details.

Using the Plugin System

Load all features (default):

const editor = QuillKit.init('#my-editor', {
  apiKey: 'ak_your_api_key_here'  // REQUIRED
});

Load specific plugins only:

const editor = QuillKit.init('#my-editor', {
  apiKey: 'ak_your_api_key_here',  // REQUIRED
  plugins: ['textFormatting', 'alignment', 'list', 'history']
});

Minimal editor:

const editor = QuillKit.init('#my-editor', {
  apiKey: 'ak_your_api_key_here',  // REQUIRED
  plugins: ['textFormatting', 'history']
});

Available Built-in Plugins

  • textFormatting - Bold, italic, underline, strikethrough
  • fontFamily - Font family selection
  • fontSize - Font size selection
  • alignment - Text alignment (left, center, right)
  • list - Bullet and numbered lists
  • blockFormatting - Headings (H1-H3) and paragraphs
  • link - Link insertion
  • image - Image insertion and resizing
  • table - Table creation and manipulation
  • column - Multi-column layouts (1, 2, or 3 columns)
  • noteBox - Custom note boxes with collapsible content
  • symbol - Symbol picker for special characters
  • bookmark - Bookmark management for navigation
  • pageBreak - Insert page breaks
  • circleAnnotation - Circle words and add annotations for language learning and document review
  • history - Undo/redo functionality
  • pageView - Page view mode
  • math - LaTeX and MathML support
  • iconLibrary - Icon insertion from Bootstrap Icons, Font Awesome, and custom sources
  • customSnippet - Custom HTML snippet insertion
  • insert - General insertion commands

Creating Custom Plugins

import { Plugin } from '@atlarafirm/quillkit';

class MyCustomPlugin extends Plugin {
  constructor(editor, options = {}) {
    super(editor, options);
    this.name = 'MyCustomPlugin';
  }

  getToolbarButtons() {
    return [{
      name: 'my-buttons',
      buttons: [
        { command: 'myCommand', label: '⚡', title: 'My Command' }
      ]
    }];
  }

  executeCommand(command, value) {
    if (command === 'myCommand') {
      // Your logic here
    }
  }

  getMetadata() {
    return {
      name: 'My Custom Plugin',
      version: '1.0.0',
      description: 'Does something amazing',
      author: 'Your Name'
    };
  }
}

// Register and use
const editor = QuillKit.init('#my-editor', {
  apiKey: 'ak_your_api_key_here'  // REQUIRED
});
editor.pluginManager.register('myCustom', MyCustomPlugin);
editor.pluginManager.load('myCustom');

Dynamic Plugin Loading

// Load a plugin at runtime
editor.pluginManager.load('math');

// Unload a plugin
editor.pluginManager.unload('alignment');

// Check if loaded
if (editor.pluginManager.isLoaded('table')) {
  console.log('Table plugin is available');
}

For comprehensive documentation, see PLUGIN_SYSTEM.md and the plugin system demo in examples/plugin-system-demo.html.

API

Global API Methods

The Global API provides static methods for managing editor instances across your application.

QuillKit.init(textarea, options)

Initialize a new editor instance with automatic instance tracking.

const editor = QuillKit.init('#my-editor', { height: '500px' });
  • textarea: Either a textarea DOM element or a CSS selector string
  • options: Configuration object (optional)
  • Returns: Editor instance (returns existing instance if already initialized)

QuillKit.getInstance(id)

Get an editor instance by its textarea ID.

const editor = QuillKit.getInstance('my-editor');
if (editor) {
  console.log(editor.getValue());
}

QuillKit.getAllInstances()

Get an array of all active editor instances.

const allEditors = QuillKit.getAllInstances();
console.log(`Total editors: ${allEditors.length}`);

QuillKit.destroyInstance(id)

Destroy a specific editor instance by ID.

const destroyed = QuillKit.destroyInstance('my-editor');
// Returns true if destroyed, false if not found

QuillKit.destroyAll()

Destroy all editor instances.

QuillKit.destroyAll();

QuillKit.on(event, callback)

Register a global event listener.

QuillKit.on('init', (data) => {
  console.log(`Editor ${data.id} initialized`);
});

Built-in events:

  • init: Fired when an editor is initialized via QuillKit.init()
  • destroy: Fired when an editor is destroyed

QuillKit.off(event, callback)

Remove a global event listener.

const handler = (data) => console.log(data);
QuillKit.on('init', handler);
// Later...
QuillKit.off('init', handler);
// Or remove all listeners for an event
QuillKit.off('init');

QuillKit.emit(event, data)

Emit a custom event to all listeners.

QuillKit.emit('custom-event', { message: 'Hello!' });

Constructor (Traditional Pattern)

new QuillKit(textarea, options)
  • textarea: Either a textarea DOM element or a CSS selector string
  • options: Configuration object (optional)

Note: Instances created with new QuillKit() are not tracked in the global instance map.

Instance Methods

getValue()

Get the current HTML content as a string.

const html = editor.getValue();

setValue(value)

Set the editor content.

editor.setValue('<h1>New Content</h1><p>Some text...</p>');

getMode()

Get the current view mode ('rich', 'html', or 'css').

const mode = editor.getMode(); // Returns: 'rich', 'html', or 'css'

setMode(mode)

Switch to a different view mode.

editor.setMode('html');  // Switch to HTML mode
editor.setMode('rich');  // Switch to Rich Text mode
editor.setMode('css');   // Switch to CSS mode

destroy()

Remove the editor and restore the original textarea.

editor.destroy();

View Modes

Rich Text Mode

  • Visual WYSIWYG editing
  • Full toolbar functionality
  • Real-time formatting

HTML Mode

  • Direct HTML code editing
  • Syntax-friendly monospace font
  • Ideal for manual HTML adjustments

CSS Mode

  • Automatically extracts inline styles from HTML
  • Displays styles in CSS format
  • Useful for viewing and understanding applied styles

Page View

The editor includes a Page View feature that renders content on a virtual piece of paper, similar to Microsoft Word:

  • Paper Size: 8.5" x 11" (standard US Letter size)
  • Margins: 1 inch on all sides
  • Appearance: Realistic paper with shadow effect
  • Toggle: Click the 📄 button in the toolbar to enable/disable

This feature provides a better visualization of how documents will look when printed and creates a more professional editing experience.

// Enable page view (default)
const editor = new QuillKit('#my-editor', {
  apiKey: 'ak_your_api_key_here',  // REQUIRED
  pageView: true
});

// Disable page view
const editor = new QuillKit('#my-editor', {
  apiKey: 'ak_your_api_key_here',  // REQUIRED
  pageView: false
});

Custom HTML Snippets

The editor supports Custom HTML Snippets, allowing end users to define reusable HTML content that can be easily inserted via the toolbar.

How It Works

  1. Define snippet groups when initializing the editor
  2. Each group gets its own ⊕ button in the toolbar
  3. Clicking the button opens a modal showing all snippets in that group
  4. Users can preview snippets and insert them with one click

Configuration

Add custom snippets through the customSnippets option:

const editor = new QuillKit('#my-editor', {
  apiKey: 'ak_your_api_key_here',  // REQUIRED
  customSnippets: {
    'math-components': [
      {
        name: 'Einstein Equation',
        html: '<div style="text-align: center;">E = mc²</div>'
      },
      {
        name: 'Pythagorean Theorem',
        html: '<div style="text-align: center;">a² + b² = c²</div>'
      }
    ],
    'text-templates': [
      {
        name: 'Info Box',
        html: '<div style="background: #e7f3ff; border-left: 4px solid #007bff; padding: 15px;"><strong>Note:</strong> Important information</div>'
      },
      {
        name: 'Warning Box',
        html: '<div style="background: #fff3cd; border-left: 4px solid #ffc107; padding: 15px;"><strong>Warning:</strong> Please be careful</div>'
      }
    ]
  }
});

Snippet Structure

Each snippet object has two properties:

  • name (string): The display name shown in the snippet browser
  • html (string): The HTML content to insert when the snippet is selected

Use Cases

Custom snippets are perfect for:

  • Mathematical formulas and equations
  • Text templates (headers, footers, callout boxes)
  • Reusable components (contact forms, cards, tables)
  • Branded content (company logos, disclaimers, signatures)
  • Code blocks or special formatting

Security Note

Custom snippets are defined by developers during editor initialization and are treated as trusted content. Ensure that snippet HTML comes from trusted sources only, as it will be inserted directly into the editor without sanitization.

Icon Support

QuillKit includes powerful icon support, allowing users to easily insert icons from popular icon libraries or custom icon URLs into their documents.

Features

  • Bootstrap Icons: Access to 1,800+ high-quality icons from the Bootstrap Icons library
  • Font Awesome: Access to 30,000+ icons from the world's most popular icon toolkit
  • Custom Icons: Use your own icon images via URLs
  • Interactive Browser: Beautiful modal interface to browse and select icons
  • Tab Navigation: Switch between different icon sources with ease
  • Automatic CSS Loading: Automatically injects required icon library CSS when needed

Configuration

Enable icon support when initializing the editor:

const editor = new QuillKit('#my-editor', {
  apiKey: 'ak_your_api_key_here',  // REQUIRED
  icons: {
    enabled: true,          // Enable icon support (default: true)
    bootstrap: true,        // Enable Bootstrap Icons (default: true)
    fontAwesome: true,      // Enable Font Awesome (default: true)
    autoLoadCss: true,      // Auto-inject CSS for icon libraries (default: true)
    bootstrapCdn: 'https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.css',
    fontAwesomeCdn: 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css',
    customIcons: [          // Custom icon URLs (default: [])
      {
        name: 'My Logo',
        url: 'https://example.com/logo.png'
      },
      {
        name: 'Custom Icon',
        url: 'https://example.com/icon.svg'
      }
    ]
  }
});

Automatic CSS Loading

New in this version: QuillKit now automatically injects the required CSS for icon libraries when you open the icon modal. This ensures icons render properly without requiring you to manually include CSS links in your HTML.

How it works:

  • When you click the icon button (⭐) to open the icon modal, the editor checks if the required CSS is already loaded
  • If not loaded, it automatically injects the CSS into the document <head>
  • Smart duplicate detection prevents loading the same CSS multiple times
  • Works with both default CDN URLs and custom CDN URLs

Configuration options:

  • autoLoadCss (default: true): Enable/disable automatic CSS injection
  • bootstrapCdn: Custom CDN URL for Bootstrap Icons CSS
  • fontAwesomeCdn: Custom CDN URL for Font Awesome CSS

To disable auto-loading (if you prefer to manage CSS yourself):

const editor = new QuillKit('#my-editor', {
  icons: {
    enabled: true,
    autoLoadCss: false  // Disable automatic CSS injection
  }
});

Icon Sources

Bootstrap Icons

Bootstrap Icons are automatically loaded when you open the icon modal (if autoLoadCss is enabled).

Alternatively, you can manually include the CDN in your HTML:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/font/bootstrap-icons.css">

Bootstrap Icons are inserted as icon fonts:

<i class="bi bi-heart"></i>

Font Awesome

Font Awesome CSS is automatically loaded when you open the icon modal (if autoLoadCss is enabled).

Alternatively, you can manually include the CDN in your HTML:

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">

Font Awesome icons are inserted as icon fonts:

<i class="fas fa-coffee"></i>

Custom Icons

Custom icons are inserted as <img> tags with the URL you provide:

<img src="https://example.com/icon.png" alt="My Icon" style="max-width: 32px; max-height: 32px; vertical-align: middle;" />

Usage

  1. Click the ⭐ icon button in the toolbar
  2. Browse icons in the modal that appears
  3. Switch between tabs (Bootstrap Icons, Font Awesome, Custom Icons) if multiple sources are enabled
  4. Click on an icon to insert it at the cursor position

Examples

Enable only Bootstrap Icons:

const editor = new QuillKit('#my-editor', {
  icons: {
    enabled: true,
    bootstrap: true,
    fontAwesome: false,
    customIcons: []
  }
});

Enable only Font Awesome:

const editor = new QuillKit('#my-editor', {
  icons: {
    enabled: true,
    bootstrap: false,
    fontAwesome: true,
    customIcons: []
  }
});

Use only custom icons:

const editor = new QuillKit('#my-editor', {
  icons: {
    enabled: true,
    bootstrap: false,
    fontAwesome: false,
    customIcons: [
      { name: 'Logo', url: 'https://example.com/logo.png' },
      { name: 'Badge', url: 'https://example.com/badge.svg' }
    ]
  }
});

Use custom CDN URLs:

const editor = new QuillKit('#my-editor', {
  icons: {
    enabled: true,
    bootstrap: true,
    fontAwesome: true,
    autoLoadCss: true,
    bootstrapCdn: 'https://your-cdn.example.com/bootstrap-icons.css',
    fontAwesomeCdn: 'https://your-cdn.example.com/font-awesome.css'
  }
});

Disable icon support:

const editor = new QuillKit('#my-editor', {
  icons: {
    enabled: false
  }
});

Demo

See the examples/icons-demo.html and examples/test-icon-css-injection.html files for complete demos showcasing all icon features, including automatic CSS injection.

Image Support

QuillKit provides comprehensive image functionality with resizing capabilities and dimension control.

Inserting Images

Click the 🖼 button in the toolbar to open the image insertion dialog:

  1. Enter the image URL (HTTP, HTTPS, or Data URL)
  2. Optionally specify alternative text for accessibility
  3. Optionally specify width in pixels
  4. Optionally specify height in pixels
  5. Click Insert
// You can also insert images programmatically
import * as SelectionUtils from './SelectionUtils';

// Insert with URL only
SelectionUtils.insertImage('https://example.com/image.jpg');

// Insert with alt text
SelectionUtils.insertImage('https://example.com/image.jpg', 'Description');

// Insert with dimensions
SelectionUtils.insertImage('https://example.com/image.jpg', 'Description', 400, 300);

Resizing Images

After inserting an image, you can resize it visually:

Drag to Resize

  • Hover over any corner of an image to see resize handles
  • Click and drag any corner handle to resize the image
  • Proportional Resizing: Dragging maintains the original aspect ratio
  • Minimum Size: Images cannot be resized smaller than 50px

Visual Feedback

  • Blue corner handles appear at all four corners: northwest, northeast, southwest, southeast
  • Handles are visible when hovering over or interacting with images
  • Cursor changes to indicate resize direction

Specify Dimensions

When inserting an image, you can specify exact pixel dimensions:

  • Width: Enter the desired width in pixels
  • Height: Enter the desired height in pixels
  • Leave blank: Image will use its natural dimensions
  • Specify one: Aspect ratio is maintained automatically

Technical Details

  • Images are wrapped in a container div for resize handle positioning
  • Resize handles are automatically added via MutationObserver
  • All images get the quillkit-image class
  • Resizing maintains aspect ratio for proportional scaling
  • All image operations support undo/redo
  • Minimum dimensions ensure usability

Example

const editor = new QuillKit('#my-editor', {
  toolbar: true,
  height: '500px'
});

// Images are inserted interactively via the UI
// Resize handles appear automatically on all images

Demo

See the examples/image-resize-demo.html file for a complete demo showcasing all image features.

Table Support

QuillKit provides comprehensive table functionality with advanced resizing capabilities and customization options.

Creating Tables

Click the button in the toolbar to open the table creation dialog:

  1. Specify the number of rows (1-20)
  2. Specify the number of columns (1-20)
  3. Choose a custom border color using the color picker
  4. Click Insert

Resizing Tables

Column Width Resizing

  • Hover over the right edge of any column (except the last one) to see the resize cursor
  • Click and drag to adjust the column width
  • Minimum column width is 50px

Row Height Resizing

  • Hover over the bottom edge of any row (except the last one) to see the resize cursor
  • Click and drag to adjust the row height
  • Minimum row height is 30px

Auto-Fit to Content

  • Double-click the right edge of any column to automatically fit the column width to its content
  • The editor calculates the maximum content width across all cells in the column

Custom Border Colors

When creating a table, you can specify a custom border color:

  • Use the color picker in the table creation dialog
  • Default border color is #dddddd (light gray)
  • Border colors are preserved when adding new rows or columns

Table Manipulation

Use the table manipulation buttons in the toolbar:

  • ↑+ Add Row Above - Insert a row above the current cursor position
  • ↓+ Add Row Below - Insert a row below the current cursor position
  • ←+ Add Column Left - Insert a column to the left of the cursor
  • →+ Add Column Right - Insert a column to the right of the cursor
  • ↕− Remove Row - Delete the row containing the cursor
  • ↔− Remove Column - Delete the column containing the cursor
  • Delete Table - Remove the entire table

Technical Details

  • Tables use table-layout: fixed for predictable resizing
  • Resize handles are automatically added via MutationObserver
  • Border colors are stored as data attributes on table elements
  • All table operations support undo/redo
  • Minimum dimensions ensure usability

Example

const editor = new QuillKit('#my-editor', {
  toolbar: true,
  height: '600px'
});

// Tables are created interactively via the UI
// Resize handles appear automatically when tables are inserted

Demo

See the examples/table-demo.html and examples/table-resize-demo.html files for complete demos showcasing all table features.

Column Layout Support

QuillKit supports multi-column layouts, similar to newspaper columns, allowing you to create professional-looking documents with text flowing across multiple columns.

Features

  • Multiple Column Options: Choose between 1-column (normal), 2-column, or 3-column layouts
  • Automatic Text Flow: Content flows naturally from one column to the next
  • Visual Column Dividers: Clear separation between columns with 1px borders
  • Consistent Spacing: 20px gap between columns for optimal readability
  • Element Preservation: Headings, images, tables, and paragraphs avoid breaking across columns

Using Column Layouts

Click the column buttons in the toolbar:

  • 1 Col - Single column layout (removes columns, returns to normal)
  • 2 Col - Two-column layout
  • 3 Col - Three-column layout

How It Works

When you apply a column layout:

  1. Your content is wrapped in a column container
  2. CSS multi-column properties automatically flow the text
  3. Column dividers appear between columns
  4. Elements like headings and images stay intact (no awkward breaks)

Toggling Between Layouts

You can easily switch between different column layouts:

  • Apply 2 columns to your content
  • Switch to 3 columns for more compact layout
  • Return to 1 column for normal viewing

Programmatic Usage

// Initialize editor (column support is enabled by default)
const editor = QuillKit.init('#my-editor', {
  toolbar: true,
  height: '600px'
});

// Access the column plugin
const columnPlugin = editor.pluginManager.get('column');

// Apply 2-column layout programmatically
columnPlugin.setColumnCount(2);

// Apply 3-column layout
columnPlugin.setColumnCount(3);

// Remove columns (back to single column)
columnPlugin.setColumnCount(1);

Use Cases

Column layouts are perfect for:

  • Newsletters: Create professional company newsletters
  • Magazine Articles: Design magazine-style content
  • Brochures: Marketing materials with attractive layouts
  • Academic Papers: Conference proceedings with multi-column format
  • Reports: Make long reports more readable

Technical Details

  • Uses CSS column-count, column-gap, and column-rule properties
  • Content is wrapped in containers with class atlara-column-container
  • Automatic break-inside prevention for common elements
  • Full undo/redo support
  • Compatible with page view mode

Example

const editor = new QuillKit('#my-editor', {
  toolbar: true,
  pageView: true,
  height: '600px'
});

// Columns are applied interactively via toolbar buttons
// Or programmatically using the column plugin

Demo

See the examples/column-demo.html file for a complete interactive demo showcasing all column features.

Math Support

LaTeX

Click the "TeX" button in the toolbar or use the API:

// Renders using KaTeX
// Example: E = mc^2

MathML

Click the "ML" button to insert MathML code directly:

<math>
  <mrow>
    <mi>E</mi>
    <mo>=</mo>
    <mi>m</mi>
    <msup>
      <mi>c</mi>
      <mn>2</mn>
    </msup>
  </mrow>
</math>

Configuring Math Font Size

You can set a default font size for all mathematical expressions using the mathFontSize option:

const editor = new QuillKit('#my-editor', {
  mathSupport: true,
  mathFontSize: '20pt'  // All math will render at 20pt by default
});

The mathFontSize option accepts any valid CSS font-size value:

  • Absolute sizes: '12pt', '16pt', '20pt', '24pt'
  • Relative sizes: '1.2em', '1.5em', '120%'
  • Keywords: 'larger', 'smaller' (not recommended)

Notes:

  • When mathFontSize is not specified (or set to null), math elements render at the browser's default size
  • Users can still change individual math element sizes using the Font Size dropdown in the toolbar
  • The default size only applies to newly inserted math and math loaded from content
  • Existing math elements with explicit font sizes are not overridden

Example:

// Create an editor with large math by default
const editor = new QuillKit('#scientific-doc', {
  mathSupport: true,
  mathFontSize: '24pt'  // Great for presentations
});

// Create an editor with compact math
const compactEditor = new QuillKit('#compact-doc', {
  mathSupport: true,
  mathFontSize: '12pt'  // Good for dense documentation
});

// Create an editor with proportional math sizing
const flexEditor = new QuillKit('#flex-doc', {
  mathSupport: true,
  mathFontSize: '1.5em'  // Scales with surrounding text
});

See demo-math-font-size.html for a complete working example.

Development

Build

npm run build

Run Tests

npm test

Lint Code

npm run lint

Development Mode (with watch)

npm run dev

Testing

The library includes a comprehensive test suite covering:

  • Initialization and configuration
  • Content management
  • Mode switching
  • Toolbar commands
  • History management (undo/redo)
  • Math support
  • Events and synchronization
  • CSS extraction

Run tests with:

npm test

Browser Support

QuillKit works in all modern browsers that support:

  • ES6+ JavaScript
  • ContentEditable API
  • Modern Selection API and Range API
  • DOMParser API
  • CSS Grid/Flexbox

Tested in:

  • Chrome/Edge 90+
  • Firefox 88+
  • Safari 14+

Security Considerations

QuillKit is designed to work with HTML content and allows users to edit and render HTML directly. When using this library:

  • Content Sanitization: If you're accepting content from untrusted sources, you should sanitize the HTML before passing it to the editor to prevent XSS attacks. Consider using a library like DOMPurify to sanitize user input.
  • Trusted Content: The library is best suited for environments where the content is created by trusted users (e.g., internal content management systems, personal note-taking apps).
  • Server-Side Validation: Always validate and sanitize content on the server side before storing or displaying it to other users.

Example of safe usage with DOMPurify:

import DOMPurify from 'dompurify';

const editor = new QuillKit('#my-editor');

// When loading untrusted content
const untrustedContent = getUserContent();
const cleanContent = DOMPurify.sanitize(untrustedContent);
editor.setValue(cleanContent);

// When saving content
const content = editor.getValue();
// Send to server for validation and sanitization

Examples

See the examples/index.html file for a complete demo showcasing all features.

Technical Details

Modern Selection API and Range API

QuillKit uses the modern Selection API and Range API for all text selection and manipulation operations. This ensures compatibility with current web standards and future browser versions.

The deprecated document.execCommand() API has been completely replaced with modern alternatives:

  • Text formatting (bold, italic, underline, strikethrough) uses direct DOM manipulation with Range objects
  • Block formatting uses Range-based node manipulation
  • Link and image insertion uses Range.insertNode()
  • HTML insertion uses document fragments with Range API

Known Limitations

  • Browser Dialogs: Link insertion currently uses browser prompt() dialogs. A future version may implement custom modal dialogs for better UX.

Frontend Platform

QuillKit includes a complete web application frontend that provides a professional interface for users to manage their accounts, API keys, and test the editor! The frontend offers:

Features

  • Landing Page: Modern marketing site with features, pricing, and call-to-actions
  • Authentication: Sign in, sign up, password reset, and session management
  • User Dashboard: Overview of API usage, statistics, and quick actions
  • API Key Management: Create, view, copy, and delete API keys
  • Editor Playground: Live testing environment with plan-based feature access
  • Settings & Billing: Profile management, subscription plans, and preferences
  • Responsive Design: Mobile, tablet, and desktop optimized

Quick Start

# Navigate to frontend directory
cd frontend

# Serve the application
python -m http.server 8080
# Or using Node.js
npx http-server . -p 8080

Then open http://localhost:8080 in your browser.

Documentation

  • Frontend Guide: frontend/README.md
  • Backend Integration: Configure API endpoint in frontend/js/api.js
  • Customization: Modify CSS variables in frontend/css/main.css for branding

Screenshots

See the frontend README for screenshots of the landing page, dashboard, API keys management, playground, and settings.

Backend API

QuillKit also includes a complete backend API system for productization and distribution! The backend provides:

Features

  • API Key Management: Create, manage, and track API keys with usage limits
  • Subscription Plans: Four-tier system (Free, Basic, Pro, Enterprise) with progressive features
  • Feature Access Control: Control which editor features are available based on subscription
  • Payment Integration: Stripe-hosted checkout pages for secure payments
    • NEW: Pre-configured Stripe Products/Prices (recommended approach)
    • See STRIPE_SETUP.md for detailed setup instructions
    • See MIGRATION_GUIDE.md if upgrading from older version
  • Usage Tracking: Monitor API usage and enforce limits
  • Webhook Support: Automatic handling of Stripe payment events
  • Admin Panel: Comprehensive admin dashboard for managing users, viewing statistics, and controlling subscriptions

Quick Start

# Navigate to backend directory
cd backend

# Install dependencies
npm install

# Configure environment
cp .env.example .env
# Edit .env with your configuration

# Start the server
npm start

The server will start on http://localhost:3000

Demo Pages Configuration

All demo pages included in the repository can automatically use an API key from an environment variable:

  1. Set the ATLARA_DEMO_API_KEY environment variable in your .env file:

    ATLARA_DEMO_API_KEY=ak_your_api_key_here
  2. The demo-api-key.js file automatically loads this key from the environment variable or meta tags

  3. All demo HTML files (in root and examples/ directory) are configured to use this environment variable via window.QUILLKIT_DEMO_CONFIG?.apiKey or window.ATLARA_DEMO_API_KEY

This makes it easy to run demo pages without manually entering API keys each time. The API key should be obtained from the QuillKit service.

HTML Template System

All demo and example pages use inline templates for consistent headers and footers:

  • Shared Header: Includes Google Tag Manager (GTM) scripts for analytics (Google Ads and Google Analytics)
  • Shared Footer: Consistent copyright and branding
  • Template Location: templates/ directory (header.html and footer.html)
  • Implementation: Templates are inlined directly into HTML files to avoid MIME type issues

The header and footer content from templates/header.html and templates/footer.html is embedded directly in each page's HTML. This approach:

  • Eliminates MIME type errors from dynamic script loading
  • Ensures templates work in all deployment environments
  • Maintains consistency across all demo and frontend pages

For more details, see templates/README.md.

API Endpoints

| Endpoint | Description | |----------|-------------| | POST /api/keys | Create a new API key | | GET /api/keys | List all API keys | | GET /api/subscriptions | Get subscription details | | GET /api/subscriptions/plans | View available plans | | POST /api/payments/checkout | Create Stripe checkout session |

Subscription Plans

  • Free: Basic editor, HTML mode (1K API calls/month)
  • Basic: + Rich text, toolbar (10K API calls/month) - $9/mo
  • Pro: + Math, tables, images (100K API calls/month) - $29/mo
  • Enterprise: + Custom plugins, unlimited API calls - $99/mo

Documentation

Integration Example

// Create an API key
const response = await fetch('http://localhost:3000/api/keys', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    name: 'My App',
    userId: 'user_123',
    plan: 'pro'
  })
});

const { data } = await response.json();
const apiKey = data.key;

// Use the API key
const editor = QuillKit.init('#editor', {
  apiKey: apiKey,
  // Features will be automatically enabled based on plan
});

Future Enhancements

Potential improvements for future versions:

Editor:

  • Custom modal dialog for link insertion (images and math already have custom modals)
  • Drag-and-drop image upload with file handling
  • Image cropping and editing tools
  • More comprehensive CSS editing with syntax highlighting
  • Export to PDF or Word formats
  • Collaborative editing support
  • Webpack code splitting for dynamic plugin loading

Frontend Platform:

  • Two-factor authentication
  • Email verification
  • Team/organization management
  • Usage analytics dashboard with charts
  • Webhook management UI
  • API documentation viewer
  • Dark mode theme
  • Internationalization (i18n)
  • Mobile app (React Native/Flutter)

CI/CD

This project uses GitHub Actions for continuous integration and deployment:

Continuous Integration (CI)

The CI workflow runs on every push and pull request to main and develop branches:

  • Linting: Checks code style with ESLint
  • Testing: Runs the full test suite with Jest
  • Building: Builds the production bundle with Webpack
  • Multi-version Testing: Tests against Node.js 16.x, 18.x, and 20.x
  • Coverage: Uploads code coverage to Codecov (optional)
  • Artifacts: Stores build artifacts for 7 days

NPM Publishing

The NPM publish workflow automatically publishes the package to the public NPM registry:

  • Triggers: Runs on every push to the main branch
  • Pre-publish Checks: Runs linting, tests, and build before publishing
  • Version Check: Automatically checks if the version already exists on NPM and only publishes new versions
  • Registry: Publishes to npmjs.com
  • Provenance: Uses NPM provenance for supply chain security
  • Requirements: Requires NPM_TOKEN secret to be configured in repository settings

Docker Build and Push

The Docker workflow automatically builds and publishes Docker images to GitHub Container Registry:

  • Triggers: Runs on pushes to main, version tags (v*), releases, and manual dispatch
  • Multi-platform: Builds for both linux/amd64 and linux/arm64
  • Caching: Uses GitHub Actions cache for faster builds
  • Tagging: Automatically tags images with version numbers, branch names, and latest
  • Registry: Publishes to ghcr.io/atlarafirm/quillkit

Using the Docker Image

Pull and run the latest Docker image:

docker pull ghcr.io/atlarafirm/quillkit:latest
docker run -p 8080:80 ghcr.io/atlarafirm/quillkit:latest

Then open http://localhost:8080/examples/ in your browser to see the demo.

License

MIT

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Development Setup

  1. Clone the repository
  2. Install dependencies: npm install
  3. Run tests: npm test
  4. Build: npm run build
  5. Run development server: npm run dev

CI/CD Requirements

  • All pull requests must pass CI checks (linting, tests, build)
  • Code coverage should be maintained or improved
  • Docker builds are automatically triggered on merges to main
  • NPM publishing is automatically triggered on merges to main (only if version has changed)
  • Update package version in package.json before merging to main to publish a new version