Editor API
Single public API: Editor + plugins on a virtual document kernel. The kernel model is JSON (getJSON / setJSON). For app integrate / persist, prefer HTML (getHTML / setHTML) or Markdown (getMarkdown / setMarkdown) — see Integrate.
import 'on-codemerge/index.css';
import 'on-codemerge/public.css';
import { Editor, createDefaultPlugins, insertText } from 'on-codemerge';
const editor = new Editor(document.getElementById('editor')!, {
plugins: createDefaultPlugins(),
});
editor.run(insertText('Hello'));Getting Started
This page is the WYSIWYG Editor API. Launch snippets for all three products (WYSIWYG / JSON / Markdown): Editors and the home Getting Started.
- Install
on-codemerge - Import
index.css+public.css - Construct
Editor(host, { plugins: [...] }) - Load / save with
setHTML/getHTML(or Markdown). UsegetJSON/setJSONwhen you need the kernel snapshot.
import { Editor, ToolbarPlugin, AlignmentPlugin, ListsPlugin } from 'on-codemerge';
const editor = new Editor(host, {
plugins: [ToolbarPlugin(), AlignmentPlugin(), ListsPlugin()],
});
editor.setHTML(localStorage.getItem('doc-html') ?? '<p></p>');
editor.on('docChanged', () => {
localStorage.setItem('doc-html', editor.getHTML());
});
editor.command('bulletList');Core owns UI
- Toolbar panel is created by the editor (
editor.toolbar.add) - Popups:
editor.ui.popup/ pluginctx.popup - Context menus:
editor.ui.menu - Toasts:
editor.notify(...) - i18n:
editor.t/editor.setLocale/editor.registerLocale
Plugins never own the panel or reinvent modals. Authoring surface: SDK reference.
Options
| Option | Role |
|---|---|
plugins | Plugin factories (XPlugin() / createDefaultPlugins()) |
doc | Initial DocNode / JSON doc |
history | { maxDepth?, mergeWindowMs? } |
locale / fallbackLocale / messages | i18n bootstrap |
colorScheme | host (default — leave <html class="dark"> alone) or system (sync prefers-color-scheme to documentElement) |
chrome | bar (default sticky chrome) or page (popup toolbar) — see Chrome & host |
toolbar | { menus?: ToolbarMenuDef[] } — overflow dropdowns. Omit → Insert / Review / Tools. { menus: [] } → flat bar |
Document API
| Method | Role |
|---|---|
getJSON() / setJSON(doc) | Kernel document (collab / advanced sync) |
getHTML() / setHTML(html) | Usual app load/save (semantic HTML; atoms as empty data-node shells) |
getMarkdown() / setMarkdown(md) | Markdown load/save (CommonMark/GFM subset) |
getPublishedHTML() | Hydrated HTML for published pages (plugin publish.render fills atoms) |
getPublishedJS() | dist/public.js href when runtimes are needed; otherwise null |
getPublishedDocument() | Standalone HTML document (public.css + optional public.js) |
run(command) | Execute a command function |
command(name, …args) | Named plugin/core command |
use(plugin) | Register a plugin after construct |
on('docChanged' | 'selectionChanged', cb) | Subscriptions — callback receives editor state |
destroy() | Tear down editor + plugins |
Boundaries: JSON vs HTML vs Markdown vs published
const html = editor.getHTML();
editor.setHTML(html);
const md = editor.getMarkdown();
editor.setMarkdown('# Title\n\nHello **world**');
const json = editor.getJSON(); // optional kernel snapshot
editor.setJSON(json);
const published = editor.getPublishedHTML();
const page = editor.getPublishedDocument();| Format | Use when |
|---|---|
getHTML / setHTML | Default app persistence, paste, SSR shells |
| Markdown | Notes apps, CMS that store MD, ExportPlugin → .md |
| JSON | Collab, advanced sync, undo internals |
getPublished* | Public pages, export HTML/PDF, live preview with public.js runtimes |
Atoms (timer, calendar, …) stay as data-node="…" + attrs in semantic HTML. Published HTML runs each plugin’s publish.render and may set data-ocm-runtime / data-ocm-config for dist/public.js.
Headless IO (no Editor instance)
Same adapters the editor uses, exported from the package root:
import {
importHTML,
exportHTML,
exportPublishedHTML,
importMarkdown,
exportMarkdown,
docToMarkdown,
markdownToDoc,
sanitizeHTML,
serializeJSON,
parseJSON,
} from 'on-codemerge';
const doc = importMarkdown('# Hi');
const md = exportMarkdown(doc);
const html = exportHTML(doc);exportPublishedHTML(doc, publishers) needs the publish-node map from plugins (collectPublishNodes in the SDK) — prefer editor.getPublishedHTML() when an editor exists.
Plugin System
Plugins are factory functions that return a sealed plugin descriptor (definePlugin). Pass them in the constructor:
import { Editor } from 'on-codemerge';
import { TablePlugin, ImagePlugin } from 'on-codemerge/plugins';
const editor = new Editor(host, {
plugins: [TablePlugin(), ImagePlugin()],
});To author a plugin, see Authoring plugins and the SDK reference.
Localization
UI copy uses semantic nested keys via @i18n-micro/runtime. Editor core ships shared namespaces (common.*, toolbar.*, …) under packages/editor/src/i18n/locales/. Large plugins ship their own packs under plugins/<Name>Plugin/i18n/locales/ and merge them via wirePluginLocales / registerLocale — only the current non-en locale chunk loads asynchronously.
await editor.setLocale('ru');
await editor.setLocale('en'); // same API
editor.t('toolbar.bold');
editor.t('greeting', { name: 'Ada' });
editor.listLocales();
// Merge overlay (does not skip core locale load):
editor.registerLocale('ru', { myPlugin: { title: 'Заголовок' } });registerLocale merges messages without marking the locale as base-loaded. Plugin packs register an overlay loader so setLocale awaits them after the core JSON. Missing keys fall back to fallbackLocale (en), then the key string.
LanguagePlugin is optional UI for picking a language; loading does not depend on it.
Related
- SDK reference —
on-codemerge/sdkpublic surface - Authoring plugins — definePlugin, toolbar menus, portals, publish
- Document model
- Migration v1 → v2
- Integrate — framework-specific setups
- Chrome & host —
chrome+ hosting / portals - Export plugin — UI menu over the same boundaries