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

@hascii/canvas

v0.1.1

Published

Terminal canvas sketches with p5-like ergonomics, powered by OpenTUI. Bun-only.

Readme

@hascii/canvas

ターミナル上で動く p5 風のクリエイティブコーディング・ライブラリ。@opentui/core を薄くラップし、アニメーションやゲームを気持ちよく書くための小さな関数群を提供します。Bun 専用。

  • 描画はすべて (buffer, props) の素直な関数
  • 入力・フレーム・リサイズは自動クリーンアップ付きの関数
  • 時間・アニメーション・パーティクルは step(dt) で自分で進める素のファクトリ関数
  • 純粋ロジックはレンダラから完全に分離されていて、すべてユニットテスト済み
  • 計算系(math / color / time / animation / particles / geometry / raster)はサブパスで個別 import でき、ターミナルなしの Node やブラウザでも動く

動かす

bun add @hascii/canvas

my-sketch.ts を作って、矢印キーで四角を動かす最小スケッチを書きます。

import { sketch, axis, clear, square, text } from "@hascii/canvas"

export const config = { loop: true, fps: 60 }

export default sketch((renderer, signal) => {
  let x = 0
  const moveX = axis(renderer, signal, { negative: ["left", "a"], positive: ["right", "d"] })

  return (buffer, dt) => {
    x += moveX.value * 30 * dt // dt は秒。30 セル/秒で動く

    clear(buffer, "#000")
    square(buffer, { x, y: 2, size: 3, char: "█", fg: "#f06" })
    text(buffer, { x: 0, y: 0, str: "← → to move", fg: "#888" })
  }
})

CLI で実行します。ファイルを保存すると自動でリロードします。

hascii-canvas run my-sketch

考え方

スケッチは「renderersignal を受け取り、毎フレーム呼ばれる Draw を返す関数」です。

type Sketch = (renderer: CliRenderer, signal: AbortSignal) => Draw | void
type Draw = (buffer: OptimizedBuffer, dt: number) => void // dt は秒

セットアップ(クロージャ変数の用意やフック登録)は外側の関数で一度だけ。毎フレームの描画は返り値の Draw で行います。Draw には毎フレーム最新の buffer が渡されます。これだけ押さえれば、あとは下のリファレンスから必要なものを拾うだけです。

  • renderer@opentui/coreCliRendererwidth height で現在のサイズを取得でき、リサイズしても常に最新を返す。フックの登録先でもある
  • signal … クリーンアップ用の AbortSignal。スケッチが破棄されると abort され、登録したフックや購読が自動で解除される
  • bufferDraw に毎フレーム渡される OptimizedBuffer。リサイズで作り直されるため、セットアップで掴まず毎フレーム受け取ったものを使う
  • Config{ loop?: boolean; fps?: number }loop: false で一枚絵モード
  • mount(sketch, config?) → Promise<CliRenderer | Error> … プログラムから起動したいとき(CLI 経由なら不要)

構造

lib/ は層ごとに分かれていて、下に行くほど積み上がります。ピュアな道具(math / color / time / animation / particles / geometry / raster)はサブパス公開で Node / ブラウザでも動きます。generators はほぼ純粋ですが turtle が描画層を引くためルート公開のみです(純粋な線分生成だけ要るなら turtleSegments)。描画依存層(draw / quadrant / sextant / block / three)はターミナル向けで Bun 専用。汎用 3D エンジンは three だけで、ジャンル固有の擬似 3D(dungeon / raycast / mode7 / voxel / parallax など)は examples/ にレシピとして降りています。

