Package Exports
- @waveeditor/core
- @waveeditor/core/dist/stats.html
- @waveeditor/core/dist/waveeditor.esm.js
- @waveeditor/core/dist/waveeditor.esm.js.map
- @waveeditor/core/dist/waveeditor.min.css
- @waveeditor/core/dist/waveeditor.min.js
- @waveeditor/core/dist/waveeditor.min.js.map
- @waveeditor/core/dist/waveeditor.tinymce-clone.min.css
- @waveeditor/core/package.json
Readme
🌊 WaveEditor
A self-hosted, white-labeled rich-text editor for the web. Drop-in replacement for TinyMCE — without the API key, the external CDN, or the surprise bills.
🎯 v0.9.0 — Phase 2 cut #4: polish + tinymce-clone theme (soft-launch). Everything from v0.8.0 plus visual-blocks debug toggle, markdown-shortcut marker (typing
**bold**/# h1/> bq/- list/1. listalready works via StarterKit input rules), templates/snippets (config-driven popover), and the opt-inwaveeditor.tinymce-clone.min.csstheme — link this stylesheet instead ofwaveeditor.min.cssfor a TinyMCE-7 visual match (blue accent, gray toolbar, 28px buttons). 586 unit tests + 74 e2e tests, 94 KB gzipped. Last window for breaking API changes before v1.0.0 locks the surface; seedocs/phases/phase-2.md.
What WaveEditor is
WaveEditor gives web developers a rich-text editor that is owned by the people who use it:
- ✅ Drop-in replacement for TinyMCE — public API mirrors
tinymce.init({...})so existing codebases migrate with a find-and-replace - ✅ Self-hosted — single JS + CSS pair, no external CDN, no API key, works offline and behind firewalls
- ✅ MIT-licensed open core — no GPL contagion, no recurring fees
- ✅ Brandable — full white-label support via CSS variables; ship it under your own product name
- ✅ Commercial-ready — clean separation between free core (Phases 0–3) and future paid tier (Phase 4)
Package
Published on npm as @waveeditor/core.
The unscoped waveeditor name is blocked by npm's anti-typosquatting policy (similarity to the unrelated wangeditor package), so we use the @waveeditor org scope — same convention as TipTap (@tiptap/core), Lexical (@lexical/core), CKEditor 5 (@ckeditor/*). Brand identity stays "WaveEditor" everywhere except the install command.
Quick start
Via npm
npm install @waveeditor/coreimport { WaveEditor } from '@waveeditor/core';
import '@waveeditor/core/dist/waveeditor.min.css';
WaveEditor.init({
selector: '#editor',
plugins:
'undo redo bold italic underline strikethrough subscript superscript ' +
'heading blockquote bullet-list ordered-list indent outdent ' +
'align-left align-center align-right align-justify ' +
'link unlink image clear-formatting horizontal-rule ' +
'source-view fullscreen word-count clipboard',
toolbar:
'undo redo | bold italic underline strikethrough | ' +
'heading blockquote | bullet-list ordered-list indent outdent | ' +
'align-left align-center align-right align-justify | ' +
'link unlink image | source-view fullscreen',
});Via CDN (drop-in, no build step)
<link rel="stylesheet" href="https://unpkg.com/@waveeditor/core/dist/waveeditor.min.css">
<script src="https://unpkg.com/@waveeditor/core/dist/waveeditor.min.js"></script>For a TinyMCE-7 visual match (smaller buttons, lighter toolbar, TinyMCE blue accent), swap the stylesheet — JS is unchanged:
<link rel="stylesheet" href="https://unpkg.com/@waveeditor/core/dist/waveeditor.tinymce-clone.min.css">
<div id="editor"></div>
<script>
WaveEditor.init({
selector: '#editor',
plugins: 'bold italic link image bullet-list',
toolbar: 'bold italic | link image | bullet-list',
});
</script>Identical pattern to TinyMCE. Same config string format. Just tinymce.init → WaveEditor.init.
Currently shipped (through v0.9.0)
| Category | Features |
|---|---|
| Marks | bold · italic · underline · strikethrough · subscript · superscript · code |
| Typography (v0.7.0) | font-family · font-size · font-color · highlight · line-height |
| Blocks | heading (paragraph / H1–H6 dropdown) · blockquote · preformatted · bullet-list · ordered-list · horizontal-rule |
| Code blocks (v0.7.0) | code-block — Auto-detect + Plain + 12 languages (Bash / CSS / HTML / JS / JSON / Markdown / PHP / Python / SQL / TS / XML / YAML) via lowlight |
| Tables (v0.6.0) | table · table-ops (row + col ops, merge / split, toggle header, delete) · column resize · table-cell-color (shared picker since v0.7.0) · table-cell-border |
| Alignment | align-left · align-center · align-right · align-justify (paragraphs + headings) |
| Operations | undo · redo · indent · outdent (lists) · clear-formatting · page-break · date-time (5 formats) |
| Editing aids (v0.8.0) | anchor (named jump target) · search-replace (decoration highlights + prev / next / replace / replace-all + case / whole-word) · charmap (~115 special characters with live search) · emoji (8 categories + search + recents) |
| Workflow (v0.9.0) | templates (config-driven snippet popover) · markdown-shortcuts (StarterKit input rules) · visual-blocks (debug-overlay toggle) |
| Dialogs | link (insert / edit / autoprefix https:// / new-tab / autolink on type) · unlink · image (Upload / URL, drag-drop + paste, server upload via images_upload_url / images_upload_handler; v0.7.0 adds resize / align / caption / alt via a floating bubble) · media (YouTube / Vimeo auto-detect + configurable iframe allowlist) |
| Editor modes | source-view (HTML edit) · fullscreen (ESC exits) · word-count (debounced status bar) · autosave (v0.8.0) (debounced localStorage save + restore prompt + "Saved · HH:MM" indicator) |
| Security | clipboard (strips <script>, <iframe>, inline on*= handlers, javascript: URLs on paste) · paste-from-word (v0.8.0) (7-stage MSO scrub + pseudo-list recovery) · media_allowlist rejects clickjacking-prone iframe sources |
| Drag & drop | image (file → upload pipeline) · drag-drop (v0.8.0) (text / html / .txt with drop-zone outline) |
| TinyMCE aliases | numlist → ordered-list, bullist → bullet-list, alignleft → align-left, etc. |
See docs/api.md for the full public API reference and docs/plugins.md for writing custom plugins.
Examples
HTML demos in examples/ that you can open via npm run dev:
examples/basic.html— minimal hello-world drop-in (Phase 0 baseline)examples/full-toolbar.html— every currently-shipped featureexamples/phase-1-preview.html— Phase 1 frozen snapshotexamples/phase-2-preview.html— Phase 2 in-progress delivery recordexamples/tinymce-migration.html— TinyMCE and WaveEditor side-by-side, identical config strings (§1.16.2)examples/docs.html— designed developer guide with live demo
Testing
npm test # 586 unit tests
npm run e2e # Playwright e2e — 25 specs × chromium / firefox / webkit
npm run build # produces dist/ — waveeditor.min.{js,css} (94 KB / 5 KB gz)
# + waveeditor.tinymce-clone.min.css (5.5 KB gz)
npm run license:audit # fails on GPL/AGPL/SSPLRoadmap
| Phase | Theme | Status | Plan |
|---|---|---|---|
| P0 | Project bootstrap | ✅ Done · v0.0.1 | phase-0.md |
| P1 | Core formatting (bold, italic, lists, links, images, …) | ✅ Done · v0.5.0 | phase-1.md |
| P2 | Advanced editing (tables, fonts, colors, code blocks, …) | 🚧 Soft-launch · v0.6.0 (tables) · v0.7.0 (typography + color + code + media) · v0.8.0 (editing aids + paste + autosave) · v0.9.0 (polish + tinymce-clone theme) · v1.0.0 after one real Aquasafe migration | phase-2.md |
| P3 | Power features (track changes, comments, mentions, slash commands, …) | Planned | phase-3.md |
| P4 | Backend-dependent (real-time collab, AI, asset manager, …) | Planned | phase-4.md |
Documentation
| Doc | Purpose |
|---|---|
docs/usage.md |
Start here. Recipe-style developer guide: installation, configuration, image upload, theming, TinyMCE migration |
docs/api.md |
Public API reference — WaveEditor.init, get, remove, use, plugin shapes |
docs/plugins.md |
Plugin authoring guide with worked examples |
docs/design.md |
Architecture, public API, mission & vision, licensing strategy |
docs/visual-design.md |
Complete visual language: colors, typography, components, states, dark mode |
docs/mockups/ |
Seven interactive HTML mockups capturing every visual decision |
docs/phases/ |
Detailed implementation plans per phase |
CLAUDE.md |
Project rules for AI agents working in this repo |
Built on
- TipTap — editor engine (MIT)
- ProseMirror — underlying document model (MIT)
- Tabler Icons — icon set (MIT)
- Inter — chrome typeface (OFL)
- JetBrains Mono — monospace typeface (OFL)
Full third-party attributions: NOTICES.md.
Contributing
See CONTRIBUTING.md for the contribution workflow. The architecture rules and project conventions live in CLAUDE.md.
Security
Found a vulnerability? See SECURITY.md for the responsible disclosure process.
License
MIT — © 2026 Manish Patolia.
WaveEditor is built on MIT-licensed open-source components and is itself MIT-licensed. Commercial premium features (Phase 4+) may be offered under a dual-license model in the future; see docs/design.md §16.