Documentation

OllowEditor

A clean, reusable, lightweight JavaScript rich-text editor built with plain HTML, CSS, and JavaScript. OllowEditor is designed for newsroom-style writing, blog publishing, CMS forms, article editors, and admin dashboards.

Works with a normal <textarea> Zero framework requirement HTML output stays synced for backend forms

Introduction

OllowEditor attaches to a regular <textarea>, replaces it with a full editor interface, and keeps the textarea value updated with sanitized HTML. That makes it practical for Django, Laravel, Rails, Express, FastAPI, WordPress admin pages, static forms, or any custom CMS.

Global API: the editor is exposed as both OllowEditor and NationWireEditor.

Features

Writing and Formatting

  • Paragraph and heading support
  • Bold, italic, underline, strikethrough
  • Links, bookmarks, emoji, special characters
  • Find and replace, source / HTML mode

Blocks and Media

  • Images, galleries, YouTube embeds
  • Code blocks and tables
  • Related blocks, fact boxes, attachments
  • Media alignment and resize controls

Import and Export

  • Markdown import and export
  • HTML export and PDF export
  • DOCX import and DOCX fallback export
  • Synced HTML for normal form submission

Project Structure

olloweditor/
├── ollow.html
├── ollow.css
├── ollow.js
└── README.md

Quick Start

Open the demo directly in your browser or serve the project locally.

cd /home/jaki/Dev/olloweditor
xdg-open ollow.html
python3 -m http.server 8000
http://localhost:8000/ollow.html

Installation

Include the editor stylesheet and script, then initialize the editor after the DOM is ready.

<link rel="stylesheet" href="ollow.css" />
<script src="ollow.js"></script>

Basic Usage

Add a textarea, optionally define theme behavior, and initialize the editor with JavaScript.

<textarea id="ollo-editor" name="content" data-theme="dark" data-persist-theme="true"></textarea>
<script>
  document.addEventListener("DOMContentLoaded", function () {
    OllowEditor.init("#ollo-editor", {
      theme: "dark",
      persistTheme: true
    });
  });
</script>

Theme can be set to light, dark, or auto. Plugins can also be registered globally before initialization.

Example Form

The editor keeps the original textarea synchronized, so standard form submission still works.

<form method="post">
  <textarea id="ollo-editor" name="body">
    <h2>Article title</h2>
    <p>Start writing your story...</p>
  </textarea>

  <button type="submit">Save Article</button>
</form>

<link rel="stylesheet" href="ollow.css" />
<script src="ollow.js"></script>
<script>
  document.addEventListener("DOMContentLoaded", function () {
    OllowEditor.init("#ollo-editor");
  });
</script>

Toolbar Overview

OllowEditor supports a broad set of toolbar actions for writing, editing, media, and export workflows.

Feature Description
Undo / RedoRevert or restore changes
Font Family / Font SizeApply approved typography controls
Paragraph / H2 / H3 / H4Switch block type
Bold / Italic / UnderlineFormat selected text
Link / Unlink / BookmarkCreate hyperlinks and internal anchors
Find / Replace / HTMLSearch, replace, or toggle source mode
Lists / Pull QuoteInsert structural content blocks
Image / Gallery / Embed / Table / CodeInsert media and structured blocks
Import MD / Export MD / Export HTML / Export PDF / Import DOCX / Export DOCXRun import and export workflows

Responsive Toolbars

OllowEditor changes its interaction layer based on viewport width without changing the feature set.

  • Desktop menu bar: visible from 1024px and above with File, Edit, View, Insert, Format, Tools, and Help.
  • Tablet toolbar: compact grouped mode between roughly 640px and 1024px.
  • Mobile toolbar: compact top row plus a bottom-sheet More drawer at 480px and below.
  • Overflow system: low-frequency actions move into responsive overflow menus instead of forcing page-level overflow.

Keyboard Shortcuts

