
RayEditor is a lightweight WYSIWYG editor that transforms plain content areas into feature-rich text editors with zero dependencies.
It is useful if you need more than a plain textarea but less than a full-blown document editor like Google Docs. Think blog post creation, CMS content fields, simple documentation tools, or even formatted comment sections.
Features
- Standard Text Formatting: Bold, Italic, Underline, Strikethrough.
- Case Transformation: Uppercase, Lowercase, Toggle Case.
- Text Styles: Subscript, Superscript, Text Color, Background Color, Alignment.
- Structure: Headings (H1-H6), Ordered/Unordered Lists.
- Code Editing: Inline code highlighting and multi-line code blocks.
- Media: Image and File uploads with configurable endpoints and size limits. Image resizing is included.
- Tables: Basic table creation and manipulation (add/delete rows/columns).
- History: Undo/Redo functionality.
- Links: Add and edit hyperlinks.
How to use it:
1. Download the package and load the RayEditor’s JavaScript & files in the document.
<link rel="stylesheet" href="ray-editor.css" /> <script src="ray-editor.js"></script>
2. Place an empty div (or another block element) in your HTML where you want the editor to appear. Give it an ID so you can target it with JavaScript.
<div id="myEditor"></div>
3. Call the RayEditor function to create a basic WYSIWYG editor:
const editor = new RayEditor('editor', {
// options here
});4. Configure the editor with the following options:
toolbar(ToolbarGroup[]): Defines the visual groups of buttons separated by dividers.imageUpload(object): Configures image handling. ContainsimageUploadUrl(string) andimageMaxSize(number).fileUpload(object): Configures file handling. ContainsfileUploadUrl(string) andfileMaxSize(number).mentions(object): Configures user tagging. ContainsenableMentions(boolean),mentionTag(string),mentionElement(string), andmentionUrl(string).toolbarType(string): Sets the toolbar display style. Accepts ‘default’ or ‘inline’.overflowMenu(boolean): Collapses excess toolbar buttons into an overflow menu.readOnly(boolean): Disables text editing.markdownShortcuts(boolean): Toggles markdown syntax conversion.wordCount(boolean): Displays a word count bar at the bottom.findReplace(boolean): Enables the search and replace panel.slashCommands(boolean): Activates the/command palette.historySize(number): Sets the maximum number of undo/redo steps.theme(string): Sets the visual theme. Accepts ‘light’, ‘dark’, or ‘auto’.initStyles(boolean): Auto-injects the default CSS link.stylesheetUrl(string): Points to a custom CSS file.hideWatermark(boolean): Removes the editor watermark.plugins(RayPlugin[]): Registers external plugins.onChange(function): Fires a callback when the HTML content updates.
const editor = new RayEditor('editor', {
toolbar: ToolbarGroup[],
imageUpload: {
imageUploadUrl: string,
imageMaxSize: number,
},
fileUpload: {
fileUploadUrl: string,
fileMaxSize: number,
},
mentions: {
enableMentions: boolean,
mentionTag: string,
mentionElement: 'span' | 'a',
mentionUrl: string,
},
toolbarType: 'default' | 'inline',
overflowMenu: boolean,
readOnly: boolean,
markdownShortcuts: boolean,
wordCount: boolean,
findReplace: boolean,
slashCommands: boolean,
historySize: number,
theme: 'light' | 'dark' | 'auto',
initStyles: boolean,
stylesheetUrl: string,
hideWatermark: boolean,
plugins: RayPlugin[],
onChange: (html: string) => void,
});5. API methods.
// Retrieves the current HTML content from the editor
myEditor.getContent();
// Overwrites the editor with new HTML content
myEditor.setContent('<h1>Welcome to our custom editor</h1>');
// Legacy method to get content (v1 backward compatibility)
myEditor.getRayEditorContent();
// Legacy method to set content (v1 backward compatibility)
myEditor.setRayEditorContent('<p>Legacy support active</p>');
// Attaches an event listener to the editor
myEditor.on('focus', myFocusHandler);
// Removes an event listener from the editor
myEditor.off('focus', myFocusHandler);
// Manually triggers a specific event
myEditor.emit('customEvent', { data: 'testPayload' });
// Registers a new plugin
myEditor.use(myCustomPlugin);
// Injects a new button into the toolbar
myEditor.addButton({ name: 'highlightText', icon: 'H', action: () => {} });
// Removes an existing button from the toolbar
myEditor.removeButton('highlightText');
// Adds a new command to the slash palette
myEditor.registerSlashCommand({ name: 'Insert Signature', action: () => {} });
// Registers a custom command handler
myEditor.registerCommand('saveDocument', () => {});
// Executes a registered command programmatically
myEditor.execCommand('bold');
// Switches the editor theme dynamically
myEditor.setTheme('dark');
// Toggles the read-only state
myEditor.setReadOnly(true);
// Returns the current word and character count
myEditor.getWordCount();
// Completely removes the editor instance and cleans up the DOM
myEditor.destroy();6. Events.
// Triggers whenever the HTML content updates
myEditor.on('content:change', function(event) {
console.log('New content detected:', event.html);
});
// Triggers when the user changes their text selection or cursor position
myEditor.on('selection:change', function() {
console.log('User moved the cursor');
});
// Triggers when the editor gains focus
myEditor.on('focus', function() {
console.log('Editor is now active');
});
// Triggers when the editor loses focus
myEditor.on('blur', function() {
console.log('Editor is now inactive');
});
// Triggers right before a command executes. Return false to cancel it.
myEditor.on('command:before', function(event) {
console.log('Preparing to run:', event.command);
});
// Triggers immediately after a command finishes executing
myEditor.on('command:after', function(event) {
console.log('Finished running:', event.command);
});
// Triggers when a new plugin finishes installation
myEditor.on('plugin:install', function(event) {
console.log('Successfully installed plugin:', event.name);
});
// Triggers when a plugin is removed or destroyed
myEditor.on('plugin:destroy', function(event) {
console.log('Successfully removed plugin:', event.name);
});
// Triggers when the visual theme changes
myEditor.on('theme:change', function(event) {
console.log('Switched to new theme:', event.theme);
});Changelog:
03/26/2025
- v2.0.9: bugfixes
03/04/2025
- feat: inline color picker, datetime popup, table toolbar fixes, multi-editor isolation
08/20/2025
- code fixes and improements
08/04/2025
- Implement Toggleable Source Code Button
05/28/2025
- code fixes and improements
05/27/2025
- Add a chck to ensure the codeblock insertion
05/23/2025
- JS update
05/13/2025
- css, pre and code fix







