Remove format feature for CKEditor 5 that strips formatting from selected text while preserving content.
npx @tessl/cli install tessl/npm-ckeditor--ckeditor5-remove-format@46.0.0CKEditor 5 Remove Format is a plugin that provides text formatting removal functionality for CKEditor 5. It allows users to clear formatting from selected text or content, removing styles like bold, italic, colors, fonts, and other text decorations while preserving the underlying text content.
npm install @ckeditor/ckeditor5-remove-format or npm install ckeditor5 (included in main package)import { RemoveFormat } from "@ckeditor/ckeditor5-remove-format";For CommonJS:
const { RemoveFormat } = require("@ckeditor/ckeditor5-remove-format");Individual component imports:
import {
RemoveFormat,
RemoveFormatEditing,
RemoveFormatUI,
RemoveFormatCommand,
type IsFormattingCallback,
type RemoveFormattingCallback
} from "@ckeditor/ckeditor5-remove-format";UI and Icon imports (typically used internally):
import { IconRemoveFormat } from "ckeditor5/src/icons.js";
import { ButtonView, MenuBarMenuListItemButtonView } from "ckeditor5/src/ui.js";import { ClassicEditor } from "@ckeditor/ckeditor5-editor-classic";
import { RemoveFormat } from "@ckeditor/ckeditor5-remove-format";
ClassicEditor
.create(document.querySelector('#editor'), {
plugins: [RemoveFormat, /* other plugins */],
toolbar: ['removeFormat', /* other tools */]
})
.then(editor => {
// Execute remove format command programmatically
editor.execute('removeFormat');
});The Remove Format plugin follows CKEditor 5's plugin architecture pattern:
The primary plugin class that loads all required components.
/**
* The remove format plugin that combines editing and UI functionality
*/
class RemoveFormat extends Plugin {
/** Required plugins that must be loaded */
static get requires(): [typeof RemoveFormatEditing, typeof RemoveFormatUI];
/** Plugin identifier used by CKEditor 5 */
static get pluginName(): 'RemoveFormat';
/** Flag indicating this is an official CKEditor 5 plugin */
static override get isOfficialPlugin(): true;
}Handles the core editing functionality and registers the remove format command.
/**
* The remove format editing plugin that registers the removeFormat command
*/
class RemoveFormatEditing extends Plugin {
/** Plugin identifier used by CKEditor 5 */
static get pluginName(): 'RemoveFormatEditing';
/** Flag indicating this is an official CKEditor 5 plugin */
static override get isOfficialPlugin(): true;
/** Initializes the plugin and registers the removeFormat command */
init(): void;
}Provides user interface components for the remove format functionality.
/**
* The remove format UI plugin that registers toolbar and menu bar buttons
*/
class RemoveFormatUI extends Plugin {
/** Plugin identifier used by CKEditor 5 */
static get pluginName(): 'RemoveFormatUI';
/** Flag indicating this is an official CKEditor 5 plugin */
static override get isOfficialPlugin(): true;
/** Initializes UI components and registers them with component factory */
init(): void;
}The core command that handles formatting removal from selected content.
/**
* The remove format command that removes formatting from the current selection
*/
class RemoveFormatCommand extends Command {
/** Command value indicating if formatting is available to remove */
declare public value: boolean;
/** Updates command state based on current selection */
override refresh(): void;
/** Removes formatting from current selection */
override execute(): void;
/**
* Registers custom attribute handlers for specialized formatting removal
* @internal
*/
registerCustomAttribute(
isFormatting: IsFormattingCallback,
removeFormatting: RemoveFormattingCallback
): void;
}Execute the remove format command programmatically:
// Basic command execution
editor.execute('removeFormat');
// Access the command instance
const removeFormatCommand = editor.commands.get('removeFormat');
if (removeFormatCommand.isEnabled) {
removeFormatCommand.execute();
}Access UI components through the component factory:
// Toolbar button component
const toolbarButton = editor.ui.componentFactory.create('removeFormat');
// Menu bar item component
const menuBarItem = editor.ui.componentFactory.create('menuBar:removeFormat');The RemoveFormatUI plugin creates UI components using internal methods:
// Toolbar button creation (ButtonView)
const toolbarButton = editor.ui.componentFactory.create('removeFormat');
// Menu bar button creation (MenuBarMenuListItemButtonView)
const menuBarButton = editor.ui.componentFactory.create('menuBar:removeFormat');Both components share common properties:
{
label: 'Remove Format', // Localized text
icon: IconRemoveFormat, // Remove format icon
isEnabled: boolean, // Bound to command's isEnabled state
tooltip: true // Show tooltip on hover (toolbar button only)
}The following types are from CKEditor 5's engine module and are used in the Remove Format API:
// From @ckeditor/ckeditor5-core
type PluginConstructor = typeof Plugin;
interface CommandCollection {
// CKEditor 5 command collection
get(name: string): Command | undefined;
add(name: string, command: Command): void;
}
interface Model {
// CKEditor 5 model
document: ModelDocument;
schema: Schema;
change(callback: (writer: ModelWriter) => void): void;
createPositionAt(item: ModelItem, offset: number): ModelPosition;
}
interface ModelDocument {
// CKEditor 5 model document
selection: ModelDocumentSelection;
}
interface Editor {
// CKEditor 5 editor interface
commands: CommandCollection;
model: Model;
ui: UI;
locale: Locale;
execute(commandName: string, ...args: any[]): void;
}
interface Locale {
// CKEditor 5 locale
t(message: string): string;
}
abstract class Plugin {
// CKEditor 5 plugin base class
static readonly pluginName: string;
static readonly requires?: readonly PluginConstructor[];
static readonly isOfficialPlugin?: boolean;
readonly editor: Editor;
init?(): void;
}
abstract class Command {
// CKEditor 5 command base class
readonly editor: Editor;
value?: any;
isEnabled: boolean;
refresh(): void;
execute(...args: any[]): void;
}
// From @ckeditor/ckeditor5-engine
interface ModelItem {
// CKEditor 5 model item (element or text node)
getAttributes(): Iterable<[string, any]>;
is(type: string): boolean;
}
interface Schema {
// CKEditor 5 schema
getAttributeProperties(attributeName: string): AttributeProperties | undefined;
isBlock(item: ModelItem): boolean;
setAttributeProperties(attributeName: string, properties: AttributeProperties): void;
}
interface AttributeProperties {
// CKEditor 5 attribute properties
isFormatting?: boolean;
}
interface ModelElement extends ModelItem {
// CKEditor 5 model element
}
interface ModelDocumentSelection {
// CKEditor 5 model document selection
getAttributes(): Iterable<[string, any]>;
getRanges(): Iterable<ModelRange>;
getSelectedBlocks(): Iterable<ModelElement>;
}
interface ModelRange {
// CKEditor 5 model range
getItems(): Iterable<ModelItem>;
end: ModelPosition;
}
interface ModelPosition {
// CKEditor 5 model position
isTouching(position: ModelPosition): boolean;
}
interface ModelWriter {
// CKEditor 5 model writer
removeAttribute(key: string, itemOrRange: ModelItem | ModelRange): void;
removeSelectionAttribute(key: string): void;
createRangeOn(item: ModelItem): ModelRange;
}
// From @ckeditor/ckeditor5-ui
interface ComponentFactory {
// CKEditor 5 UI component factory
add(name: string, callback: () => any): void;
create(name: string): any;
}
interface UI {
// CKEditor 5 UI
componentFactory: ComponentFactory;
}
abstract class ButtonView {
// CKEditor 5 button view base class
set(properties: Partial<ButtonViewProperties>): void;
bind(property: string): Binding;
}
abstract class MenuBarMenuListItemButtonView {
// CKEditor 5 menu bar button view class
set(properties: Partial<ButtonViewProperties>): void;
bind(property: string): Binding;
}
interface ButtonViewProperties {
label?: string;
icon?: string;
tooltip?: boolean;
isEnabled?: boolean;
}
interface Binding {
to(observable: any, ...properties: string[]): void;
}
// From @ckeditor/ckeditor5-utils
function first<T>(iterable: Iterable<T>): T | null;/**
* Callback that checks if an attribute is a formatting attribute
* @internal
*/
type IsFormattingCallback = (
attributeName: string,
item: ModelItem | ModelDocumentSelection
) => boolean;
/**
* Callback that removes formatting from an item
* @internal
*/
type RemoveFormattingCallback = (
attributeName: string,
range: ModelRange,
writer: ModelWriter
) => void;The plugin extends CKEditor 5's core interfaces:
// Extended interfaces (automatically registered by the plugin)
interface PluginsMap {
'RemoveFormat': RemoveFormat;
'RemoveFormatUI': RemoveFormatUI;
'RemoveFormatEditing': RemoveFormatEditing;
}
interface CommandsMap {
removeFormat: RemoveFormatCommand;
}For specialized formatting removal, you can register custom attribute handlers:
const removeFormatCommand = editor.commands.get('removeFormat');
// Register custom formatting attribute handler
removeFormatCommand.registerCustomAttribute(
// Check if attribute is custom formatting
(attributeName, item) => {
return attributeName.startsWith('custom-');
},
// Custom removal logic
(attributeName, range, writer) => {
// Custom removal implementation
writer.removeAttribute(attributeName, range);
}
);The Remove Format plugin works with CKEditor 5's schema system to automatically detect formatting attributes:
// Attributes with isFormatting: true are automatically handled
model.schema.setAttributeProperties('customFormat', {
isFormatting: true
});The RemoveFormatCommand uses sophisticated logic to determine and remove formatting:
The command identifies formatting in two ways:
isFormatting: true in their schema propertiesregisterCustomAttribute()The command processes different types of selections:
// The command processes these items in order:
// 1. Items within selected ranges (getItems())
// 2. Selected blocks (getSelectedBlocks())
// 3. The selection itself if it has formatting attributes
// For each item, it:
// - Gets all formatting attributes
// - Creates a range on the item
// - Removes each formatting attribute (custom or standard)The plugin can be included in editor configuration:
ClassicEditor.create(document.querySelector('#editor'), {
plugins: [
RemoveFormat,
// other plugins...
],
toolbar: {
items: [
'removeFormat',
'|', // separator
// other toolbar items...
]
},
menuBar: {
isVisible: true
}
})