Lightweight, robust, elegant syntax highlighting library with support for 280+ languages and multiple themes
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
The plugin system provides extensible architecture for adding features and functionality to PrismJS. Plugins integrate with the highlighting process through hooks and extend capabilities with additional UI elements, processing logic, and specialized highlighting features.
The main container for all loaded plugins and plugin-related functionality.
/**
* Object containing all loaded plugins
* @type {Object<string, Object>}
*/
Prism.plugins;Usage Examples:
// Check if plugin is loaded
if (Prism.plugins.lineNumbers) {
console.log('Line Numbers plugin is available');
}
// Access plugin functionality
Prism.plugins.fileHighlight.highlight(document);
// List all loaded plugins
console.log(Object.keys(Prism.plugins));
// Output: ['toolbar', 'lineNumbers', 'copyToClipboard', ...]Event-driven system allowing plugins to integrate with the highlighting process.
/**
* Hook system for plugin integration and event handling
*/
Prism.hooks;
/**
* Add callback function for specific hook event
* @param {string} name - Hook name (before-highlight, after-highlight, etc.)
* @param {function} callback - Function to execute when hook fires
*/
Prism.hooks.add(name, callback);
/**
* Execute all callbacks registered for specific hook
* @param {string} name - Hook name to execute
* @param {object} env - Environment object passed to all callbacks
*/
Prism.hooks.run(name, env);Available Hooks:
// Core highlighting hooks
'before-highlightall' // Before highlighting all elements
'before-all-elements-highlight' // Before processing element list
'before-sanity-check' // Before element validation
'before-highlight' // Before highlighting single element
'before-insert' // Before inserting highlighted HTML
'after-highlight' // After highlighting complete
'complete' // After DOM insertion complete
'wrap' // When wrapping tokens in HTML
// Token processing hooks
'before-tokenize' // Before tokenization starts
'after-tokenize' // After tokenization completeUsage Examples:
// Add custom processing before highlighting
Prism.hooks.add('before-highlight', function(env) {
// env.element, env.language, env.grammar, env.code
console.log('About to highlight:', env.language);
// Modify code before highlighting
env.code = env.code.trim();
});
// Process tokens after tokenization
Prism.hooks.add('after-tokenize', function(env) {
// env.tokens, env.code, env.grammar, env.language
env.tokens.forEach(token => {
if (token instanceof Prism.Token && token.type === 'comment') {
token.alias = 'faded';
}
});
});
// Customize HTML wrapping for tokens
Prism.hooks.add('wrap', function(env) {
// env.type, env.content, env.tag, env.attributes, env.language
if (env.type === 'keyword') {
env.attributes.title = `Keyword: ${env.content}`;
env.attributes['data-tooltip'] = 'This is a language keyword';
}
});
// Add custom completion logic
Prism.hooks.add('complete', function(env) {
// env.element, env.highlightedCode
env.element.setAttribute('data-highlighted', 'true');
console.log('Highlighting complete for:', env.element);
});Adds line numbers to code blocks.
/**
* Line Numbers plugin functionality
*/
Prism.plugins.lineNumbers;
/**
* Get line element for specific line number
* @param {Element} element - Pre element with line numbers
* @param {number} number - Line number to retrieve
* @returns {Element|undefined} Line element or undefined
*/
Prism.plugins.lineNumbers.getLine(element, number);
/**
* Resize line numbers to match code height
* @param {Element} element - Pre element to resize
*/
Prism.plugins.lineNumbers.resize(element);Usage Examples:
// Enable line numbers via CSS class
// <pre class="line-numbers"><code class="language-js">...</code></pre>
// Programmatically enable line numbers
const codeBlock = document.querySelector('pre');
codeBlock.classList.add('line-numbers');
Prism.highlightElement(codeBlock.querySelector('code'));
// Access specific line
const lineElement = Prism.plugins.lineNumbers.getLine(codeBlock, 5);
if (lineElement) {
lineElement.style.backgroundColor = 'yellow';
}
// Resize after dynamic content changes
Prism.plugins.lineNumbers.resize(codeBlock);Adds customizable toolbar to code blocks.
/**
* Toolbar plugin functionality
*/
Prism.plugins.toolbar;
/**
* Register new toolbar button
* @param {string} key - Unique button identifier
* @param {Object|function} button - Button configuration or factory function
*/
Prism.plugins.toolbar.registerButton(key, button);
/**
* Get toolbar for specific code element
* @param {Element} element - Code element
* @returns {Element} Toolbar element
*/
Prism.plugins.toolbar.getToolbarElement(element);Usage Examples:
// Register custom toolbar button
Prism.plugins.toolbar.registerButton('select-code', {
text: 'Select All',
onClick: function(env) {
// env.element contains the code element
const range = document.createRange();
range.selectNodeContents(env.element);
window.getSelection().removeAllRanges();
window.getSelection().addRange(range);
}
});
// Register button with dynamic content
Prism.plugins.toolbar.registerButton('show-language', function(env) {
return {
text: env.language.toUpperCase(),
className: 'language-label',
};
});
// Access toolbar after highlighting
Prism.hooks.add('complete', function(env) {
const toolbar = Prism.plugins.toolbar.getToolbarElement(env.element);
if (toolbar) {
toolbar.style.backgroundColor = '#f0f0f0';
}
});Adds copy functionality to code blocks.
/**
* Copy to Clipboard plugin (extends toolbar)
*/
Prism.plugins.copyToClipboard;Usage Examples:
// Automatically adds copy button to toolbar
// No additional API - works automatically with toolbar plugin
// Customize copy button text
Prism.hooks.add('before-highlightall', function() {
// This runs before the plugin initializes
if (typeof Prism.plugins.toolbar !== 'undefined') {
// Plugin will automatically register copy button
}
});
// Listen for copy events
document.addEventListener('prism-copy-success', function(e) {
console.log('Code copied:', e.detail.code);
});
document.addEventListener('prism-copy-error', function(e) {
console.error('Copy failed:', e.detail.error);
});Load and highlight external code files.
/**
* File Highlight plugin functionality
*/
Prism.plugins.fileHighlight;
/**
* Highlight external files in pre elements with data-src
* @param {Element} [container=document] - Container to search within
*/
Prism.plugins.fileHighlight.highlight(container);
/**
* @deprecated Use Prism.plugins.fileHighlight.highlight instead
* Legacy function for backwards compatibility
* @param {Element} [container=document] - Container to search within
*/
Prism.fileHighlight(container);Usage Examples:
<!-- HTML setup for file highlighting -->
<pre data-src="example.js"></pre>
<pre data-src="styles.css" data-range="1,10"></pre>
<pre data-src="config.json" class="language-json"></pre>// Manual file highlighting
Prism.plugins.fileHighlight.highlight(document);
// Highlight files in specific container
const container = document.getElementById('code-examples');
Prism.plugins.fileHighlight.highlight(container);
// Files are loaded asynchronously
Prism.hooks.add('complete', function(env) {
if (env.element.hasAttribute('data-src')) {
console.log('External file highlighted:', env.element.getAttribute('data-src'));
}
});Automatically load language definitions when needed.
/**
* Autoloader plugin functionality
*/
Prism.plugins.autoloader;
/**
* Set path template for loading language files
* @param {string} template - Path template with {id} placeholder
*/
Prism.plugins.autoloader.languages_path;
/**
* Load specific languages
* @param {string|string[]} languages - Language IDs to load
* @param {function} [success] - Success callback
* @param {function} [error] - Error callback
*/
Prism.plugins.autoloader.loadLanguages(languages, success, error);Usage Examples:
// Configure autoloader path
Prism.plugins.autoloader.languages_path = 'components/prism-{id}.min.js';
// Languages are loaded automatically when encountered
// <pre><code class="language-python">print("Hello")</code></pre>
// Python grammar will be loaded automatically
// Manual language loading
Prism.plugins.autoloader.loadLanguages(['python', 'rust'], function() {
console.log('Languages loaded successfully');
// Now highlight code
Prism.highlightAll();
}, function() {
console.error('Failed to load languages');
});
// Load single language
Prism.plugins.autoloader.loadLanguages('go');/**
* Line Highlight - Highlight specific lines
*/
Prism.plugins.lineHighlight;
/**
* Match Braces - Highlight matching brackets
*/
Prism.plugins.matchBraces;
/**
* Show Invisibles - Display whitespace characters
*/
Prism.plugins.showInvisibles;
/**
* Normalize Whitespace - Clean up code formatting
*/
Prism.plugins.normalizeWhitespace;
/**
* Command Line - Style command-line sessions
*/
Prism.plugins.commandLine;
/**
* Diff Highlight - Highlight code differences
*/
Prism.plugins.diffHighlight;// Basic plugin structure
(function() {
if (typeof Prism === 'undefined' || typeof document === 'undefined') {
return;
}
// Plugin configuration
var config = Prism.plugins.myPlugin = {
setting1: 'default value',
setting2: true
};
// Plugin functionality
function doSomething(element) {
// Plugin logic
element.classList.add('my-plugin-processed');
}
// Hook into highlighting process
Prism.hooks.add('complete', function(env) {
if (env.element.classList.contains('my-plugin-enabled')) {
doSomething(env.element);
}
});
})();// Environment detection
if (typeof Prism === 'undefined' || typeof document === 'undefined') {
return; // Exit if not in browser with Prism
}
// Feature detection
if (!document.querySelector) {
return; // Exit if required DOM methods unavailable
}
// Plugin namespace
var MyPlugin = Prism.plugins.myPlugin = {
// Public API
process: function(element) {
// Implementation
},
// Configuration
config: {
option1: true,
option2: 'default'
}
};
// Safe hook registration
Prism.hooks.add('complete', function(env) {
try {
MyPlugin.process(env.element);
} catch (error) {
console.error('MyPlugin error:', error);
}
});// Toolbar integration
if (Prism.plugins.toolbar) {
Prism.plugins.toolbar.registerButton('my-button', {
text: 'My Action',
onClick: function(env) {
// Button click handler
console.log('Button clicked for:', env.language);
}
});
}
// CSS class detection
Prism.hooks.add('before-sanity-check', function(env) {
if (env.element.classList.contains('my-plugin')) {
// Plugin-specific processing
env.element.setAttribute('data-processed', 'my-plugin');
}
});
// Language-specific plugins
Prism.hooks.add('after-tokenize', function(env) {
if (env.language === 'javascript') {
// JavaScript-specific token processing
processJavaScriptTokens(env.tokens);
}
});// Check plugin dependencies
function hasRequiredPlugins() {
return Prism.plugins.toolbar && Prism.plugins.lineNumbers;
}
if (hasRequiredPlugins()) {
// Initialize plugin that depends on others
initializeComplexPlugin();
} else {
console.warn('Required plugins not loaded');
}
// Dynamic plugin loading
function loadPlugin(pluginPath, callback) {
const script = document.createElement('script');
script.src = pluginPath;
script.onload = callback;
script.onerror = function() {
console.error('Failed to load plugin:', pluginPath);
};
document.head.appendChild(script);
}
// Load plugin chain
loadPlugin('plugins/toolbar/prism-toolbar.js', function() {
loadPlugin('plugins/copy-to-clipboard/prism-copy-to-clipboard.js', function() {
console.log('All plugins loaded');
Prism.highlightAll();
});
});Install with Tessl CLI
npx tessl i tessl/npm-prismjs