lib/
├─ types/        Sketch / Draw / Config / Rect — 全体の型の土台
├─ runtime.ts    mount() — スケッチを起動するエントリ
├─ internal/     OpenTUI レンダラとの結線(普段は触らない)
├─ log/          TUI 専有中の実行ログ(console.log の代わり)
│
├─ math/         clamp / lerp / map / noise / random / ease / vec3 / mat4
├─ color/        色の正規化・補間・HSL・深度フォグ
├─ time/         経過秒・FPS を step(dt) で進めるカウンタ
│
├─ animation/    バネ・トゥイーンを step(dt) で進める補間値
├─ particles/    プール付きパーティクルと発生レート
├─ generators/   迷路・ライフ・L-System・タートル・アトラクタ・TEN PRINT・Truchet・フローフィールド
├─ geometry/     画家アルゴリズム depth sort・アイソメ投影・ビルボード math(patterns 解体時に抽出)
├─ raster/       4 階調インデックスのドット絵バッファ + 2D 描画プリミティブ
│
├─ draw/         点・線・矩形・円・多角形・テキスト・枠線(セル単位、@opentui buffer 直書き)
├─ quadrant/     2×2 サブセル(16 種クアドラント)— raster の primitives を namespace 公開
├─ sextant/      2×3 サブセル(64 種セクスタント)
├─ block/        1×2 ハーフブロック(▀ ▄ █)
│
├─ hooks/        入力・フレーム・インターバル・リサイズ(自動クリーンアップ)
│  ├─ input/     キー・マウス・軸・ポインタ
│  └─ (直下)     onFrame / onInterval / onResize
│
├─ three/        ソフトウェア3D(三角形を CPU で投影して ASCII / quadrant / block 化)
│  ├─ core/      共有データ型(RGB / Triangle / Light / Scene / RasterBuffer)+ toRGB
│  ├─ scene/     行列スタック(translate / rotate / push・popMatrix)
│  ├─ shapes/    box / sphere / cylinder / cone / torus / plane
│  ├─ camera/    perspective / orthographic + 操作カメラの純粋コア
│  ├─ lighting/  ambient / directional(ランバート拡散)
│  ├─ raster/    三角形ラスタライザ + blit(ASCII / RasterBuffer 出力)
│  ├─ ascii/     輝度・形状を文字へマッチング
│  └─ helpers/   grid / axes
│
├─ controls/     入力束縛のカメラ操作(orbit / flyCamera)。three の純粋コアに hooks を結線
└─ commands/     hascii-canvas コマンド(スケッチ実行・作例の list / run)

examples/        作例。各ディレクトリは bun example <path> で実行
├─ math/         数学系の単品検証
├─ color/        色変換
├─ time/         経過秒・FPS カウンタ
├─ animation/    バネ・トゥイーン
├─ particles/    パーティクル
├─ generators/   生成アルゴリズム
├─ geometry/     投影・深度ソートの単品検証
├─ draw/         セル描画
├─ quadrant/     2×2 サブセル系(00..05 はチュートリアル)
├─ hooks/        入力・フレーム・リサイズ
├─ three/        ソフトウェア3D
│
├─ dungeon/      グリッドダンジョン(旧 patterns.dungeon)
├─ raycast/      Wolfenstein 風レイキャスト
├─ wireframe-dungeon/  線画版ダンジョン
├─ mode7/        SNES Mode 7 の床
├─ voxel/        VoxelSpace 地形
├─ parallax/     多層スクロール背景
├─ iso/          アイソメトリック投影
├─ scanline/     アウトラン風の道
├─ stack/        スプライトスタッキング
├─ painter/      画家のアルゴリズム(深度ソート描画)
│
└─ games/        ゲーム作例

各ディレクトリの純粋ロジックはレンダラから分離されていて、lib/<name>/index.ts が公開 API、*.test.ts がその仕様です。

計算系をターミナルなしで使う

ルートの @hascii/canvasmount() 経由で @opentui/corebun:ffi)を巻き込むため Bun とターミナルが要ります。一方、ターミナルに依存しない計算系はサブパスとして切り出してあり、素の Node やブラウザからそのまま import できます。

import { lerp, clamp, createNoise } from "@hascii/canvas/math"
import { parseColor, lerpColor } from "@hascii/canvas/color"
import { createElapsed } from "@hascii/canvas/time"
import { createSpring, createTween } from "@hascii/canvas/animation"
import { createParticles, createSpawner } from "@hascii/canvas/particles"
import { geometry } from "@hascii/canvas/geometry"
import { raster } from "@hascii/canvas/raster"
import { multiplyMat4, normalizeVec3 } from "@hascii/canvas/math"

