npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@kanbun-skam/skam-html-renderer

v0.1.0

Published

SKAM to HTML renderer - SKAMドキュメントから静的HTMLを生成

Readme

@kanbun-skam/skam-html-renderer

SKAM ドキュメントから静的 HTML を生成するレンダラー。

縦書き・横書き・縦中横対応、返り点・送り仮名・ルビ等の訓点レンダリングを提供。

インストール

npm install @kanbun-skam/skam-html-renderer
# or
pnpm add @kanbun-skam/skam-html-renderer

使い方

基本的なレンダリング

import { render } from '@kanbun-skam/skam-html-renderer';
import type { SKAMDocument } from '@kanbun-skam/skam';

const doc: SKAMDocument = {
  format: '[email protected]',
  tokens: [
    { id: 't1', text: '学' },
    { id: 't2', text: '而' },
  ],
  marks: [{ type: 'okurigana', anchor: { from: 't1', to: 't1' }, value: 'びて' }],
  readings: [],
};

const result = render(doc);
// result.html: レンダリングされた HTML
// result.css: 適用すべき CSS

書字方向の指定

import { render } from '@kanbun-skam/skam-html-renderer';

// 縦書き(デフォルト)
const vertical = render(doc, { writingMode: 'vertical' });

// 横書き
const horizontal = render(doc, { writingMode: 'horizontal' });

表示プロファイル

import { render, PROFILES } from '@kanbun-skam/skam-html-renderer';

// フルプロファイル(すべての要素を表示、デフォルト)
const full = render(doc, { profile: PROFILES.full });

// 学習用基本プロファイル(返り点のみ)
const basic = render(doc, { profile: PROFILES.learningBasic });

// 学習用ヒント付きプロファイル(返り点+送り仮名)
const hint = render(doc, { profile: PROFILES.learningHint });

スタイルのカスタマイズ

import { render, getDefaultStyles, generateCSS } from '@kanbun-skam/skam-html-renderer';

// CSS 生成オプション
const css = generateCSS({
  writingMode: 'vertical', // 'vertical' | 'horizontal' | 'both'
  inline: false, // インラインモード
  useLayer: true, // @layer でラップ(デフォルト: true)
  layerName: 'skam-kanbun', // レイヤー名(デフォルト: 'skam-kanbun')
});

// レンダリングも同様のオプションに対応
const result = render(doc, { writingMode: 'vertical' });

CSS Variables によるカスタマイズ

生成される CSS は CSS Variables を公開しており、ユーザー側で簡単にカスタマイズできます。

/* ユーザー側でカスタマイズ */
.skam-document {
  --skam-color-fg: #333;
  --skam-color-kaeriten: #c00;
  --skam-color-ruby: #666;
  --skam-font-family: '游明朝', serif;
}

公開 CSS Variables 一覧

| カテゴリ | 変数名 | デフォルト値 | 用途 | | -------------- | ------------------------- | -------------- | -------------------------- | | | --skam-color-fg | currentColor | 前景色(テキスト、傍線等) | | | --skam-color-kaeriten | currentColor | 返り点の色 | | | --skam-color-ruby | currentColor | ルビ・送り仮名の色 | | | --skam-color-emphasis | currentColor | 傍点の色 | | フォント | --skam-font-family | inherit | 本文フォント | | | --skam-font-family-ruby | inherit | ルビ・送り仮名フォント | | サイズ | --skam-glyph-size | 1em | 基準グリフサイズ | | | --skam-ruby-font-size | 0.5em | ルビ・送り仮名サイズ | | 余白・間隔 | --skam-line-height | 2 | 行間 | | | --skam-letter-spacing | 0 | 字間 |

コピー可能範囲の制御

デフォルトでは、テキスト選択・コピー時に本文のみがコピーされ、返り点・送り仮名・ルビなどの注記はコピーされません。

API での指定

import { render, renderHTML } from '@kanbun-skam/skam-html-renderer';

// デフォルト: 本文のみコピー可能
const result = render(doc);

// 読み仮名もコピー可能
const result = render(doc, { copyable: ['ruby'] });

// 複数指定
const result = render(doc, { copyable: ['ruby', 'okurigana'] });

// 全てコピー可能
const result = render(doc, { copyable: 'all' });

生成される HTML

<!-- デフォルト: 本文のみコピー可能 -->
<div class="skam-document">...</div>