Shortcuts run only while the editor body is focused and are disabled inside modal inputs and other page form controls.

Shortcut Action
Ctrl/Cmd + BBold
Ctrl/Cmd + IItalic
Ctrl/Cmd + UUnderline
Ctrl/Cmd + KInsert or edit link
Ctrl/Cmd + Shift + 7Numbered list
Ctrl/Cmd + Shift + 8Bullet list
Ctrl/Cmd + Shift + CCode block
Ctrl/Cmd + SSync HTML and prevent browser save dialog
EscClose active modal or floating toolbar
const editor = OllowEditor.get("#ollo-editor");

editor.addShortcut("mod+shift+m", () => {
  editor.insertHTML("<p>Note</p>");
});

editor.removeShortcut("mod+shift+m");
const shortcuts = editor.getShortcuts();

Bookmarks and Anchors

The Bookmark tool inserts internal anchors for long-form documents, auto-generates safe slugs, and exposes edit, copy-link, and delete actions.

<span class="ollow-bookmark" id="economic-policy-section" data-bookmark="true" contenteditable="false">
  🔖 Economic Policy Section
</span>

Links can target bookmarks directly with href="#economic-policy-section".

Find and Replace

The editor search panel supports find, replace, match case, whole word, highlight all, and optional code block inclusion.

  • Ctrl/Cmd + F opens find
  • Ctrl/Cmd + H opens replace
  • Enter moves to the next match
  • Shift + Enter moves to the previous match
Temporary highlight spans are UI-only and are stripped before textarea sync and export.

Source / HTML Mode

Use HTML mode to switch between visual editing and raw HTML editing. All source content is sanitized before it returns to the visual surface.

  • editor.toggleSourceMode()
  • editor.enterSourceMode()
  • editor.exitSourceMode()
  • editor.isSourceMode()

Themes

OllowEditor supports light, dark, and auto themes with optional persistence through localStorage.

<textarea
  id="ollo-editor"
  name="body"
  data-ollow-editor
  data-theme="dark"
  data-persist-theme="true"></textarea>
const editor = OllowEditor.get("#ollo-editor");

editor.setTheme("light");
editor.setTheme("dark");
editor.setTheme("auto");

const theme = editor.getTheme();

Typography Controls

The main toolbar includes Microsoft Office-style controls for font family, font size, style presets, and recent font tracking.

  • Font size values are clamped between 8 and 96.
  • Unknown font classes are stripped during sanitization.
  • Saved HTML uses safe classes such as ollow-font-georgia and ollow-font-size-22.
<p>
  <span class="ollow-font-georgia ollow-font-size-22">Styled text</span>
</p>

Text Color and Highlight

Text color and highlight controls use approved classes for presets and safe hex inline styles for custom values.

<p>
  <span class="ollow-text-color-blue">Blue text</span>
  <span class="ollow-highlight-yellow">Highlighted text</span>
</p>
Only hex color values are preserved for inline color and background-color. Dynamic CSS functions are stripped.

Formatting Tools

Inline and block formatting includes style presets, strikethrough, subscript, superscript, remove formatting, and format painter.

  • Ctrl/Cmd + Shift + X toggles strikethrough.
  • Ctrl/Cmd + , applies subscript.
  • Ctrl/Cmd + . applies superscript.
  • Ctrl/Cmd + \ removes formatting from the current selection or block.
  • Double-click Format Painter to keep it armed for multiple applications.
<p>Normal <s>struck text</s> and H<sub>2</sub>O</p>

Image Upload

Images can be inserted from local files, external URLs, or backend upload endpoints configured through data attributes or JavaScript.

<textarea
  id="ollo-editor"
  name="body"
  data-ollow-editor
  data-image-upload-url="/upload/image"
  data-gallery-upload-url="/upload/gallery"
  data-attachment-upload-url="/upload/attachment">