これらのサブパスはビルド時点で @opentui/corebun:ffi も含まないことを保証しています。描画したいときだけルートの @hascii/canvas から描画関数を取ってください。

リファレンス

機能ごとにディレクトリの README へ分けてあります。やりたいことから引いてください。

  • … 色の正規化・補間・HSL・深度フォグ
  • 描画 … 点・線・矩形・円・多角形・テキスト・枠線
  • 数学 … クランプ・補間・再マッピング・ノイズ・乱数・イージング・vec3 / mat4
  • フック … 入力・フレーム・インターバル・リサイズ(自動クリーンアップ)
  • 時間 … 経過秒・FPS を step(dt) で進めるカウンタ
  • アニメーション … バネ・トゥイーンを step(dt) で進める補間値
  • パーティクル … プール付きパーティクルと発生レート計算
  • ドット絵 — quadrant … 2×2 サブセル解像度のピクセルバッファ
  • ドット絵 — sextant … 2×3 サブセル解像度のピクセルバッファ
  • ドット絵 — block … 1×2 ハーフブロック解像度のピクセルバッファ
  • ドット絵 — raster … 4 階調インデックスバッファと 2D 描画プリミティブ(純粋・サブパス公開)
  • ジオメトリ … 深度ソート・アイソメ投影・ビルボード(純粋・サブパス公開)
  • 生成アート — generators … 迷路・ライフゲーム・L-System・タートル・アトラクタ
  • ソフトウェア3D — three … 行列スタック式の 3D シーンを ASCII に投影

作例

bun example <path> で同梱の作例を実行します。<path>examples/ 配下の相対パスです(.ts は省略可、再帰検索なし)。一覧は hascii-canvas examples で取れます。

bun example games/breakout
bun example dungeon/dungeon-animation
bun example three/block/lights
bun example quadrant/00

ヘッドレス検証

make snapshot N=games/tetris
make check-examples

CLI

hascii-canvas <file>            スケッチファイルを実行
hascii-canvas run <file>        同上
hascii-canvas examples          同梱の作例一覧
hascii-canvas examples <path>   同梱の作例を実行(例: games/breakout)
hascii-canvas samples [...]     examples のエイリアス
hascii-canvas help              このヘルプを表示

ロギング

TUI が標準出力を専有するため、console.log の代わりに実行ログを使います。出力先は ~/.hascii/canvas/logs/{pid}.jsonl です。

log("info", "message", data?)   // JSONL を実行ログに追記
logError("message", error)
getLogPath()                    // 現在のログファイルパス

動作要件

  • スケッチの実行(描画系・ルートの @hascii/canvas)は Bun 1.0 以降。mount()@opentui/core 経由で bun:ffi を使うため Node.js では動きません
  • 計算系のサブパス(@hascii/canvas/math など)は純粋なので、素の Node やブラウザでも動きます
  • truecolor 対応ターミナル(Ghostty / WezTerm / kitty / 最近の iTerm2 など)
  • heldKeys / onKeyrelease を最大限活かすには Kitty キーボードプロトコル対応が望ましい

開発

bun example <path>      # 同梱の作例をソースから実行(ホットリロード, ビルド不要。例: bun example games/breakout)
make examples           # 同梱の作例一覧
make test               # vitest
make check              # 型チェック + lint + format
make build              # dist を生成
make snapshot N=<path>  # 作例を1フレーム分オフスクリーン描画して静止画で確認
make check-examples     # 全作例をヘッドレスで起動して描画できるか検証
make check-package      # package.json の exports が dist に実在するか確認
make publish            # check → test → check-package を通してから bun publish

開発中は bun example <path> を使います。lib/examples/ もソースをそのまま実行し、保存で自動リロードします。グローバルの hascii-canvas はビルド済み dist を実行するため、lib/ を変更したら make build し直すまで反映されません。