Skip to main content

Content Formatting

The Formatter is Editor42's engine for applying, removing, and querying rich-text formats. It replaces the browser's inconsistent document.execCommand with a reliable, extensible API that works identically across all browsers.

Every editor instance exposes the Formatter via editor.formatter. Use it to register custom formats, apply them to selections or nodes, check whether a format is active, and react to format changes in real time.

editor42.init({
selector: '#my-editor',
setup: (editor) => {
editor.on('init', () => {
// Register a custom format
editor.formatter.register('highlight', {
inline: 'span',
styles: { 'background-color': '#ff0' }
});

// Apply it to the current selection
editor.formatter.apply('highlight');
});
}
});

Registering Custom Formats

Use register to add new formats and unregister to remove them. Formats can target inline elements, block elements, or match existing elements via CSS selectors.

// Register a single format
editor.formatter.register('customCode', {
inline: 'code',
styles: { 'font-family': 'monospace', 'background-color': '#f4f4f4' }
});

// Register multiple formats at once
editor.formatter.register({
note: { block: 'p', classes: 'note' },
warning: { block: 'div', classes: 'warning', wrapper: true }
});

// Check if a format exists
if (editor.formatter.has('customCode')) {
console.log('customCode format is registered');
}

// Retrieve a registered format
const fmt = editor.formatter.get('customCode');

// Remove a format from the registry
editor.formatter.unregister('customCode');

Applying and Removing Formats

Once registered, formats can be applied to the current selection, toggled on and off, or explicitly removed.

// Apply bold to the current selection
editor.formatter.apply('bold');

// Apply a format with variables (e.g. a color)
editor.formatter.apply('forecolor', { value: '#e03e2d' });

// Apply a format to a specific node
editor.formatter.apply('bold', {}, someNode);

// Remove a format from the current selection
editor.formatter.remove('bold');

// Remove with the "similar" flag — removes formats
// that are similar but not an exact variable match
editor.formatter.remove('forecolor', { value: '#e03e2d' }, null, true);

// Toggle a format on or off depending on current state
editor.formatter.toggle('bold');
editor.formatter.toggle('italic');

Querying Formats

The Formatter provides several methods for checking whether formats are active on the current selection or on specific nodes.

// Check if bold is active on the current selection
const isBold = editor.formatter.match('bold');

// Check if a specific color is active
const isRed = editor.formatter.match('forecolor', { value: '#e03e2d' });

// Find all active formats from a list
const active = editor.formatter.matchAll(['bold', 'italic', 'underline']);
// e.g. ['bold', 'italic']

// Find the closest matching format from a set
const closest = editor.formatter.closest(['h1', 'h2', 'h3', 'p']);
// e.g. 'h2'

// Check a specific node
const fmt = editor.formatter.matchNode(someNode, 'bold');
if (fmt) {
console.log('Node matches bold format');
}

// Check if a format can be applied to the current selection
if (editor.formatter.canApply('bold')) {
console.log('Bold can be applied here');
}

Observing Format Changes

Use formatChanged to run a callback whenever the current selection enters or leaves a formatted region. The names parameter accepts a comma-separated list of format names.

// React when bold or italic state changes
const watcher = editor.formatter.formatChanged('bold,italic', (active, args) => {
console.log(`Format "${args.format}" is now ${active ? 'on' : 'off'}`);
});

// Stop observing
watcher.unbind();

API Reference

MethodSignatureReturnsDescription
getget(name?: string)Array | ObjectReturns the format by name, or all registered formats if no name is specified.
hashas(name: string)booleanReturns whether a format is registered for the given name.
registerregister(name: string | object, format?: object | array)Registers a format by name. Pass an object as the first argument to register multiple formats at once.
unregisterunregister(name: string)Unregisters a format by name.
applyapply(name: string, vars?: FormatVars, node?: Node | RangeLikeObject | null)Applies the named format to the current selection or specified node.
removeremove(name: string, vars?: FormatVars, node?: Node | Range, similar?: boolean)Removes the named format from the current selection or specified node.
toggletoggle(name: string, vars?: FormatVars, node?: Node)Toggles the named format on or off.
matchmatch(name: string, vars?: FormatVars, node?: Node, similar?: boolean)booleanReturns whether the current selection or specified node matches the named format.
closestclosest(names: string[])string | nullReturns the closest matching format name from the given array, or null.
matchAllmatchAll(names: string[], vars?: FormatVars)string[]Returns the subset of format names that match the current selection.
matchNodematchNode(node: Node | null, name: string, vars?: FormatVars, similar?: boolean)Format | undefinedReturns the format object if the node matches the named format, or undefined.
canApplycanApply(name: string)booleanReturns whether the named format can be applied to the current selection.
formatChangedformatChanged(names: string, callback: FormatChangeCallback, similar?: boolean, vars?: FormatVars){ unbind: () => void }Calls the callback when the selection enters or leaves the specified formats. Returns an object with an unbind method.
getCssTextgetCssText(format: string | ApplyFormat)stringReturns a preview CSS text string for the format. Useful for rendering format previews in UI elements.

Format Specification

A format is a plain object describing how an element should be created, matched, or removed. There are three primary format types — inline, block, and selector — determined by which top-level property you set.

PropertyTypeDescription
inlinestringInline element to produce (e.g. 'span', 'b', 'i', 'code').
blockstringBlock element to produce (e.g. 'h1', 'p', 'div', 'blockquote').
selectorstringCSS selector to match existing elements instead of creating new ones.
stylesobjectCSS styles to apply as key/value pairs (e.g. { 'color': '#f00' }).
attributesobjectHTML attributes to set as key/value pairs (e.g. { 'title': 'Note' }).
classesstring | string[]CSS class names to add to the element.
wrapperbooleanWhether the format wraps content in a new container element.
removestringControls removal behavior: 'none', 'empty', or 'all'.
exactbooleanRequire an exact match of styles/classes/attributes for removal.

Examples

// Inline format — wraps selection in a styled <span>
editor.formatter.register('highlight', {
inline: 'span',
styles: { 'background-color': '#ff0' }
});

// Block format — converts paragraph to <h2>
editor.formatter.register('heading2', {
block: 'h2'
});

// Selector format — applies a class to an existing <p>
editor.formatter.register('intro', {
selector: 'p',
classes: 'intro'
});

// Format with attributes and exact matching
editor.formatter.register('langSpan', {
inline: 'span',
attributes: { 'lang': '%value' },
exact: true
});
editor.formatter.apply('langSpan', { value: 'fr' });