Skip to main content
Batoi UIF Docs

HTML and Markdown Editors

Implement deterministic rich HTML and Markdown editing with accessible tools, diagnostics, bounded history, governed autosave, and uploads.

Version 3.0.0 Version 3 active maintenance Reviewed Aug 11, 2026 Next review Nov 11, 2026

Owner: Batoi Engineering Reviewed by: Batoi UIF Maintainers Source revision: b2f3478

Browse Batoi UIF Documentation HTML and Markdown Editors

HTML and Markdown Editors

Batoi UIF provides dependency-free rich HTML, Markdown, and plain-text editing while keeping the original form control synchronized. HTML source stays canonical in rich mode; changing to source view does not convert the document to Markdown.

Rich HTML Profile

Rich editing supports headings, paragraphs, quotes, inline formatting, nested and task lists, links, images, tables, code blocks, source view, managed history, and sanitized paste or drop input. The shared UIF sanitizer applies the supported element, attribute, and URL policy.

Markdown Profile

The practical Markdown profile supports headings, thematic breaks, blockquotes, fenced code, ordered and unordered lists, task lists, pipe tables, emphasis, links, images, autolinks, and escaped input. Raw HTML is escaped. Input, line, nesting, and table-column limits keep parsing bounded; the profile does not claim complete CommonMark or GFM conformance.

import {
  markdownDiagnostics,
  markdownToHtml,
  parseMarkdown,
  renderMarkdown
} from '/assets/batoi-uif-main/packages/editor/dist/index.js';

const documentModel = parseMarkdown(source);
const html = renderMarkdown(documentModel);
const diagnostics = markdownDiagnostics(source);

Diagnostics cover unclosed fences, escaped raw HTML, parser limits, table-width mismatches, and nesting limits. Active editors expose them through editor.diagnostics, data-uif-editor-diagnostics, and the uif:editor-diagnostics event.

Keyboard and Lifecycle Behavior

  • Toolbar controls use roving focus with Arrow, Home, and End keys.
  • Dialogs trap focus, close with Escape, and restore focus to their invoking control.
  • Tab and Shift+Tab indent lists or move between rich-table cells.
  • Undo and redo group consecutive text changes while commands, paste, drop, and composition create separate bounded transactions.
  • Form reset synchronizes the active surface, clears dirty state, and emits uif:editor-reset.
  • destroy() removes listeners, overlays, timers, pending autosave work, and upload work.
  • Motion and synchronized scrolling respect prefers-reduced-motion.

Governed Autosave and Uploads

Autosave supports CSRF tokens and headers. New edits cancel pending requests, stale responses cannot mark newer content clean, and mutation retries remain disabled unless the backend provides idempotency or replay protection.

registerEditorHook('uploadImage', async ({ file, signal }) => {
  return uploadToGovernedServer(file, { signal });
});

The server must authorize the user, validate and inspect the file, assign a safe name, store it in the correct public or private location, and return an approved URL. Browser validation and sanitization are defense in depth, not replacements for server controls.

Upload hooks receive an AbortSignal; newer work or editor destruction cancels older work. The default upload limit is 10 MiB, unsafe returned URLs are ignored, and failures emit uif:editor-upload-error.

Browser Verification

Editor selection, clipboard, composition, table behavior, content editing, and mobile layout require real-browser tests. UIF 2.1 covers Chromium, Firefox, WebKit, and a representative narrow Chromium viewport; production releases still require keyboard and assistive-technology review.

Open the Rich Editor and Markdown Editor examples for current behavior.