<!-- 読み仮名もコピー可能 -->
<div class="skam-document" data-copyable="ruby">...</div>

<!-- 複数指定(スペース区切り) -->
<div class="skam-document" data-copyable="ruby okurigana">...</div>

<!-- 全てコピー可能 -->
<div class="skam-document" data-copyable="all">...</div>

指定可能な値

| 値 | 対象 | | ----------- | ---------------- | | ruby | 読み仮名(ルビ) | | okurigana | 送り仮名 | | soegana | 添え仮名 | | kaeriten | 返り点 | | okototen | ヲコト点 | | all | 全ての注記要素 |

Note: data-copyable 属性は CSS で制御されるため、HTML を直接編集して属性を変更することで、ビルド後でも動的に切り替えられます。

CSS @layer との統合

生成される CSS はデフォルトで @layer skam-kanbun でラップされます。 これにより、ユーザー側でカスケード順序を制御できます。

/* ユーザー側でレイヤー順序を定義 */
@layer reset, base, skam-kanbun, app;

/* skam-kanbun レイヤーより後のレイヤーで上書き可能 */
@layer app {
  .skam-document {
    --skam-color-kaeriten: red;
  }
}

@layer を無効にする

const css = generateCSS({ useLayer: false });

リセット CSS との共存

本ライブラリは :where() セレクタで specificity を 0 に抑えているため、 一般的なリセット CSS と競合しにくい設計です。

sanitize.css との組み合わせ

<link rel="stylesheet" href="sanitize.css" />
<style>
  @layer reset, skam-kanbun;
</style>

Tailwind CSS preflight との組み合わせ

@layer base, skam-kanbun, components, utilities;

レンダリング対応

| Mark Type | 対応状況 | | ----------- | -------- | | kaeri | ✅ | | okurigana | ✅ | | yomigana | ✅ | | soegana | ✅ | | okimoji | ✅ | | joji | ✅ | | kutoten | ✅ | | emphasis | ✅ | | saidoku | ✅ | | tateten | ✅ | | highlight | ✅ | | ref | ✅ | | okototen | 🚧 |

出力形式

interface RenderResult {
  /** レンダリングされた HTML 文字列 */
  html: string;
  /** 適用すべき CSS 文字列 */
  css: string;
}

内部アーキテクチャ

モジュール構成と依存方向

依存方向は shared → display → API の一方向に固定されています。

API層 (renderer.ts)
  ├── 公開 API (render, renderHTML, generateCSS)
  ├── option 正規化
  └── CSS 生成呼び出し (styles.ts)
       │
       ▼
display オーケストレータ層 (render-display-layer.ts)
  ├── group 解決 (tateten/highlight/range marks)
  ├── Pass 1/Pass 2 呼び出し
  └── block 単位合成
       │
       ▼
display 実装層
  ├── Pass 1: build-render-tree.ts (tokens+marks → BlockRenderTree)
  ├── Pass 2: render-tree.ts (BlockRenderTree → HTML string)
  └── token-renderer.ts (個別トークンの HTML 生成)
       │
       ▼
共通基盤層
  ├── render-config.ts (RenderProfile, RubyMethod, PROFILES)
  ├── html-utils.ts (escapeHtml, shouldApplyTateChuYoko 等)
  ├── mark-utils.ts (getBlockStartMarks 等)
  └── render-tree-types.ts (IR 型定義)

CSS Grid 命名規約

styles.ts のグリッドコンテナは grid-template-areas で名前付き配置を使用しています。

| 領域名 | 用途 | | ------------ | ----------------------------- | | ruby | ルビ注記(読み仮名) | | ruby-over | 再読文字の上側ルビ | | ruby-under | 再読文字の下側ルビ | | base | 本文文字 | | suffix | suffix-row(改行排除用) | | emphasis | 傍点行 | | okuri | 送り仮名(suffix-row 内) | | kutoten | 句読点(suffix-row 内) | | kaeri | 返り点(suffix-row 内) | | saidoku | 再読送り仮名(suffix-row 内) |

baseline 補正契約

calibrate.ts が Chromium の inline-grid baseline バグを実測検出し、 --{prefix}-grid-baseline-fix: 1 を設定します。 各グリッドコンテナの vertical-align がこの変数を参照して補正値を算出します。

関連パッケージ

Playground

インタラクティブなデモ: https://berlysia.github.io/kanbun-annotation/

ライセンス

MIT