</textarea>
OllowEditor.init("#ollo-editor", {
  upload: {
    imageUrl: "/upload/image",
    galleryUrl: "/upload/gallery",
    attachmentUrl: "/upload/attachment",
    allowFallback: false
  }
});
Upload Flow Contract
Single file{ "url": "/media/editor/images/file.jpg" }
Multiple files{ "urls": ["/media/editor/gallery/1.jpg", "/media/editor/gallery/2.jpg"] }

Drag-and-drop is also supported. Multiple dropped images retain order, and non-image files are rejected with a visible editor error.

Advanced Image Editing

Inserted images expose a floating image toolbar and an image edit modal for alignment, sizing, captions, links, alt text, and replacements.

<figure class="ollow-editor-image ollow-image-medium ollow-align-center" data-type="image">
  <a href="https://example.com" target="_blank" rel="noopener noreferrer">
    <img src="/media/example.jpg" alt="Alt text">
  </a>
  <figcaption>Caption text</figcaption>
</figure>

YouTube Embed

Supported YouTube URLs are normalized into trusted iframe embeds with lazy loading and a safe wrapper.

https://www.youtube.com/watch?v=VIDEO_ID
https://youtu.be/VIDEO_ID
https://www.youtube.com/embed/VIDEO_ID
<figure class="ollow-media ollow-embed">
  <div class="ollow-video-wrapper">
    <iframe src="https://www.youtube.com/embed/VIDEO_ID" title="YouTube video player" allowfullscreen loading="lazy"></iframe>
  </div>
  <figcaption>Video caption</figcaption>
</figure>

Code Blocks and Tables

Code blocks store escaped content in semantic HTML, and tables use a scroll container to avoid page-level overflow on smaller screens.

<figure class="ollow-editor-code" data-type="code" data-language="python">
  <figcaption>example.py</figcaption>
  <pre><code class="language-python">print("Hello")</code></pre>
</figure>
<figure class="ollow-editor-table ollow-table-bordered ollow-table-striped" data-type="table">
  <div class="ollow-editor-table-scroll">
    <table>...</table>
  </div>
  <figcaption>Table caption</figcaption>
</figure>

Export HTML and PDF

HTML export produces sanitized editor content only. PDF export creates a print-ready iframe document and relies on the browser’s native print-to-PDF flow.

const html = editor.exportHTML({
  fullDocument: true,
  includeStyles: true,
  title: "Article Export"
});

editor.exportPDF({
  title: "Article",
  pageSize: "A4",
  orientation: "portrait",
  margin: "normal"
});
OllowEditor does not generate PDF bytes directly. Use the browser print dialog and disable browser headers and footers for a clean final PDF.

DOCX Import and Export

DOCX import is client-side and uses an optional parser such as Mammoth.js. Real DOCX export requires an optional export adapter; otherwise the editor falls back to a Word-compatible HTML document.

editor.importDOCX(file, {
  mode: "replace",
  preserveFormatting: true,
  importImages: true
});

editor.exportDOCX({
  filename: "article.docx",
  title: "Article Title",
  includeImages: true,
  fallbackToDoc: true
});

Markdown Import and Export

Markdown is used for conversion workflows only. The editor still stores sanitized HTML in the hidden textarea.

const editor = OllowEditor.get("#ollo-editor");

editor.importMarkdown("## Heading\n\nParagraph text", {
  mode: "replace"
});

const markdown = editor.exportMarkdown();
  • Headings, paragraphs, links, lists, blockquotes, horizontal rules, inline code, fenced code blocks, images, and basic tables are supported.
  • Import supports replace mode and insert-at-cursor mode.

Paste Cleanup

OllowEditor cleans pasted content from Google Docs, Microsoft Word, LibreOffice, browsers, and plain text before insertion.

  • Keeps useful structure like headings, paragraphs, lists, blockquotes, tables, code, links, and safe images.
  • Removes scripts, styles, Word-specific classes, comments, event handlers, unsafe URLs, and unsupported iframes.
  • Maps pasted typography only when it matches approved OllowEditor font and size rules.
