Skip to content

An 11ty plugin that adds classes to code elements at build time using Prism so you can highlight syntax using CSS

License

Notifications You must be signed in to change notification settings

JKC-Codes/eleventy-plugin-code-style-hooks

Repository files navigation

Code Style Hooks

An 11ty plugin that adds classes to code elements at build time using Prism so you can highlight syntax using CSS.

Installation

npm install eleventy-plugin-code-style-hooks

Usage

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>

PostHTML

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;
    }
  });
}

Configuration

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'
  });
}

colorPreviews

  • Default: True
  • Accepts: Boolean
  • Hooks: Colours have a span around them with 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.

defaultLanguage

  • 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.

highlightSyntax

  • Default: True
  • Accepts: Boolean
  • Hooks: see Prism FAQs

Turn syntax highlighting from Prism on or off. See https://prismjs.com/ for more information.

languageLabels

  • Default: True
  • Accepts: Boolean
  • Hooks: 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.

lineNumbers

  • Default: True
  • Accepts: Boolean
  • Hooks: 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.

markdownTrimTrailingNewline

  • 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;
    }
  });
}

prism

  • 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.

removeRedundancy

  • Default: True
  • Accepts: Boolean

Remove attributes used by Code Style Hooks that aren't needed after builds.

Removes:

  • data-color-previews="true/false" attributes
  • data-highlight-syntax="true/false" attributes
  • data-language-labels="true/false" attributes
  • data-line-numbers="true/false" attributes
  • language-xxx classes from non pre or code elements
  • language-xxx classes on code after the first language class
  • language-xxx classes from pre elements if there are no code children or if code children don't use that language

scripts

  • 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>

styles

  • 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)">

Inline Options

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"

Differences

Official Plugin

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

Prism JS

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.

Licence

MPL-2.0

About

An 11ty plugin that adds classes to code elements at build time using Prism so you can highlight syntax using CSS

Resources

License

Stars

Watchers

Forks