or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-highlighting.mdindex.mdlanguage-system.mdplugin-system.mdtoken-system.mdutilities.md

plugin-system.mddocs/

0

# Plugin System

1

2

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.

3

4

## Capabilities

5

6

### Plugin Namespace

7

8

The main container for all loaded plugins and plugin-related functionality.

9

10

```javascript { .api }

11

/**

12

* Object containing all loaded plugins

13

* @type {Object<string, Object>}

14

*/

15

Prism.plugins;

16

```

17

18

**Usage Examples:**

19

20

```javascript

21

// Check if plugin is loaded

22

if (Prism.plugins.lineNumbers) {

23

console.log('Line Numbers plugin is available');

24

}

25

26

// Access plugin functionality

27

Prism.plugins.fileHighlight.highlight(document);

28

29

// List all loaded plugins

30

console.log(Object.keys(Prism.plugins));

31

// Output: ['toolbar', 'lineNumbers', 'copyToClipboard', ...]

32

```

33

34

### Hook System

35

36

Event-driven system allowing plugins to integrate with the highlighting process.

37

38

```javascript { .api }

39

/**

40

* Hook system for plugin integration and event handling

41

*/

42

Prism.hooks;

43

44

/**

45

* Add callback function for specific hook event

46

* @param {string} name - Hook name (before-highlight, after-highlight, etc.)

47

* @param {function} callback - Function to execute when hook fires

48

*/

49

Prism.hooks.add(name, callback);

50

51

/**

52

* Execute all callbacks registered for specific hook

53

* @param {string} name - Hook name to execute

54

* @param {object} env - Environment object passed to all callbacks

55

*/

56

Prism.hooks.run(name, env);

57

```

58

59

**Available Hooks:**

60

61

```javascript

62

// Core highlighting hooks

63

'before-highlightall' // Before highlighting all elements

64

'before-all-elements-highlight' // Before processing element list

65

'before-sanity-check' // Before element validation

66

'before-highlight' // Before highlighting single element

67

'before-insert' // Before inserting highlighted HTML

68

'after-highlight' // After highlighting complete

69

'complete' // After DOM insertion complete

70

'wrap' // When wrapping tokens in HTML

71

72

// Token processing hooks

73

'before-tokenize' // Before tokenization starts

74

'after-tokenize' // After tokenization complete

75

```

76

77

**Usage Examples:**

78

79

```javascript

80

// Add custom processing before highlighting

81

Prism.hooks.add('before-highlight', function(env) {

82

// env.element, env.language, env.grammar, env.code

83

console.log('About to highlight:', env.language);

84

85

// Modify code before highlighting

86

env.code = env.code.trim();

87

});

88

89

// Process tokens after tokenization

90

Prism.hooks.add('after-tokenize', function(env) {

91

// env.tokens, env.code, env.grammar, env.language

92

env.tokens.forEach(token => {

93

if (token instanceof Prism.Token && token.type === 'comment') {

94

token.alias = 'faded';

95

}

96

});

97

});

98

99

// Customize HTML wrapping for tokens

100

Prism.hooks.add('wrap', function(env) {

101

// env.type, env.content, env.tag, env.attributes, env.language

102

if (env.type === 'keyword') {

103

env.attributes.title = `Keyword: ${env.content}`;

104

env.attributes['data-tooltip'] = 'This is a language keyword';

105

}

106

});

107

108

// Add custom completion logic

109

Prism.hooks.add('complete', function(env) {

110

// env.element, env.highlightedCode

111

env.element.setAttribute('data-highlighted', 'true');

112

console.log('Highlighting complete for:', env.element);

113

});

114

```

115

116

## Built-in Plugins

117

118

### Line Numbers Plugin

119

120

Adds line numbers to code blocks.

121

122

```javascript { .api }

123

/**

124

* Line Numbers plugin functionality

125

*/

126

Prism.plugins.lineNumbers;

127

128

/**

129

* Get line element for specific line number

130

* @param {Element} element - Pre element with line numbers

131

* @param {number} number - Line number to retrieve

132

* @returns {Element|undefined} Line element or undefined

133

*/

134

Prism.plugins.lineNumbers.getLine(element, number);

135

136

/**

137

* Resize line numbers to match code height

138

* @param {Element} element - Pre element to resize

139

*/

140

Prism.plugins.lineNumbers.resize(element);

141

```

142

143

**Usage Examples:**

144

145

```javascript

146

// Enable line numbers via CSS class

147

// <pre class="line-numbers"><code class="language-js">...</code></pre>

148

149

// Programmatically enable line numbers

150

const codeBlock = document.querySelector('pre');

151

codeBlock.classList.add('line-numbers');

152

Prism.highlightElement(codeBlock.querySelector('code'));

153

154

// Access specific line

155

const lineElement = Prism.plugins.lineNumbers.getLine(codeBlock, 5);

156

if (lineElement) {

157

lineElement.style.backgroundColor = 'yellow';

158

}

159

160

// Resize after dynamic content changes

161

Prism.plugins.lineNumbers.resize(codeBlock);

162

```

