Liking cljdoc? Tell your friends :D

x-code

A code-display Web Component: it reads source code from its own light-DOM text content, tokenizes it with a built-in syntax highlighter, and renders it as a themable code block with optional line numbers, soft-wrapping, a header bar with a copy button, and a collapsible long-snippet mode.

The component is statelessDOM = f(attributes, properties). The expand/collapse state lives in the expanded attribute, never in a mutable field.

Tag

<x-code language="js">
const greeting = "hello";
console.log(greeting);
</x-code>

The code is the element's text content. Leading/trailing blank lines are dropped and shared indentation is stripped, so code can be indented to match the surrounding markup.

Literal HTML in the content is parsed by the browser before x-code ever sees it. To show markup, escape it (&lt;div&gt;) or set the code property/attribute instead.

Attributes

NameTypeDefaultDescription
languagestringtextjs, json, css, html (plus aliases). Anything else = no tokens.
filenamestring""Shown on the left of the header bar.
show-copybooleanabsentShows a copy-to-clipboard button in the header.
line-numbersbooleanabsentRenders a non-selectable line-number gutter.
wrapbooleanabsentSoft-wraps long lines instead of scrolling horizontally.
max-linesnumber0When positive and exceeded, the block collapses behind a fade. 0 = off.
expandedbooleanabsentWhether a collapsible block is expanded. Toggled by the expander.
codestringCode source as an attribute. Overridden by the code property; overrides text content.

Properties

PropertyTypeReflectsDefaultDescription
languagestringlanguage""
filenamestringfilename""
showCopybooleanshow-copyfalse
lineNumbersbooleanline-numbersfalse
wrapbooleanwrapfalse
maxLinesnumbermax-lines0
expandedbooleanexpandedfalse
codestring— (none)Property-only override. Getter reports the effective code (property → code attribute → text content). Setting it re-renders.

Code source precedence

The rendered code is resolved in this order:

  1. The code property (if set to a string).
  2. The code attribute.
  3. The element's light-DOM textContent.

A MutationObserver re-renders the block whenever the light-DOM text changes.

Events

EventCancelableDetailWhen it fires
x-code-copyno{ code: string }The composed copy button reported a successful copy.
x-code-toggleno{ expanded: boolean }The collapse/expand state changed via the expander.

The inner x-copy still emits its own x-copy-* events (they are composed and bubble through); listen for the x-code-* events for a stable API.

Methods

MethodReturnsDescription
expand()voidSets the expanded attribute.
collapse()voidRemoves the expanded attribute.

Parts

PartDescription
containerOuter bordered box.
headerHeader bar — present only when filename is set or show-copy is on.
filenameFilename text in the header.
languageLanguage badge — appears in the header when show-copy is on and no filename is given.
copy-wrapWrapper around the copy button.
copyThe composed x-copy element. Its inner button is reachable via [part=copy]::part(trigger).
bodyPositioning context for the collapse fade.
scrollScrollable, focusable code region.
pre / codeThe <pre> / <code> elements.
lineOne rendered line (gutter + content).
gutterPer-line line-number cell.
line-contentPer-line tokenized content.
fadeGradient overlay shown while collapsed.
expander"Show more" / "Show less" button.

Token spans inside line-content carry classes tok-comment, tok-string, tok-keyword, tok-number, tok-punct, tok-tag, etc.

CSS custom properties

VariableDefaultDescription
--x-code-bgvar(--x-color-surface, …)Block background.
--x-code-fgvar(--x-color-text, …)Default text colour.
--x-code-bordervar(--x-color-border, …)Border colour.
--x-code-mutedvar(--x-color-text-muted, …)Gutter / badge colour.
--x-code-radiusvar(--x-radius-md, 8px)Corner radius.
--x-code-fontvar(--x-font-family-mono, …)Monospace font stack.
--x-code-font-size0.8125remCode font size.
--x-code-line-height1.6Code line height.
--x-code-tab-size2Tab width.
--x-code-token-commentgreyComment colour.
--x-code-token-stringgreenString / template colour.
--x-code-token-keywordredKeyword / at-rule colour.
--x-code-token-numberblueNumber colour.
--x-code-token-punctmutedPunctuation colour.
--x-code-token-taggreenHTML tag colour.
--x-code-token-propertyblueCSS property / JSON key.
--x-code-token-attr-valuedark blueHTML attribute value.
--x-code-token-entityblueHTML entity colour.

All token colours have separate light and dark fallbacks via @media (prefers-color-scheme: dark) and can be overridden per instance.

Tokenizer & languages

The tokenizer is in-house, regex-based, and intentionally lightweight. It supports js, json, css, and html; every other language renders as plain monospace text. Known limitations:

  • It is a highlighter, not a parser — there is no nested-language handling (<script> / <style> bodies inside HTML stay plain HTML text).
  • JavaScript regex literals are not recognised; / is treated as punctuation.
  • The CSS property heuristic (an identifier followed by :) can occasionally mis-colour a pseudo-class selector.

These trade-offs keep the highlighter small and dependency-free.

Accessibility

  • The scrollable region is a focusable role="region" with an aria-label (the filename, the language, or "Code").
  • Line-number cells are aria-hidden and not selectable, so copying or selecting code never picks up the numbers.
  • The expander is a real <button> carrying aria-expanded.
  • The copy button is provided by x-copy, which is itself a <button>.
  • Animations honour prefers-reduced-motion.

Examples

Line numbers + copy button

<x-code language="js" filename="greet.js" line-numbers show-copy>
function greet(name) {
  return `Hello, ${name}!`;
}
</x-code>

Collapsible long snippet

<x-code language="css" max-lines="6">
/* …a long stylesheet… */
</x-code>

Soft-wrapping

<x-code language="json" wrap>
{ "a very": "long single line that should fold instead of scrolling" }
</x-code>

Setting code programmatically

const el = document.querySelector('x-code');
el.language = 'js';
el.code = 'const x = 1;';

Can you improve this documentation?Edit on GitHub

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close