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

@sinhala-typer/typing-engine

v0.1.0

Published

Framework-agnostic, zero-dependency Sinhala transliteration engine (phonetic + Wijesekara input methods, plus a legacy-font converter), with zero DOM/browser dependencies and a pluggable LanguageModule interface for future languages.

Readme

@sinhala-typer/typing-engine

A framework-agnostic, zero-dependency Sinhala transliteration engine — phonetic (ammaa → අම්මා) and Wijesekara keyboard input methods, plus a legacy 8-bit font converter, with zero DOM/browser API dependencies. It's a pure (state, keystroke) → { state, edit } function: you own the text buffer, this library only tells you what to change.

Designed to be reusable from React, Vue, Angular, Node.js, Electron, VS Code extensions, or browser extensions — see @sinhala-typer/typing-engine-dom for a ready-made browser <textarea> adapter if you're building a web UI.

Install

npm install @sinhala-typer/typing-engine

Usage

import { getLanguage, type EngineState } from "@sinhala-typer/typing-engine";

const sinhala = getLanguage("si")!;
const phonetic = sinhala.inputMethods.find((m) => m.id === "phonetic")!;

let state: EngineState = phonetic.initialState();
let text = "";

function press(char: string) {
  const { state: nextState, edit } = phonetic.type(state, { char });
  state = nextState;
  text = text.slice(0, text.length - edit.deleteCount) + edit.insertText;
}

for (const ch of ["a", "m", "m", "a", "a"]) press(ch);
console.log(text); // "අම්මා"

Backspace is a separate method, since it's not just "undo the last edit" — it always removes exactly one character, even mid-conjunct:

const { state: nextState, edit } = phonetic.backspace(state);
state = nextState;
text = text.slice(0, text.length - edit.deleteCount) + edit.insertText;

After any change your engine didn't produce (paste, undo, programmatic edit, cursor move), resync state from the actual buffer:

state = phonetic.resync(text, caretIndex);

API

  • getLanguage(id) / listLanguages() / registerLanguage(module) — the language registry. Sinhala ("si") is registered automatically on import.
  • A LanguageModule exposes inputMethods: InputMethod[] and an optional convertLegacyFont(text).
  • An InputMethod (e.g. phonetic, wijesekara) exposes:
    • initialState() — a fresh, empty composition state.
    • type(state, keystroke) → { state, edit }.
    • backspace(state) → { state, edit } — always deletes exactly one character.
    • resync(text, caretIndex) → rebuilds state from arbitrary buffer content.
  • Edit = { deleteCount: number; insertText: string } — delete deleteCount characters immediately before the caret, then insert insertText. Applying it is your responsibility; this library never touches a text buffer itself.
  • UndoStack — a small generic undo/redo helper (you supply the applied edit and its inverse; it just sequences them).

Supported languages

Sinhala only, for now. The LanguageModule interface is designed to support additional languages later, but hasn't been validated against a second language yet — see the root docs/OPEN_QUESTIONS.md.

Correctness

Every composition rule (vowel doubling, rakaransaya/yansaya ZWJ conjuncts, diphthongs, sanyaka nasalization, and more — see docs/GLOSSARY.md) is covered by a keystroke-trace unit test in tests/. The engine was originally ported from a legacy implementation and verified against it via differential fuzz testing (thousands of randomized keystroke sequences, comparing output and internal state after every keystroke) before being considered correct.

License

MIT