163

164

### Toolbar Plugin

165

166

Adds customizable toolbar to code blocks.

167

168

```javascript { .api }

169

/**

170

* Toolbar plugin functionality

171

*/

172

Prism.plugins.toolbar;

173

174

/**

175

* Register new toolbar button

176

* @param {string} key - Unique button identifier

177

* @param {Object|function} button - Button configuration or factory function

178

*/

179

Prism.plugins.toolbar.registerButton(key, button);

180

181

/**

182

* Get toolbar for specific code element

183

* @param {Element} element - Code element

184

* @returns {Element} Toolbar element

185

*/

186

Prism.plugins.toolbar.getToolbarElement(element);

187

```

188

189

**Usage Examples:**

190

191

```javascript

192

// Register custom toolbar button

193

Prism.plugins.toolbar.registerButton('select-code', {

194

text: 'Select All',

195

onClick: function(env) {

196

// env.element contains the code element

197

const range = document.createRange();

198

range.selectNodeContents(env.element);

199

window.getSelection().removeAllRanges();

200

window.getSelection().addRange(range);

201

}

202

});

203

204

// Register button with dynamic content

205

Prism.plugins.toolbar.registerButton('show-language', function(env) {

206

return {

207

text: env.language.toUpperCase(),

208

className: 'language-label',

209

};

210

});

211

212

// Access toolbar after highlighting

213

Prism.hooks.add('complete', function(env) {

214

const toolbar = Prism.plugins.toolbar.getToolbarElement(env.element);

215

if (toolbar) {

216

toolbar.style.backgroundColor = '#f0f0f0';

217

}

218

});

219

```

220

221

### Copy to Clipboard Plugin

222

223

Adds copy functionality to code blocks.

224

225

```javascript { .api }

226

/**

227

* Copy to Clipboard plugin (extends toolbar)

228

*/

229

Prism.plugins.copyToClipboard;

230

```

231

232

**Usage Examples:**

233

234

```javascript

235

// Automatically adds copy button to toolbar

236

// No additional API - works automatically with toolbar plugin

237

238

// Customize copy button text

239

Prism.hooks.add('before-highlightall', function() {

240

// This runs before the plugin initializes

241

if (typeof Prism.plugins.toolbar !== 'undefined') {

242

// Plugin will automatically register copy button

243

}

244

});

245

246

// Listen for copy events

247

document.addEventListener('prism-copy-success', function(e) {

248

console.log('Code copied:', e.detail.code);

249

});

250

251

document.addEventListener('prism-copy-error', function(e) {

252

console.error('Copy failed:', e.detail.error);

253

});

254

```

255

256

### File Highlight Plugin

257

258

Load and highlight external code files.

259

260

```javascript { .api }

261

/**

262

* File Highlight plugin functionality

263

*/

264

Prism.plugins.fileHighlight;

265

266

/**

267

* Highlight external files in pre elements with data-src

268

* @param {Element} [container=document] - Container to search within

269

*/

270

Prism.plugins.fileHighlight.highlight(container);

271

272

/**

273

* @deprecated Use Prism.plugins.fileHighlight.highlight instead

274

* Legacy function for backwards compatibility

275

* @param {Element} [container=document] - Container to search within

276

*/

277

Prism.fileHighlight(container);

278

```

279

280

**Usage Examples:**

281

282

```html

283

<!-- HTML setup for file highlighting -->

284

<pre data-src="example.js"></pre>

285

<pre data-src="styles.css" data-range="1,10"></pre>

286

<pre data-src="config.json" class="language-json"></pre>

287

```

288

289

```javascript

290

// Manual file highlighting

291

Prism.plugins.fileHighlight.highlight(document);

292

293

// Highlight files in specific container

294

const container = document.getElementById('code-examples');

295

Prism.plugins.fileHighlight.highlight(container);

296

297

// Files are loaded asynchronously

298

Prism.hooks.add('complete', function(env) {

299

if (env.element.hasAttribute('data-src')) {

300

console.log('External file highlighted:', env.element.getAttribute('data-src'));

301

}

302

});

303

```

304

305

### Autoloader Plugin

306

307

Automatically load language definitions when needed.

308

309

```javascript { .api }

310

/**

311

* Autoloader plugin functionality

312

*/

313

Prism.plugins.autoloader;

314

315

/**

316

* Set path template for loading language files

317

* @param {string} template - Path template with {id} placeholder

318

*/

319

Prism.plugins.autoloader.languages_path;

320

321

/**

322

* Load specific languages

323

* @param {string|string[]} languages - Language IDs to load

324

* @param {function} [success] - Success callback

325

* @param {function} [error] - Error callback

326

*/

327

Prism.plugins.autoloader.loadLanguages(languages, success, error);

328

```

329

330

**Usage Examples:**

331

332

