Base classes and utilities for creating custom Eruda tools and extensions. Eruda's modular architecture allows developers to create custom debugging tools that integrate seamlessly with the existing interface.
The foundation for creating custom Eruda tools with standardized lifecycle methods.
/**
* Base class for all Eruda tools
*/
class Tool {
/** Unique tool name displayed as tab title */
name: string;
/**
* Initialize tool with container element
* @param el - Container element wrapped as jQuery-like object
*/
init(el: unknown): void;
/**
* Show tool panel (called when tab is selected)
* @returns Tool instance for chaining
*/
show(): Tool | undefined;
/**
* Hide tool panel (called when switching to other tab)
* @returns Tool instance for chaining
*/
hide(): Tool | undefined;
/**
* Clean up tool resources (called when tool is removed)
*/
destroy(): void;
}
/**
* Tool constructor interface
*/
interface ToolConstructor {
new (): Tool;
readonly prototype: Tool;
/**
* Extend base Tool class to create custom tool
* @param tool - Tool implementation object
* @returns Custom tool constructor
*/
extend(tool: Tool): ToolConstructor;
}Create custom tools by extending the base Tool class.
Usage Examples:
// Create a custom tool using extend
const MyTool = eruda.Tool.extend({
name: 'myTool',
init(el) {
this._$el = el;
this._initHtml();
this._bindEvents();
},
show() {
this._$el.show();
return this;
},
hide() {
this._$el.hide();
return this;
},
destroy() {
this._$el.remove();
},
_initHtml() {
this._$el.html(`
<div class="my-tool-container">
<h3>My Custom Tool</h3>
<button class="my-btn">Click me</button>
<div class="my-output"></div>
</div>
`);
},
_bindEvents() {
const self = this;
this._$el.find('.my-btn').on('click', function() {
self._handleClick();
});
},
_handleClick() {
this._$el.find('.my-output').text('Button clicked!');
}
});
// Add the custom tool to Eruda
eruda.add(new MyTool());Tools can integrate with Eruda's configuration system and other advanced features.
/**
* Create configuration store for tool settings
* @param name - Configuration name
* @param data - Default configuration data
* @returns Configuration store
*/
Settings.createCfg(name: string, data: object): LocalStore;
interface LocalStore {
get(key: string): any;
set(key: string, value: any): void;
remove(key: string): void;
clear(): void;
}Advanced Tool Example:
// Advanced tool with configuration and settings integration
const AdvancedTool = eruda.Tool.extend({
name: 'advancedTool',
init(el) {
this._$el = el;
this._initConfig();
this._initHtml();
this._bindEvents();
},
_initConfig() {
// Create configuration store
this._config = eruda.Settings.createCfg('advancedTool', {
autoRefresh: true,
refreshInterval: 1000,
theme: 'light'
});
},
_initHtml() {
this._$el.html(`
<div class="advanced-tool">
<div class="toolbar">
<button class="refresh-btn">Refresh</button>
<button class="settings-btn">Settings</button>
</div>
<div class="content"></div>
</div>
`);
},
show() {
this._$el.show();
if (this._config.get('autoRefresh')) {
this._startAutoRefresh();
}
return this;
},
hide() {
this._$el.hide();
this._stopAutoRefresh();
return this;
},
_startAutoRefresh() {
const interval = this._config.get('refreshInterval');
this._refreshTimer = setInterval(() => {
this._refresh();
}, interval);
},
_stopAutoRefresh() {
if (this._refreshTimer) {
clearInterval(this._refreshTimer);
this._refreshTimer = null;
}
},
_refresh() {
// Update tool content
const content = this._$el.find('.content');
content.html(`<p>Last updated: ${new Date().toLocaleTimeString()}</p>`);
}
});
// Add to Eruda
eruda.add(new AdvancedTool());Tools can integrate with Eruda's settings panel and other tools.
// Tool with settings integration
const ConfigurableTool = eruda.Tool.extend({
name: 'configurableTool',
init(el) {
this._$el = el;
this._initConfig();
this._initHtml();
this._addToSettings();
},
_initConfig() {
this._config = eruda.Settings.createCfg('configurableTool', {
enabled: true,
maxItems: 50,
sortOrder: 'asc'
});
},
_addToSettings() {
// Get settings tool to add configuration options
const settings = eruda.get('settings');
// Add settings section
settings.text('Configurable Tool');
settings.switch(this._config, 'enabled', 'Enable tool');
settings.range(this._config, 'maxItems', 'Max items', {
min: 10,
max: 100,
step: 10
});
settings.select(this._config, 'sortOrder', 'Sort order', [
'asc', 'desc'
]);
settings.separator();
},
_initHtml() {
// Tool implementation...
}
});Tools can use Eruda's event system for inter-tool communication.
// Tool with event integration
const EventTool = eruda.Tool.extend({
name: 'eventTool',
init(el) {
this._$el = el;
this._bindGlobalEvents();
this._initHtml();
},
_bindGlobalEvents() {
// Listen for Eruda events
eruda.util.emitter.on('console.log', (data) => {
this._onConsoleLog(data);
});
eruda.util.emitter.on('network.request', (request) => {
this._onNetworkRequest(request);
});
},
_onConsoleLog(data) {
// React to console activity
this._updateDisplay('Console activity detected');
},
_onNetworkRequest(request) {
// React to network activity
this._updateDisplay(`Network request: ${request.method} ${request.url}`);
},
_updateDisplay(message) {
const display = this._$el.find('.event-display');
display.append(`<div>${new Date().toLocaleTimeString()}: ${message}</div>`);
},
destroy() {
// Clean up event listeners
eruda.util.emitter.removeAllListeners();
this._$el.remove();
}
});Tools can use Eruda's utility functions for common operations.
// Tool using Eruda utilities
const UtilityTool = eruda.Tool.extend({
name: 'utilityTool',
init(el) {
this._$el = el;
this._initHtml();
this._applyTheme();
},
_applyTheme() {
const util = eruda.util;
const currentTheme = util.getTheme();
const isDark = util.isDarkTheme(currentTheme);
// Apply theme-appropriate styles
if (isDark) {
this._$el.addClass('dark-theme');
} else {
this._$el.removeClass('dark-theme');
}
},
_injectCustomStyles() {
// Use Eruda's CSS injection
eruda.util.evalCss(`
.utility-tool {
padding: 10px;
background: var(--background);
color: var(--foreground);
}
.utility-tool.dark-theme {
background: #2d2d2d;
color: #ffffff;
}
`);
},
_checkElement(element) {
// Check if element belongs to Eruda
if (eruda.util.isErudaEl(element)) {
console.log('This element belongs to Eruda');
}
}
});When developing custom tools:
destroy()