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.
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.
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 / Redo | Revert or restore changes |
| Font Family / Font Size | Apply approved typography controls |
| Paragraph / H2 / H3 / H4 | Switch block type |
| Bold / Italic / Underline | Format selected text |
| Link / Unlink / Bookmark | Create hyperlinks and internal anchors |
| Find / Replace / HTML | Search, replace, or toggle source mode |
| Lists / Pull Quote | Insert structural content blocks |
| Image / Gallery / Embed / Table / Code | Insert media and structured blocks |
| Import MD / Export MD / Export HTML / Export PDF / Import DOCX / Export DOCX | Run 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
1024pxand above with File, Edit, View, Insert, Format, Tools, and Help. - Tablet toolbar: compact grouped mode between roughly
640pxand1024px. - Mobile toolbar: compact top row plus a bottom-sheet
Moredrawer at480pxand 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 + B | Bold |
Ctrl/Cmd + I | Italic |
Ctrl/Cmd + U | Underline |
Ctrl/Cmd + K | Insert or edit link |
Ctrl/Cmd + Shift + 7 | Numbered list |
Ctrl/Cmd + Shift + 8 | Bullet list |
Ctrl/Cmd + Shift + C | Code block |
Ctrl/Cmd + S | Sync HTML and prevent browser save dialog |
Esc | Close 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 + Fopens findCtrl/Cmd + Hopens replaceEntermoves to the next matchShift + Entermoves to the previous match
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
8and96. - Unknown font classes are stripped during sanitization.
- Saved HTML uses safe classes such as
ollow-font-georgiaandollow-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>
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 + Xtoggles strikethrough.Ctrl/Cmd + ,applies subscript.Ctrl/Cmd + .applies superscript.Ctrl/Cmd + \removes formatting from the current selection or block.- Double-click
Format Painterto 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>
Gallery Block
Gallery blocks support multiple uploaded images and render them in a responsive grid with optional title and note.
<section class="ollow-media ollow-gallery">
<div class="ollow-gallery-header">
<h3>Gallery title</h3>
<p>Gallery note or caption</p>
</div>
<div class="ollow-gallery-grid">
<figure><img src="image-1.jpg" alt="Gallery image 1" /></figure>
<figure><img src="image-2.jpg" alt="Gallery image 2" /></figure>
</div>
</section>
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"
});
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.
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
colorandbackground-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.