```javascript

333

// Configure autoloader path

334

Prism.plugins.autoloader.languages_path = 'components/prism-{id}.min.js';

335

336

// Languages are loaded automatically when encountered

337

// <pre><code class="language-python">print("Hello")</code></pre>

338

// Python grammar will be loaded automatically

339

340

// Manual language loading

341

Prism.plugins.autoloader.loadLanguages(['python', 'rust'], function() {

342

console.log('Languages loaded successfully');

343

// Now highlight code

344

Prism.highlightAll();

345

}, function() {

346

console.error('Failed to load languages');

347

});

348

349

// Load single language

350

Prism.plugins.autoloader.loadLanguages('go');

351

```

352

353

### Additional Plugins

354

355

```javascript { .api }

356

/**

357

* Line Highlight - Highlight specific lines

358

*/

359

Prism.plugins.lineHighlight;

360

361

/**

362

* Match Braces - Highlight matching brackets

363

*/

364

Prism.plugins.matchBraces;

365

366

/**

367

* Show Invisibles - Display whitespace characters

368

*/

369

Prism.plugins.showInvisibles;

370

371

/**

372

* Normalize Whitespace - Clean up code formatting

373

*/

374

Prism.plugins.normalizeWhitespace;

375

376

/**

377

* Command Line - Style command-line sessions

378

*/

379

Prism.plugins.commandLine;

380

381

/**

382

* Diff Highlight - Highlight code differences

383

*/

384

Prism.plugins.diffHighlight;

385

```

386

387

## Plugin Development

388

389

### Creating Custom Plugins

390

391

```javascript

392

// Basic plugin structure

393

(function() {

394

if (typeof Prism === 'undefined' || typeof document === 'undefined') {

395

return;

396

}

397

398

// Plugin configuration

399

var config = Prism.plugins.myPlugin = {

400

setting1: 'default value',

401

setting2: true

402

};

403

404

// Plugin functionality

405

function doSomething(element) {

406

// Plugin logic

407

element.classList.add('my-plugin-processed');

408

}

409

410

// Hook into highlighting process

411

Prism.hooks.add('complete', function(env) {

412

if (env.element.classList.contains('my-plugin-enabled')) {

413

doSomething(env.element);

414

}

415

});

416

})();

417

```

418

419

### Plugin Best Practices

420

421

```javascript

422

// Environment detection

423

if (typeof Prism === 'undefined' || typeof document === 'undefined') {

424

return; // Exit if not in browser with Prism

425

}

426

427

// Feature detection

428

if (!document.querySelector) {

429

return; // Exit if required DOM methods unavailable

430

}

431

432

// Plugin namespace

433

var MyPlugin = Prism.plugins.myPlugin = {

434

// Public API

435

process: function(element) {

436

// Implementation

437

},

438

439

// Configuration

440

config: {

441

option1: true,

442

option2: 'default'

443

}

444

};

445

446

// Safe hook registration

447

Prism.hooks.add('complete', function(env) {

448

try {

449

MyPlugin.process(env.element);

450

} catch (error) {

451

console.error('MyPlugin error:', error);

452

}

453

});

454

```

455

456

### Plugin Integration Patterns

457

458

```javascript

459

// Toolbar integration

460

if (Prism.plugins.toolbar) {

461

Prism.plugins.toolbar.registerButton('my-button', {

462

text: 'My Action',

463

onClick: function(env) {

464

// Button click handler

465

console.log('Button clicked for:', env.language);

466

}

467

});

468

}

469

470

// CSS class detection

471

Prism.hooks.add('before-sanity-check', function(env) {

472

if (env.element.classList.contains('my-plugin')) {

473

// Plugin-specific processing

474

env.element.setAttribute('data-processed', 'my-plugin');

475

}

476

});

477

478

// Language-specific plugins

479

Prism.hooks.add('after-tokenize', function(env) {

480

if (env.language === 'javascript') {

481

// JavaScript-specific token processing

482

processJavaScriptTokens(env.tokens);

483

}

484

});

485

```

486

487

## Plugin Loading and Dependencies

488

489

```javascript

490

// Check plugin dependencies

491

function hasRequiredPlugins() {

492

return Prism.plugins.toolbar && Prism.plugins.lineNumbers;

493

}

494

495

if (hasRequiredPlugins()) {

496

// Initialize plugin that depends on others

497

initializeComplexPlugin();

498

} else {

499

console.warn('Required plugins not loaded');

500

}

501

502

// Dynamic plugin loading

503

function loadPlugin(pluginPath, callback) {

504

const script = document.createElement('script');

505

script.src = pluginPath;

506

script.onload = callback;

507

script.onerror = function() {

508

console.error('Failed to load plugin:', pluginPath);

509

};

510

document.head.appendChild(script);

511

}

512

513

// Load plugin chain

514

loadPlugin('plugins/toolbar/prism-toolbar.js', function() {

515

loadPlugin('plugins/copy-to-clipboard/prism-copy-to-clipboard.js', function() {

516

console.log('All plugins loaded');

517

Prism.highlightAll();

518

});

519

});

520

```