npm package: @profpowell/code-block
Description: A code block web component with syntax highlighting (via highlight.js), copy functionality, line numbers, and theme support
Author: Prof Thomas Powell
Latest version: 2.7.1

# code-block

A feature-rich code block web component with syntax highlighting, copy-to-clipboard, and extensive customization options. Designed for tutorials, documentation, and educational content.

## Highlights

> **[See the live demo](demo.html)** for all features in action

| Feature | Description |
|---------|-------------|
| [**Multi-File Tabs**](demo.html#multi-file-tabs) | Tabbed interface for related code files with `<code-block-group>` |
| [**Line Highlighting**](demo.html#line-highlighting) | Draw attention to specific lines with `highlight-lines="3,5-7"` |
| [**Focus Mode**](demo.html#focus-mode) | Dim non-highlighted lines with `focus-mode` for emphasis |
| [**Share & Download**](demo.html#share-download) | One-click download or open in CodePen |
| [**Collapsible Blocks**](demo.html#collapsible) | Expandable code with "Show more" for long snippets |
| [**Lazy Loading**](demo.html#lazy-highlighting) | Defer syntax highlighting until visible for performance |
| [**Diff Support**](demo.html#diff-support) | Visualize code changes with +/- line highlighting |
| [**Custom Themes**](demo.html#css-custom-properties) | Full CSS custom property support for branding |
| [**Light & Dark**](demo.html#themes) | GitHub-inspired color schemes |

## Features

- **13 Web Languages** - HTML, CSS, JS, JSON, YAML, PHP, and more
- **Line Numbers** - Optional line number display
- **Filename Headers** - Show file paths in the header
- **Copy to Clipboard** - One-click copy with visual feedback
- **Word Wrap** - Toggle between scroll and wrap for long lines
- **Shadow DOM** - Encapsulated styles that won't conflict with your app
- **Accessible** - ARIA labels, keyboard focus, screen reader support
- **TypeScript Support** - Full type definitions included

## Installation

### npm

```bash
npm install @profpowell/code-block
```

### Git Submodule

Add this repository as a git submodule to your project:

```bash
git submodule add https://github.com/ProfPowell/code-block.git lib/code-block
cd lib/code-block && npm install
```

Then import the component:

```javascript
import './lib/code-block/code-block.js';
```

## Usage

Once imported, the `<code-block>` custom element is automatically registered:

```html
<code-block language="javascript">
function greet(name) {
  return `Hello, ${name}!`;
}
</code-block>
```

### With Custom Label

```html
<code-block language="python" label="Data Processing">
import pandas as pd

df = pd.read_csv('data.csv')
print(df.head())
</code-block>
```

### Dark Theme

```html
<code-block language="css" theme="dark">
.container {
  display: grid;
  gap: 1rem;
}
</code-block>
```

### With Line Numbers

```html
<code-block language="javascript" show-lines>
class EventEmitter {
  constructor() {
    this.events = new Map();
  }

  on(event, callback) {
    if (!this.events.has(event)) {
      this.events.set(event, []);
    }
    this.events.get(event).push(callback);
  }
}
</code-block>
```

### Combined Options

```html
<code-block language="typescript" theme="dark" show-lines label="User Service">
interface User {
  id: number;
  name: string;
}

class UserService {
  async getUser(id: number): Promise<User> {
    const response = await fetch(`/api/users/${id}`);
    return response.json();
  }
}
</code-block>
```

## Supported Languages

The component includes an optimized bundle with 13 web development languages:

| Language | Values |
|----------|--------|
| HTML | `html`, `markup` |
| XML | `xml` |
| XHTML | `xhtml` |
| SVG | `svg` |
| CSS | `css` |
| JavaScript | `javascript`, `js` |
| JSON | `json` |
| YAML | `yaml`, `yml` |
| PHP | `php` |
| HTTP | `http` |
| Diff | `diff` |
| Plain Text | `plaintext`, `text`, `txt` |
| CSV | `csv` |

Additional languages can be added by importing them from highlight.js.

## API

### Attributes

| Attribute | Type | Default | Description |
|-----------|------|---------|-------------|
| `language` | string | `'plaintext'` | Programming language for highlighting |
| `label` | string | `language` | Label displayed in the header |
| `theme` | `'light'` \| `'dark'` | `'light'` | Color theme |
| `show-lines` | boolean | `false` | Display line numbers |
| `filename` | string | — | File path shown in header |
| `highlight-lines` | string | — | Lines to highlight (e.g., `"3,5-7"`) |
| `focus-mode` | boolean | `false` | Dim non-highlighted lines for emphasis |
| `collapsed` | boolean | `false` | Start in collapsed state |
| `max-lines` | number | `10` | Lines visible when collapsed |
| `max-height` | string | — | Max height with scrolling (e.g., `"300px"`) |
| `wrap` | boolean | `false` | Wrap long lines |
| `copy-text` | string | `'Copy'` | Custom copy button text |
| `copied-text` | string | `'Copied!'` | Custom success message |
| `show-share` | boolean | `false` | Show share button |
| `show-download` | boolean | `false` | Show download button |
| `lazy` | boolean | `false` | Defer highlighting until visible |

### Methods

| Method | Returns | Description |
|--------|---------|-------------|
| `copyCode()` | `Promise<void>` | Copy code to clipboard |
| `setCode(code)` | `void` | Update code content |
| `getCode()` | `string` | Get current code |
| `downloadCode()` | `void` | Download as file |
| `openInCodePen()` | `void` | Open in CodePen |
| `toggleCollapsed()` | `void` | Toggle collapsed state |
| `render()` | `void` | Re-render the component |

### CSS Custom Properties

The component exposes 60+ CSS custom properties for full theme control. Properties marked "theme-aware" adapt automatically to light/dark mode.

#### Container & Layout

| Property | Default | Description |
|----------|---------|-------------|
| `--cb-bg` | theme-aware | Outer container background |
| `--cb-code-bg` | theme-aware | Code area background |
| `--cb-border-color` | theme-aware | Border color used throughout |
| `--cb-border-radius` | `8px` | Outer container border radius |
| `--cb-margin` | `1rem 0` | Component outer margin |
| `--cb-shadow` | theme-aware | Box shadow on dropdown menus |

#### Typography

| Property | Default | Description |
|----------|---------|-------------|
| `--cb-font-family` | `Consolas, Monaco, Courier New, monospace` | Code font |
| `--cb-ui-font-family` | `-apple-system, BlinkMacSystemFont, Segoe UI, sans-serif` | UI font (buttons, menus) |
| `--cb-font-size` | `0.875rem` | Base code font size |
| `--cb-text-color` | theme-aware | Default code text color |
| `--cb-line-height` | `1.6` | Code line height |

#### Header

| Property | Default | Description |
|----------|---------|-------------|
| `--cb-header-bg` | theme-aware | Header bar background |
| `--cb-header-padding` | `0.5rem 1rem` | Header padding |
| `--cb-label-color` | theme-aware | Language label and icon color |
| `--cb-filename-color` | theme-aware | Filename text color |

#### Buttons

| Property | Default | Description |
|----------|---------|-------------|
| `--cb-button-bg` | theme-aware | Button background |
| `--cb-button-color` | theme-aware | Button text color |
| `--cb-button-border` | theme-aware | Button border color |
| `--cb-button-border-width` | `1px` | Button border width |
| `--cb-button-border-style` | `solid` | Button border style (`solid`, `none`, etc.) |
| `--cb-button-radius` | `4px` | Border radius for copy and action buttons |
| `--cb-button-padding` | `4px 12px` | Copy button padding |
| `--cb-button-font-size` | `0.75rem` | Copy button font size |
| `--cb-button-hover-bg` | theme-aware | Copy button hover background |
| `--cb-button-hover-border` | theme-aware | Copy button hover border color |
| `--cb-action-button-hover-bg` | theme-aware | Icon button hover background |
| `--cb-success-color` | `#238636` | Copied-success state color |
| `--cb-error-color` | `#da3633` | Copy-failed state color |
| `--cb-focus-color` | theme-aware | Focus ring color |

#### Code Area & Line Numbers

| Property | Default | Description |
|----------|---------|-------------|
| `--cb-code-padding` | `1rem` | Code area and gutter padding |
| `--cb-line-numbers-bg` | theme-aware | Line-numbers gutter background |
| `--cb-line-numbers-color` | theme-aware | Line-numbers text color |

#### Syntax Highlighting

| Property | Default (Light / Dark) | Description |
|----------|----------------------|-------------|
| `--cb-keyword` | `#d73a49` / `#ff7b72` | Keywords |
| `--cb-string` | `#22863a` / `#a5d6ff` | Strings |
| `--cb-comment` | theme-aware | Comments |
| `--cb-function` | `#6f42c1` / `#d2a8ff` | Function names |
| `--cb-number` | `#005cc5` / `#79c0ff` | Numbers |
| `--cb-attribute` | `#005cc5` / `#79c0ff` | HTML/XML attributes |
| `--cb-tag` | `#22863a` / `#7ee787` | HTML/XML tags |
| `--cb-meta` | `#e36209` / `#ffa657` | Meta/preprocessor tokens |
| `--cb-builtin` | `#d73a49` / `#ffa198` | Built-in names |

See `docs/api.html` for the complete reference including diff, expand/collapse, scrollbar, highlight, and focus-mode properties.

#### Example: Vanilla Breeze Integration

```css
code-block {
  --cb-button-radius: 0;
  --cb-button-border-style: none;
  --cb-border-radius: 0;
  --cb-ui-font-family: 'Inter', sans-serif;
  --cb-font-family: 'JetBrains Mono', monospace;
}
```

### Programmatic Usage

```javascript
// Get a reference to a code block
const codeBlock = document.querySelector('code-block');

// Copy code programmatically
await codeBlock.copyCode();

// Update code content dynamically
codeBlock.setCode('const updated = true;');

// Get current code
const code = codeBlock.getCode();

// Get all supported languages (static method)
const languages = CodeBlock.getSupportedLanguages();
console.log(`Supports ${languages.length} languages`);
```

## Server-Side Rendering (SSR)

For static sites and documentation, code blocks can be pre-rendered at build time using the SSR module. This eliminates client-side syntax highlighting and displays code instantly using Declarative Shadow DOM.

### Installation

The SSR module is included in the package — no extra install needed:

```javascript
import { prerenderCodeBlock, prerenderCodeBlocksInHtml } from '@profpowell/code-block/ssr'
```

### Single Block

```javascript
const html = prerenderCodeBlock({
  code: 'const x = 42;',
  language: 'javascript',
  theme: 'dark',
  showLines: true,
  filename: 'app.js',
})
// Returns complete <code-block data-ssr> with Declarative Shadow DOM
```

### Process an HTML Page

```javascript
const page = prerenderCodeBlocksInHtml(rawHtml)
// Finds all <code-block> elements and pre-renders them
// Skips blocks with src attribute or data-ssr (already processed)
```

### SSG Integration (Cook, Eleventy, etc.)

The SSR module runs in Node.js and can be used as a build step in any static site generator:

```javascript
// Example Cook plugin
import { prerenderCodeBlocksInHtml } from '@profpowell/code-block/ssr'

// Process HTML after all other transforms
file.src = prerenderCodeBlocksInHtml(file.src)
```

### How It Works

1. **Build time**: `prerenderCodeBlock()` runs highlight.js in Node.js and generates the full shadow DOM HTML
2. **Output**: A `<code-block data-ssr>` element with `<template shadowrootmode="open">` containing pre-rendered styles and highlighted code, plus a `<textarea>` preserving raw code for copy-to-clipboard
3. **Browser**: The Declarative Shadow DOM template is parsed into a real shadow root — code is visible immediately, before any JavaScript loads
4. **Hydration**: When the component JS loads, it detects `data-ssr`, skips re-rendering, and attaches interactive event listeners (copy, download, share, expand/collapse)

### Options

`prerenderCodeBlock()` accepts all the same options as the component's HTML attributes:

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `code` | string | required | Source code to highlight |
| `language` | string | `'plaintext'` | Language for highlighting |
| `theme` | string | `'light'` | `'light'` or `'dark'` |
| `filename` | string | — | Filename in header |
| `label` | string | — | Custom label |
| `showLines` | boolean | `false` | Show line numbers |
| `highlightLines` | string | — | Lines to highlight, e.g. `"2,4-6"` |
| `focusMode` | boolean | `false` | Dim non-highlighted lines |
| `collapsed` | boolean | `false` | Start collapsed |
| `maxLines` | number | `10` | Visible lines when collapsed |
| `maxHeight` | string | — | Max height with scroll |
| `wrap` | boolean | `false` | Word wrap |
| `noCopy` | boolean | `false` | Hide copy button |
| `copyText` | string | `'Copy'` | Copy button text |
| `showShare` | boolean | `false` | Show share button |
| `showDownload` | boolean | `false` | Show download button |

## Demo

Open `demo.html` in a browser to see all features in action:

- [Multi-file tabbed interface](demo.html#multi-file-tabs)
- [Line highlighting](demo.html#line-highlighting)
- [Focus mode](demo.html#focus-mode)
- [Share & download buttons](demo.html#share-download)
- [Collapsible code blocks](demo.html#collapsible)
- [Lazy loading for performance](demo.html#lazy-highlighting)
- [Diff visualization](demo.html#diff-support)
- [CSS custom properties](demo.html#css-custom-properties)
- [Light and dark themes](demo.html#themes)
- Complete API reference

## Browser Support

Works in all modern browsers that support:
- Custom Elements v1
- Shadow DOM v1
- ES6 Modules
- Clipboard API

## Dependencies

- [highlight.js](https://highlightjs.org/) ^11.11.1 - Syntax highlighting

## License

MIT License - see [LICENSE](LICENSE) for details.