Skip to content

Code Blocks

This library can also render static code blocks. The code blocks require no JavaScript to work and support some features that can’t be added to editors. Every code block on this page has been generated with this library.

Below you can toggle most of the boolean options for every code block on this page.

renderCodeBlock() renders a code block as an HTML string. This is intended to be ran on a server to generate static HTML.

import { renderCodeBlock } from "prism-code-editor/ssr"
const html = renderCodeBlock({
language: "javascript",
code: "const foo = 'bar'"
})

The only argument to renderCodeBlock() is a CodeBlockOptions object. These options include a few properties not present in EditorOptions such as lineNumberStart, preserveIndent, and guideIndents.

When indentation preservation is enabled, wrapped lines get the same indentation as their parent line. This can greatly increase the readability of code with many wrapped lines and is enabled by default when wordWrap is enabled.

<p>
Here's a very long paragraph that will probably be split across multiple lines. This should show you what <code>preserveIndent</code> does.
</p>

lineNumberStart can be used to configure the line number of the first line. This defaults to 1, obviously.

import { renderCodeBlock } from "prism-code-editor/ssr"
const html = renderCodeBlock({
language: "javascript",
code: "const foo = 'bar'",
lineNumbers: true,
lineNumberStart: 5
})

Unlike the indentation guides in the editors, these are rendered as a repeating linear gradient on .pce-line::after. This has the advantage of not requiring any extra elements and supporting wordWrap.

In addition to prism-code-editor/layout.css, the code blocks require styles from prism-code-editor/code-block.css.

The code blocks have a nearly identical layout to the editors to make them compatible with the styles from prism-code-editor/layout.css. This means the styling guide mostly applies to code blocks as well. The only difference is that the two outermost elements use pre and code tags. Below is the full DOM structure.

<pre class="prism-code-editor language-[lang] [extra-classes]">
<!-- ::before pseudo element is the line number background -->
<code class="pce-wrapper">
<div class="pce-overlays"></div>
<div class="pce-line">
<!-- ::before pseudo element is the line number -->
<!-- Prism tokens for the line -->
<!-- ::after pseudo element has indentation guides if any -->
</div>
<div class="pce-line"></div>
<!-- More lines... -->
</code>
</pre>
  • show-line-numbers if line numbers are enabled.
  • pce-wrap if word wrap is enabled, and pce-nowrap if not.
  • pce-preserve if indentation is preserved.
  • pce-guides if indentation guides are enabled.
  • pce-rtl if the rtl option is true.

The forEachCodeBlock() function can be used to run a callback for each PrismCodeBlock under a specified root. The function returns an array of all visited code blocks in document order. The same code block is never visited twice even when forEachCodeBlock() is called multiple times.

forEachCodeBlock() can be used to add code block with addCodeBlock().

import "prism-code-editor/copy-button.css"
import { addCopyButton, forEachCodeBlock } from "prism-code-editor/code-blocks"
const codeBlocks = forEachCodeBlock(document, codeBlock => {
addCopyButton(codeBlock)
})

The second parameter to addCodeBlock() can be used to customize the copied text. If you’re using line highlighting with one markdown plugins for example, you may want to use omitLines() to remove lines marked as deleted from the copied text.

const codeBlocks = forEachCodeBlock(document, codeBlock => {
addCopyButton(codeBlock, omitLines(".deleted"))
})

highlightBracketPairsOnHover() will add highlighting to bracket pairs when hovered. Clicking on a pair keeps it highlighted and clicking anywhere inside the code block removes the highlight. It doesn’t require rainbow brackets to work. You can try it on any code block on this page.

const string = /(["'])(?:\\[\s\S]|(?!\1)[^\\\n])*\1/

highlightTagPairsOnHover() is very similar to highlightBracketPairsOnHover(), but highlights the tag name in matching tags instead. You can try it on the DOM structure code block.

The addOverlay() utility can be used to add overlays to code blocks as well. The only difference to adding overlays to editors is that code blocks don’t have pointer-events: none or user-select: none.

If you have complicated code you want to describe, but without cluttering the code up with comments, you can show descriptions on hover instead with addHoverDescriptions(). Below is a very simple example. Try hovering a string token.

import "prism-code-editor/copy-button.css"
import {
addCopyButton,
forEachCodeBlock,
addHoverDescriptions
} from "prism-code-editor/code-blocks"
const codeBlocks = forEachCodeBlock(document, codeBlock => {
addCopyButton(codeBlock)
addHoverDescriptions(
codeBlock,
(types, language, text, element) => {
if (types.includes("string")) return ["This is a string token."]
}
)
})

The callback function passed receives 4 arguments:

  • types: Array with the token’s type as the first element, followed by any alises.
  • language: The language at the token’s position.
  • text: The textContent of the token.
  • element: The <span> element of the hovered token.

If it returns an array of children, those children are appended to the tooltip that’s then shown.

The library only ensures the tooltip is correctly positioned. You must style it yourself. You can use the selector .pce-hover-tooltip to target the container the content is appended to.

.pce-hover-tooltip {
/* Recommended styles */
position: sticky;
left: 0.5em;
right: 0.5em;
box-sizing: border-box;
/* Overriding the monospace font */
font-family: Arial, Helvetica, sans-serif;
white-space: normal;
background: var(--widget__bg);
padding: 0.3em 0.4em;
border: 1px solid var(--widget__border);
border-radius: 0.3em;
overflow-y: auto;
}
/* Show users they can hover some tokens */
pre.prism-code-editor .token.string {
border-bottom: 1px dotted #0000;
transition: border-color 0.2s;
}
pre.prism-code-editor:hover .token.string {
border-color: #888;
}

To ensure the tooltip doesn’t get too big and overflows, max-width and max-height are added as inline styles to the tooltip. If you want to set your own max-width or max-height, you can use the third argument to addHoverDescriptions(). The values you provide are added as extra arguments to the CSS min() function, so multiple values can be comma separated.

addHoverDescriptions(
codeBlock,
(types) => { ... },
{
maxWidth: "40ch + 50px",
maxHeight: "20em, 300px"
}
)

Just like the SSR API, these code blocks are meant to be usable with many technologies. It’s your job to integrate this API with the server-side framework or static-site generator you’re using. Here’s a working example for Astro.

There are markdown plugins for both rehype and marked that highlight fenced code blocks. These use renderCodeBlock() under the hood. Read their documentation to learn more.