How Draw.io Desktop Implements a Custom Context Menu with Paste and Match Style
Draw.io Desktop leverages the electron-context-menu library in src/main/electron.js to inject a "Paste and Match Style" option that appears only when plain text exists on the clipboard, executing browserWindow.webContents.pasteAndMatchStyle() to strip formatting during paste operations.
The jgraph/drawio-desktop application provides a native-like editing experience by customizing the right-click menu in its Electron-based interface. The implementation of the custom context menu, specifically the "Paste and Match Style" functionality, demonstrates how to extend default Electron menus with conditional logic and clipboard-aware visibility controls.
Electron Context Menu Architecture
The application builds its menu system on top of the third-party electron-context-menu package, which automatically attaches to all renderer windows and provides hooks for custom extensions.
Library Integration in the Main Process
In src/main/electron.js (lines 16-17), the module imports the library alongside standard Electron APIs:
import { clipboard, BrowserWindow } from 'electron';
import contextMenu from 'electron-context-menu';
Configuring the Append Callback
The configuration occurs at lines 53-71 of src/main/electron.js, where the contextMenu() function receives an append callback. This callback injects the custom "Paste and Match Style" entry into the default menu array:
contextMenu({
showCopyImage: true,
showSaveImage: true,
showSaveImageAs: true,
showLookUpSelection: false,
showSearchWithGoogle: false,
showCopyLink: false,
showSelectAll: true,
append: (defaultActions, params, browserWindow) => [
{
label: 'Paste and Match Style',
visible: clipboard.availableFormats().includes('text/plain'),
click: () => {
browserWindow.webContents.pasteAndMatchStyle();
}
}
]
});
Conditional Visibility and Execution Logic
The visible property dynamically controls menu item availability by checking clipboard.availableFormats() for the 'text/plain' type. When the user clicks the option, the click handler invokes browserWindow.webContents.pasteAndMatchStyle(), an Electron API that inserts clipboard content without source formatting—effectively matching the destination style.
Dependency and Project Structure
The electron-context-menu dependency is declared in package.json under the standard dependencies section. No native modules are required, as the implementation relies purely on Electron's built-in clipboard and webContents APIs.
While src/main/electron-preload.js establishes the secure IPC bridge for renderer communication, the context menu logic remains entirely within the main process, with menu actions directly manipulating web contents.
Standalone Implementation Example
To replicate this pattern in a minimal Electron application:
// main.js
import { app, BrowserWindow, clipboard } from 'electron';
import contextMenu from 'electron-context-menu';
function createWindow () {
const win = new BrowserWindow({
webPreferences: { nodeIntegration: false }
});
win.loadURL('https://example.com');
}
app.whenReady().then(() => {
contextMenu({
showSelectAll: true,
append: (defaultActions, params, browserWindow) => [{
label: 'Paste and Match Style',
visible: clipboard.availableFormats().includes('text/plain'),
click: () => browserWindow.webContents.pasteAndMatchStyle()
}]
});
createWindow();
});
Extending with Additional Custom Actions
Developers can augment the menu array returned by the append function with multiple custom entries. Each object supports label, visible, enabled, and click properties, allowing complex conditional logic based on params.selectionText or other browser window attributes.
Summary
- Draw.io Desktop uses
electron-context-menuinsrc/main/electron.jsto customize the right-click experience - The "Paste and Match Style" option appears only when
clipboard.availableFormats()contains'text/plain' - Execution calls
browserWindow.webContents.pasteAndMatchStyle()to paste unformatted text - Configuration spans lines 53-71, with library imports at lines 16-17
- The implementation requires no native code, relying solely on standard Electron APIs
Frequently Asked Questions
How does Draw.io detect when to show the "Paste and Match Style" option?
The menu item's visible property checks clipboard.availableFormats().includes('text/plain') to determine if plain text exists on the system clipboard. If no plain text is available, the option remains hidden from the context menu.
What is the difference between standard paste and pasteAndMatchStyle?
Standard paste operations preserve source formatting from the clipboard, while pasteAndMatchStyle() strips all formatting and inserts the content using the destination's current text styles. This matches the behavior of "Paste and Match Style" commands in native macOS and Windows applications.
Can I add other custom items to the Draw.io context menu?
Yes. The append callback in src/main/electron.js returns an array of menu item objects. Developers can add additional entries with custom labels, visibility conditions based on params.selectionText, and click handlers that invoke browserWindow.webContents methods or IPC calls to the renderer process.
Where is the electron-context-menu dependency declared?
The dependency is listed in package.json under the dependencies section, ensuring it installs automatically with the project. The library is then imported at line 16 of src/main/electron.js and instantiated immediately after command-line option handling.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →