shiki-hide-lines
v1.1.0
Published
A Shiki transformer that hides marked lines from rendered code blocks
Maintainers
Readme
shiki-hide-lines
A Shiki transformer that hides marked lines from rendered code blocks while keeping them in the source.
Hide boilerplate (imports, setup, autoloading) that is necessary for execution but distracting for readers.
Install
npm install shiki-hide-linesUsage
Syntax
Mark single lines with // [!code hide] or # [!code hide]:
<?php // [!code hide]
declare(strict_types=1); // [!code hide]
require_once 'vendor/autoload.php'; // [!code hide]
use App\Models\User; // [!code hide]
$user = User::find(1);
echo $user->name;import os # [!code hide]
from pathlib import Path # [!code hide]
print(Path.home())Rendered output shows only the meaningful lines.
Use block markers to hide ranges:
// [!code hide:start]
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
// [!code hide:end]
createApp(App).use(router).mount('#app')# [!code hide:start]
version: '3.8'
services:
# [!code hide:end]
web:
image: nginx:alpine
ports:
- '8080:80'The comment marker adapts to the language:
| Marker | Languages |
|--------|-----------|
| // | PHP, JavaScript, TypeScript, Go, Rust, Java, C |
| # | Python, Ruby, Bash, YAML, Perl, Dockerfile, Elixir |
| -- | SQL, Lua, Haskell, Elm |
| % | LaTeX, TeX, Erlang |
| ; | Lisp, Scheme, Clojure, ASM |
Modes
Fully Hidden (default) — marked lines are completely removed from output:
import { codeToHtml } from 'shiki'
import { transformerHideLines } from 'shiki-hide-lines'
const html = await codeToHtml(code, {
lang: 'php',
theme: 'github-dark',
transformers: [transformerHideLines()]
})Revealable — marked lines are collapsed behind a clickable placeholder:
transformerHideLines({ reveal: true })In reveal mode, a ··· N hidden lines placeholder appears. Clicking it expands the hidden lines and changes the text to ▲ N hidden lines. Clicking again collapses them back.
Custom Placeholder Text
Customize the collapsed and expanded placeholder text:
String template — use {count} for the line count:
transformerHideLines({
reveal: true,
summaryTemplate: '▶ {count} lines collapsed',
expandedSummaryTemplate: '▼ {count} lines shown'
})
// Collapsed: ▶ 3 lines collapsed
// Expanded: ▼ 3 lines shownFunction — full control for i18n or pluralization:
transformerHideLines({
reveal: true,
summaryTemplate: (count) =>
count === 1 ? '1 ligne masquée' : `${count} lignes masquées`,
expandedSummaryTemplate: (count) =>
count === 1 ? '▲ 1 ligne' : `▲ ${count} lignes`
})Custom Marker
Change the marker keyword (default: hide):
transformerHideLines({ marker: 'hidden' })
// Uses: // [!code hidden] and // [!code hidden:start] / // [!code hidden:end]Integration
VitePress
// .vitepress/config.ts
import { transformerHideLines } from 'shiki-hide-lines'
export default defineConfig({
markdown: {
codeTransformers: [
transformerHideLines({ reveal: true })
]
}
})Astro
// astro.config.mjs
import { transformerHideLines } from 'shiki-hide-lines'
export default defineConfig({
markdown: {
shikiConfig: {
transformers: [transformerHideLines()]
}
}
})Nuxt Content
// nuxt.config.ts
import { transformerHideLines } from 'shiki-hide-lines'
export default defineNuxtConfig({
content: {
highlight: {
transformers: [transformerHideLines()]
}
}
})Reveal Mode Setup
Reveal mode requires CSS and a small client-side script for the toggle interaction.
CSS
Import the default stylesheet:
import 'shiki-hide-lines/style.css'Or add it to your CSS manually. The styles use these classes:
| Class | Element | Description |
|-------|---------|-------------|
| has-hidden-lines | <pre> | Code block contains hidden lines |
| hidden-line | <span class="line"> | A hidden line |
| hidden-lines-summary | <span> | Clickable placeholder (role="button") |
| hidden-lines-revealed | <pre> | Toggled to expanded state |
| hidden-lines-collapsed-text | <span> | Text shown when collapsed |
| hidden-lines-expanded-text | <span> | Text shown when expanded |
The default styles respect --vp-code-tab-text-color and --vp-c-brand CSS custom properties for theme compatibility.
Client Script
The toggle requires event delegation for click and keyboard interaction. Choose one:
Option A — Inline script (SSG/SSR sites):
import { getToggleScript } from 'shiki-hide-lines'
// Inject into your page <head> or layout
const script = `<script>${getToggleScript()}</script>`Option B — Direct import (SPA/client-side, e.g. VitePress):
import { setupHiddenLinesToggle } from 'shiki-hide-lines'
setupHiddenLinesToggle()Both options register click and keyboard (Enter/Space) handlers with full ARIA support.
Accessibility
Reveal mode follows the ARIA disclosure pattern:
- Summary elements have
role="button"andtabindex="0"for keyboard access aria-expandedreflects the current toggle statearia-labeldescribes the action (e.g. "Toggle 3 hidden lines")- Enter and Space keys trigger the toggle
- Focus indicator appears on keyboard navigation (
:focus-visible)
API
function transformerHideLines(options?: HideLinesOptions): ShikiTransformerOptions
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| reveal | boolean | false | Enable reveal mode with clickable placeholders |
| marker | string | 'hide' | The marker keyword in [!code <marker>] |
| summaryTemplate | string \| (count: number) => string | '··· N hidden line(s)' | Customize collapsed placeholder text. Use {count} in strings |
| expandedSummaryTemplate | string \| (count: number) => string | '▲ N hidden line(s)' | Customize expanded placeholder text. Use {count} in strings |
Exports
| Export | Description |
|--------|-------------|
| transformerHideLines | The Shiki transformer factory |
| getToggleScript | Returns toggle script as a string (for inline injection) |
| setupHiddenLinesToggle | Registers click and keyboard handlers (for SPA use) |
| HideLinesOptions | TypeScript options interface |