const editor = OllowEditor.get("#ollo-editor");

const cleanedHtml = editor.cleanPastedHTML(dirtyHtml);
const cleanedText = editor.cleanPlainText("Line one\n\nLine two");
const sanitized = editor.sanitizeHTML("<p>Safe HTML</p>");

Textarea Sync

The original textarea remains the source submitted with the form. OllowEditor updates it automatically whenever content changes or the form submits.

<textarea name="content"></textarea>

Plugin API

Plugins are registered globally and enabled per editor. They can add buttons, commands, events, shortcuts, and sanitizer rules.

OllowEditor.registerPlugin("alertBox", function (editor, options) {
  editor.addSanitizerRule({
    classes: ["ollow-alert-box"]
  });

  editor.addToolbarButton({
    name: "alertBox",
    label: options.label || "Alert",
    icon: "!",
    group: "blocks",
    title: "Insert alert box",
    onClick() {
      editor.insertHTML('<section class="ollow-alert-box"><p>Alert text</p></section>');
    }
  });
});
OllowEditor.init("#ollo-editor", {
  plugins: {
    alertBox: {
      label: "Alert"
    }
  }
});

Plugin-facing helpers include addToolbarButton, addToolbarGroup, addCommand, runCommand, insertHTML, openModal, getHTML, setHTML, sync, focus, and destroy.

Backend Integration

OllowEditor is backend-independent and works with Django, Laravel, Express.js, FastAPI, Rails, WordPress admin pages, static HTML forms, and custom CMS flows.

OllowEditor.init("#ollo-editor", {
  upload: {
    imageUrl: "/upload/image",
    galleryUrl: "/upload/gallery",
    attachmentUrl: "/upload/attachment",
    allowFallback: false
  }
});

const editor = OllowEditor.get("#ollo-editor");

await editor.uploadFile(file, "image");
await editor.uploadFile(file, "attachment");

Custom Styling

All editor visuals live in ollow.css. You can adapt those classes to match your own application or design system.

.ollow-editor
.ollow-toolbar
.ollow-content
.ollow-media
.ollow-image
.ollow-gallery
.ollow-gallery-grid
.ollow-embed
.ollow-video-wrapper

Browser Support

OllowEditor is designed for modern browsers.

  • Chrome
  • Edge
  • Firefox
  • Safari

Security Audit

Audit date: 2026-07-07. The current hardening focuses on unsafe HTML, script execution, unsafe URLs, inline styles, and trusted media/embed handling.

OllowEditor is hardened against common XSS and unsafe HTML injection vectors, but host applications still need server-side validation, CSP, and safe upload handling.

Audit Highlights

  • Blocked javascript:, vbscript:, protocol-relative, and unsafe data URLs.
  • Restricted image data URLs to safe bitmap MIME types only.
  • Normalized iframe embeds to trusted YouTube URLs only.
  • Removed dangerous tags like script, style, object, embed, svg, and form controls.
  • Limited inline style preservation to safe hex-based color and background-color.

Allowed URL Schemes

  • http:, https:, mailto:, tel:
  • Safe relative URLs and internal anchors such as #section-id

Host Application Recommendations

  • Authentication and authorization
  • CSRF protection for backend upload/import endpoints
  • Server-side validation and sanitization
  • Content Security Policy headers
  • Safe file upload validation and rate limiting

Roadmap

The README roadmap still lists the editor’s ongoing priorities and expected refinements.

  • Typography controls and styles dropdown
  • Advanced image and table controls
  • Find / replace and special character workflows
  • Source / HTML mode, export workflows, and DOCX import

License

This project is open for personal and commercial use. You can customize it freely for your own applications.

Author

Built for custom CMS and publishing workflows.

Ollow Editor — a lightweight reusable JavaScript editor.