An 11ty plugin that adds classes to code elements at build time using Prism so you can highlight syntax using CSS
MPL-2.0 License
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'
});
}
class="token color"
containing an empty span at the start with class="color-preview"
and style="--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.
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.
Turn syntax highlighting from Prism on or off. See https://prismjs.com/ for more information.
code
and pre
elements have a data-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.
code
and pre
elements have class="line-numbers"
and code
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.
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;
}
});
}
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.
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 non pre
or code
elementslanguage-xxx
classes on code
after the first language classlanguage-xxx
classes from pre
elements if there are no code
children or if code
children don't use that languageAppend 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>
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.