Skip to content

TestFlowLabs/shiki-hide-lines

Repository files navigation

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-lines

Usage

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 shown

Function — 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" and tabindex="0" for keyboard access
  • aria-expanded reflects the current toggle state
  • aria-label describes 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): ShikiTransformer

Options

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

License

MIT

About

A Shiki transformer that hides marked lines from rendered code blocks while keeping them in the source

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors