CodeBlock

サーバーでハイライトし、コピーボタンを添えたコードブロック

インポート

ハイライトはサーバーで済ませ、shiki はブラウザに送らない。server-only を import しているので、Client Component から読み込むとビルドが止まる。そのためルートとは別の入口にある。

ts
import { CodeBlock } from '@k8ordo/ui/code-block';

使い方

tsx
export function Total({ items }: { items: Item[] }) {
  const done = items.filter((item) => item.done).length;
  return <p>{done} / {items.length}</p>;
}
tsx
<CodeBlock code={source} lang="tsx" />

ファイル名

title を渡すと、見出しの行に言語の代わりに表示する(figure の figcaption になる)。

total.tsx
export function Total({ items }: { items: Item[] }) {
  const done = items.filter((item) => item.done).length;
  return <p>{done} / {items.length}</p>;
}
tsx
<CodeBlock code={source} lang="tsx" title="total.tsx" />

行の印

marks は 1 始まりの行番号ごとに highlight・add・remove を付ける。追加と削除は色だけでなく + と − でも示す。

ts
const done = items.filter((item) => item.done).length;
const rate = done / items.length;
const rate = items.length === 0 ? 0 : done / items.length;
tsx
<CodeBlock
  code={source}
  lang="ts"
  marks={{ 1: 'highlight', 2: 'remove', 3: 'add' }}
/>

注記

callouts は行の直後に、その行の字下げに揃えて注記を置く(配列なら書いた順に重ねる)。コピーされるのは code そのもので、印や注記は含まれない。

ts
const done = items.filter((item) => item.done).length;
const rate = done / items.length;
const rate = items.length === 0 ? 0 : done / items.length;
Guard the division when the list is empty
tsx
<CodeBlock
  callouts={{ 3: 'Guard the division when the list is empty' }}
  code={source}
  lang="ts"
/>

色とダークモード

shiki の css-variables テーマを使い、--shiki-token-* を ui のトークンに結びつけている。トークンが .dark で切り替わるので、ダーク用のテーマは持たない。知らない言語名は色を付けずに描く。

Props

code
Type: string
Default: -
callouts?
Type: Readonly<Record<number, string | readonly string[]>>
Default: -
lang?
Type: string
Default: 'text'
marks?
Type: Readonly<Record<number, 'highlight' | 'add' | 'remove'>>
Default: -
title?
Type: string
Default: -

型ベース(内部で固定する一部attrsは除外): HTMLAttributes<HTMLElement>

このコンポーネントが描画する文言(ラベルやプレースホルダーなど)は、propsで指定しないとき文言辞書から解決されます。差し替え方は次を参照してください: i18n