An 11ty plugin that adds classes to code
elements at build time using Prism so you can highlight syntax using CSS.
npm install eleventy-plugin-code-style-hooks
In your Eleventy config file (.eleventy.js
by default):
const codeStyleHooks = require('eleventy-plugin-code-style-hooks');
module.exports = function(eleventyConfig) {
eleventyConfig.addPlugin(codeStyleHooks);
}
Then add your CSS file to the page (or configure Code Style Hooks to do this automatically).
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/static/styles/prism.min.css">
</head>
…
</html>
If you're already using PostHTML you can reduce build times by using the posthtml
export as a plugin to your existing PostHTML syntax tree. It provides a stand-alone PostHTML version of Code Style Hooks that can even be used outside of Eleventy.
The optional parser
export further reduces build times when using PostHTML with Eleventy's --watch
or --serve
arguments. Parsing your options outside of the transform will mean it's only done once at the start of watching or serving rather than every time Eleventy builds.
const posthtml = require('posthtml');
const anotherPostHTMLPlugin = require('another-posthtml-plugin');
const { posthtml: codeStyleHooks, parser } = require('eleventy-plugin-code-style-hooks');
const options = parser({defaultLanguage: 'js'});
module.exports = function(eleventyConfig) {
eleventyConfig.addTransform('posthtml', function(HTMLString, outputPath) {
if(outputPath && outputPath.endsWith('.html')) {
return posthtml([codeStyleHooks(options), anotherPostHTMLPlugin()])
.process(HTMLString)
.then(result => result.html);
}
else {
return HTMLString;
}
});
}
const codeStyleHooks = require('eleventy-plugin-code-style-hooks');
module.exports = function(eleventyConfig) {
eleventyConfig.addPlugin(codeStyleHooks, {
colorPreviews: true,
defaultLanguage: 'js',
highlightSyntax: true,
languageLabels: true,
lineNumbers: true,
markdownTrimTrailingNewline: true,
prism: function(prism) {
prism.languages.example = {
tokenname: /\w+/i
}
},
removeRedundancy: true,
scripts: '/static/scripts/code-blocks.js',
styles: '/static/styles/prism.js'
});
}
- Default: True
- Accepts: Boolean
- Hooks: Colours have a span around them with
class="token color"
containing an empty span at the start withclass="color-preview"
andstyle="--color-value:colourvalue"
properties.
<!-- #fff -->
<span class="token color"><span class="color-preview" style="--color-value:#fff" aria-hidden="true"></span>#fff</span>
Insert spans in and around CSS colours. Applies to Hex, RGB, HSL, HWB, Lab, LCH and named colours (excluding system colours).
Works with CSS and other languages that extend the CSS language in Prism.
highlightSyntax must be True
.
See the examples folder of the Code Style Hooks repo for example CSS.
- Default: ''
- Accepts: String
Set a global default for code
elements missing a class="language=xxx"
attribute. For example, setting this as 'js' will apply class="language-js"
.
See https://prismjs.com/#supported-languages for a list of built-in Prism languages.
- Default: True
- Accepts: Boolean
- Hooks: see Prism FAQs
Turn syntax highlighting from Prism on or off. See https://prismjs.com/ for more information.
- Default: True
- Accepts: Boolean
- Hooks:
code
andpre
elements have adata-language="languagename"
attribute.
<!-- <pre><code class="language-CSS"></code></pre> -->
<pre class="language-css" data-language="CSS"><code class="language-css" data-language="CSS"></code></pre>
Insert a data attribute on code
and pre
elements matching the language from the language-xxx class.
Keeps the case from the language-xxx class, for example, class="language-JaVaScRiPt"
will apply a data-language="JaVaScRiPt"
attribute.
highlightSyntax must be True
.
See the examples folder of the Code Style Hooks repo for example CSS.
- Default: True
- Accepts: Boolean
- Hooks:
code
andpre
elements haveclass="line-numbers"
andcode
elements have<span class="token line-number" aria-hidden="true"></span>
inserted at the start of each new line.
<!--
<pre><code>line 1
line 2</code></pre>
-->
<pre class="line-numbers"><code class="line-numbers"><span class="token line-number" aria-hidden="true"></span>line 1
<span class="token line-number" aria-hidden="true"></span>line 2</code></pre>
Insert spans at the start of each line within a code
block with a pre
parent.
If you're getting an empty line at the end of Markdown generated code blocks, you may need to turn on markdownTrimTrailingNewline.
See the examples folder of the Code Style Hooks repo for example CSS.
- Default: True
- Accepts: Boolean
Remove the unavoidable new line character at the end of Markdown code blocks. Warning: turning this off while line numbers are on will result in an empty numbered line at the end of all Markdown generated code blocks.
If you are using the PostHTML module, markdownTrimTrailingNewline will not work inside the options object. You must import markdownTrimTrailingNewline and add it as a separate plugin.
const posthtml = require('posthtml');
const { posthtml: codeStyleHooks, parser, markdownTrimTrailingNewline } = require('eleventy-plugin-code-style-hooks');
module.exports = function(eleventyConfig) {
eleventyConfig.addPlugin(markdownTrimTrailingNewline);
eleventyConfig.addTransform('posthtml', function(HTMLString, outputPath) {
if(outputPath && outputPath.endsWith('.html')) {
return posthtml([codeStyleHooks()])
.process(HTMLString)
.then(result => result.html);
}
else {
return HTMLString;
}
});
}
- Accepts: Function
Provides a function that can be called before Prism languages are loaded. Will be passed the Prism module as its first argument and Prism's loadLanguages()
utility as its second argument. Can be used to add/customise languages.
- Default: True
- Accepts: Boolean
Remove attributes used by Code Style Hooks that aren't needed after builds.
Removes:
data-color-previews="true/false"
attributesdata-highlight-syntax="true/false"
attributesdata-language-labels="true/false"
attributesdata-line-numbers="true/false"
attributeslanguage-xxx
classes from nonpre
orcode
elementslanguage-xxx
classes oncode
after the first language classlanguage-xxx
classes frompre
elements if there are nocode
children or ifcode
children don't use that language
- Default: []
- Accepts: String, Object or Array of Strings and/or Objects
Append a script
element to the head of each page with a code
element on it.
If a URL string is given, a src="stringValue"
attribute will be automatically added.
If an object is given, each key will be added as an attribute with the key's value as the attribute value.
<!--
{
src: '/scripts/foo.js',
defer: ''
}
-->
<script src="/scripts/foo.js" defer=""></script>
- Default: []
- Accepts: String, Object or Array of Strings and/or Objects
Append a link
element to the head of each page with a code
element on it.
If a URL string is given, href="stringValue"
and rel="stylesheet"
attributes will be automatically added.
If an object is given, each key will be added as an attribute with the key's value as the attribute value.
<!--
{
href: '/styles/prism-dark.css',
media: '(prefers-color-scheme: dark)'
}
-->
<link rel="stylesheet" href="/styles/prism-dark.css" media="(prefers-color-scheme: dark)">
The global options defined in your Eleventy config file can be superseded on a page-by-page or element-by-element basis.
The following attributes will supersede the accompanying global option on that element and any children of that element:
class="language-xxx"
data-color-previews="true/false"
data-highlight-syntax="true/false"
data-language-labels="true/false"
data-line-numbers="true/false"
The official syntax highlighting plugin only applies to Markdown, Nunjucks and Liquid templates, the last two using shortcodes. Code Style Hooks uses a transform to look at all your HTML files and add Prism tags to all code
elements automatically without shortcodes. This makes the official plugin more efficient but Code Style Hooks more convenient.
See below for the differences in major options available:
Option | Official Plugin | Code Style Hooks |
---|---|---|
Line highlighting | ✓ yes | ✗ no |
Trim whitespace | ✓ yes | ✗ no |
Colour previews | ✗ no | ✓ yes |
Auto add CSS/JS | ✗ no | ✓ yes |
The main difference between Prism and Code Style Hooks is that Prism runs on the client side whereas Code Style Hooks runs at build time. This means that Prism plugins listed on prismjs.com likely won't work since they expect a DOM.
The only other notable difference is that Code Style Hooks does not remove existing HTML and even allows code
blocks to be nested.