# Code Blocks

> Code blocks with copy buttons, package manager tabs and terminal windows.

A code block is a `<pre><code>`, styled by the theme in its mono font. Every code block gets a copy button and a button that wraps long lines. Escape the code inside it: `&lt;` for `<` and `&amp;` for `&`. Tabs of code blocks are covered under [Code Tabs](/authoring/rich-elements/#code-tabs).

**HTML**

```html
<pre><code>const greeting = "&lt;hello&gt;"</code></pre>
```

**Markdown**

````md
```
const greeting = "<hello>"
```
````

Renders as:

```
const greeting = "<hello>"
```

## Syntax Highlighting

A `language-*` class on the `<code>` colors the block at build time with VS Code's TextMate grammars, the same output as Shiki, in a light and a dark theme that follow the reader's (see [Syntax Themes](/customization/syntax-themes/)). Over 220 languages are built in, with their usual aliases (`ts`, `sh`, `yml`); an unknown one, or a block holding markup of its own, stays plain.

**HTML**

```html
<pre><code class="language-rust">fn main() {
    println!("hello");
}</code></pre>
```

**Markdown**

````md
```rust
fn main() {
    println!("hello");
}
```
````

Renders as:

```rust
fn main() {
    println!("hello");
}
```

## Titles

`data-title` on the `<pre>` gives the block a title bar, usually the file name; it works whether or not the block is highlighted.

**HTML**

```html
<pre data-title="htmlpress.yaml"><code class="language-yaml">title: Htmlpress</code></pre>
```

**Markdown**

````md
```yaml title="htmlpress.yaml"
title: Htmlpress
```
````

Renders as:

**htmlpress.yaml**

```yaml
title: Htmlpress
```

## Line Highlighting

`data-lines` on a highlighted block marks lines, counted from 1: single lines and ranges, comma-separated.

**HTML**

```html
<pre><code class="language-js" data-lines="2">…</code></pre>
```

**Markdown**

````md
```js lines="2"
…
```
````

```js
const a = 1
const b = 2
const c = 3
```

## Word Highlighting

`data-words` on a highlighted block marks every occurrence of each comma-separated word. A word the grammar splits into two tokens is not marked.

**HTML**

```html
<pre><code class="language-js" data-words="greeting">…</code></pre>
```

**Markdown**

````md
```js words="greeting"
…
```
````

```js
const greeting = "hello"
console.log(greeting)
```

## Line Numbers

`data-line-numbers` on a highlighted block numbers its lines; `data-line-numbers="10"` starts from 10. The copy button leaves the numbers out.

```js
const a = 1
const b = 2
```

## Diff Lines

`data-add` and `data-remove` on a highlighted block mark lines as added or removed, with a `+` or `−` the copy button leaves out. Inside a [terminal](#terminal), `<ins>` and `<del>` color output green and red.

**HTML**

```html
<pre><code class="language-js" data-remove="1" data-add="2">…</code></pre>
```

**Markdown**

````md
```js remove="1" add="2"
…
```
````

```js
const port = 8080
const port = 8000
serve(port)
```

## Focus Lines

`data-focus` on a highlighted block dims every other line, until the reader points at the block.

```js
import { build } from "htmlpress"
await build("docs")
console.log("done")
```

## Error and Warning

`data-error` and `data-warning` mark lines in red and yellow.

```js
undefinedCall()
const unused = 1
```

Every line mark takes the same list as `data-lines`, such as `2,4-5`, and an invalid list fails the build.

## Collapsible Code

A `<details>` around a long block hides it behind its `<summary>`:

**HTML**

```html
<details>
  <summary>The full config</summary>
  <pre><code>…</code></pre>
</details>
```

**Markdown**

````md
:::details[The full config]
```
…
```
:::
````

`data-collapse` on the `<pre>` shows only its first lines, with an Expand bar under the block for the rest; without the script, the block scrolls instead. A block no taller than that gets no bar.

**HTML**

```html
<pre data-collapse="5"><code class="language-yaml">…</code></pre>
```

**Markdown**

````md
```yaml collapse="5"
…
```
````

```yaml
steps:
  build: 1
  build: 2
  build: 3
  build: 4
  build: 5
  build: 6
  build: 7
  build: 8
  build: 9
  build: 10
  build: 11
  build: 12
```

## ANSI Output

A block in `language-ansi` renders terminal output's color escapes, written raw or as `&#27;`: the 16 colors, the 256-color and true-color forms, bold, dim, italic, underline and strikethrough. Other escapes are dropped.

**HTML**

```html
<pre><code class="language-ansi">&#27;[32m✓&#27;[0m built 48 pages
&#27;[1;31merror&#27;[0m: index.html: no title</code></pre>
```

**Markdown**

```html
<pre><code class="language-ansi">&#27;[32m✓&#27;[0m built 48 pages
&#27;[1;31merror&#27;[0m: index.html: no title</code></pre>
```

Renders as:

```ansi
✓ built 48 pages
error: index.html: no title
```

## Language Icons

A titled block shows its language's logo in the title bar: TypeScript, JavaScript, React (`jsx`, `tsx`), Python, Rust and shell, the set Livemark shows, or a generic file icon for any other language.

**main.rs**

```rust
fn main() {}
```

**build.sh**

```sh
htmlpress build docs
```

## TypeScript Support

> **Not planned**
>
> Type information on hover, as Twoslash gives, needs the TypeScript compiler, which a single Rust binary does not carry. A TypeScript block is highlighted like any other.

## NPM Commands

Write one `npm` or `npx` command inside `<htmlpress-package-tabs>` and the build turns it into tabs for npm, pnpm, yarn and bun, synced across the site. Other lines stay as written.

**HTML**

```html
<htmlpress-package-tabs>
  <pre><code>npm install --save-dev gethtmlpress</code></pre>
</htmlpress-package-tabs>
```

**Markdown**

````md
```npm
npm install --save-dev gethtmlpress
```
````

Renders as:

**npm**

```
npm install --save-dev gethtmlpress
```

**pnpm**

```
pnpm add -D gethtmlpress
```

**yarn**

```
yarn add -D gethtmlpress
```

**bun**

```
bun add -D gethtmlpress
```

## Terminal

A `<pre>` inside `<htmlpress-terminal>` looks like a terminal window, dark in both themes and named by `title`. Inside it, `<kbd>` is a typed command (the prompt is added), `<samp>` plain output, and `<ins>`, `<del>` and `<mark>` green, red and yellow output.

**HTML**

```html
<htmlpress-terminal title="zsh">
  <pre><kbd>htmlpress build docs</kbd>
<samp>built 7 pages…</samp>
<ins>✓ ready</ins></pre>
</htmlpress-terminal>
```

**Markdown**

```html
<htmlpress-terminal title="zsh">
  <pre><kbd>htmlpress build docs</kbd>
<samp>built 7 pages…</samp>
<ins>✓ ready</ins></pre>
</htmlpress-terminal>
```

Renders as:

```
$ htmlpress build docs
built 7 pages and 0 files into docs/.htmlpress/build
✓ ready
✗ 1 page failed
! 1 warning
```
