# astro-better-code-blocks

Remark/rehype plugins for enhanced code blocks with copy button, line highlighting, diff mode, collapsible sections, file titles, and shell session formatting.

> For the index of this section of the site, see [llms.txt](https://lambdalatitudinarians.org/llms.txt)

# astro-better-code-blocks

Remark and rehype plugins that enhance code blocks in Astro MDX files. Adds a copy-to-clipboard button, syntax highlighting via Prism, and a meta string mini-language for titles, line highlights, collapsible sections, and diff overlays. Also formats shell session blocks with distinct prompt styling.

Current version: **0.1.2** --[npm](https://www.npmjs.com/package/astro-better-code-blocks)

## Installation

```shell-session
$ npm install astro-better-code-blocks @astrojs/prism prismjs
```

Import the CSS in your global stylesheet:

```css
@import "astro-better-code-blocks/style.css";
```

## Setup

### Configure the plugins

In `astro.config.ts`:

astro.config.ts

astro.config.ts

```typescript
import { defineConfig } from 'astro/config';
import { rehypeCodeBlocks, remarkShellSession } from 'astro-better-code-blocks';

export default defineConfig({
  markdown: {
    syntaxHighlight: false,
    remarkPlugins: [remarkShellSession],
    rehypePlugins: [rehypeCodeBlocks],
  },
});
```

### Import the CSS

In your root layout or global stylesheet:

```css
@import "astro-better-code-blocks/style.css";
```

## Meta string features

All features are activated by keywords or patterns in the opening code fence. They can be combined freely on the same block.

### Title tab

`title="filename"` renders a filename tab above the code block.

````text
```ts title="src/lib/auth.ts"
````

src/lib/auth.ts

src/lib/auth.ts

```typescript
export async function verifyToken(token: string) {
  const payload = await decode(token);
  return payload.sub;
}
```

### Line highlighting

`{lines}` highlights specific lines with a yellow tint and a left accent bar. Accepts individual lines and ranges separated by commas.

````text
```ts {2,6-8}
````

```typescript
import { defineConfig } from 'astro/config';import { rehypeCodeBlocks, remarkShellSession } from 'astro-better-code-blocks';export default defineConfig({  markdown: {    remarkPlugins: [remarkShellSession],    rehypePlugins: [rehypeCodeBlocks],  },});
```

### Collapsible sections

`[lines]` hides a range of lines behind an expandable toggle. Use this to keep examples focused while still making the full code accessible.

````text
```ts [4-8]
````

```typescript
import { defineConfig } from 'astro/config';import { rehypeCodeBlocks, remarkShellSession } from 'astro-better-code-blocks';5 hidden linesexport default defineConfig({  markdown: {    remarkPlugins: [remarkShellSession],    rehypePlugins: [rehypeCodeBlocks],    syntaxHighlight: false,  },  integrations: [],});
```

### Diff mode

`diff` colors lines that start with `+` green and lines that start with `-` red. Works on any language — the language sets the syntax highlighting, `diff` adds the color overlay on top.

````text
```ts diff
````

```typescript
-import { oldHelper } from './utils';+import { newHelper } from './helpers';export function processData(input: string) {-  return oldHelper(input);+  return newHelper(input);}
```

### Escape (MDX-safe blocks)

`escape` renders the block using JSX grammar so that MDX component tags like `<Details>` appear as literal text instead of being executed by the MDX compiler. Use this whenever you’re documenting MDX component usage inside an MDX file.

`````text
````mdx escape
`````

```jsx
import Details from 'astro-better-details/Details.astro';

<Details title="Click to expand">
  This content is hidden by default and revealed when clicked.
</Details>
```

Without `escape`, the `<Details>` tag above would render as a live component rather than source code.

### Combining features

All meta keywords compose freely on the same fence:

````text
```ts {2} [5-8] title="astro.config.ts"
````

astro.config.ts

astro.config.ts

```typescript
import { defineConfig } from 'astro/config';import { rehypeCodeBlocks, remarkShellSession } from 'astro-better-code-blocks';export default defineConfig({4 hidden lines  markdown: {    remarkPlugins: [remarkShellSession],    rehypePlugins: [rehypeCodeBlocks],    syntaxHighlight: false,  },});
```

Line 2 is highlighted, lines 5-8 are collapsible, and a title tab appears above.

## Shell session

`shell-session` blocks are processed by `remarkShellSession` before syntax highlighting. Lines that do not already start with `$` or `#` get `$` prepended automatically, so you can write clean commands without repeating the prompt on every line.

Prompt characters are excluded from the copy button — clicking copy gives you the raw commands without the `$` prefix.

```shell-session
$ npm install astro-better-code-blocks
$ npx astro dev
```

### Multi-line commands

Line continuation (`\` at end of a line) and open single-quoted strings are tracked so that continuation lines do not get a prompt prepended.

```shell-session
$ npm install \
    astro-better-code-blocks \
    @astrojs/prism prismjs
$ added 5 packages in 0.8s
```

### Mixed commands and output

Lines that already start with `$` or `#` are left unchanged, so you can mix commands and output freely.

```shell-session
$ git status
$ On branch main
$ nothing to commit, working tree clean
$ git log --oneline -3
$ 1dc6d53 Update llms-for-docs and actions
$ 62ba842 migrate php quickstart to bluehawk
$ 6d4605 migrate laravel quickstart to bluehawk
```

## Plugin options

### rehypeCodeBlocks

```typescript
rehypeCodeBlocks({
  // Languages to skip entirely -- no highlighting, no copy button wrapper.
  // Default: ['mermaid']
  excludeLangs: ['mermaid'],

  // Inject a copy-to-clipboard button into every code block.
  // Default: true
  copyButton: true,

  // Position of the title tab when title="..." is present.
  // Default: { position: 'top' }
  title: { position: 'top' },
})
```

### remarkShellSession

```typescript
remarkShellSession({
  // Prompt string prepended to lines that have no existing prompt.
  // Default: '$ '
  prompt: '$ ',
})
```