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

perlscript-web

v1.0.0

Published

A reactive UI runtime built with Perl 1.0-shaped syntax for the browser.

Downloads

290

Readme

perlscript-web

The future of UI, written in 1987.

perlscript-web is a browser runtime and reactive UI layer built from a deliberately small, Perl 1.0-shaped language. The syntax stays in 1987; rendering, state scheduling, keyed reconciliation, lifecycle, and transactional recovery live in the 2026 runtime.

Perl 1.0 syntax. 2026 runtime.

<script src="https://cdn.jsdelivr.net/npm/perlscript-web/dist/perlscript-web.min.js"></script>

<div id="app"></div>
<script type="text/perl">
$count = 0;

sub increment { $count++; }

sub view {
    begin("button", "type", "button");
    on("click", "increment");
    text("Count: $count");
    end();
}

open APP, ">ui:#app";
mount(APP, "view");
</script>

State is an ordinary Perl scalar. Views and handlers are named subroutines. Changing the scalar schedules one safe DOM update; no DOM query, HTML string, JavaScript callback, JSX, object system, or new Perl syntax is involved.

This is not a revival of ActiveState PerlScript and not a Perl-flavoured React port. It is a browser-only interpreter, structured UI runtime, and I/O bridge, installable from npm and usable from a CDN.

Try the live perlscript-web workbench or open the editable BBS directly.

PerlUI

PerlUI turns ordinary calls into a validated UI instruction tree:

  • open APP, ">ui:#app" owns a mount point.
  • mount(APP, "view") renders a named view subroutine.
  • begin, text, and end describe structured, text-safe elements.
  • on("click", "handler", $argument) invokes a named subroutine with captured @_ arguments.
  • bind("value", "name") connects a form property to $name.
  • key($id) preserves element identity across list changes.

Assignments and array mutations are batched until the current top-level action finishes. Event and render failures restore the previous Perl state and last good UI. Nested subroutines are components and errors include their UI call stack.

See the normative PerlUI 1.0 Profile, the standalone Counter and Todo, and the editable Guestbook.

Low-level browser filehandles

The original browser-as-UNIX API remains available as the low-level compatibility layer. DOM values, text output, and browser events become filehandles rather than DOM objects:

open NAME,    "dom:#name";             # read value/text
open POSTS,   ">dom:#posts";           # write text
open POST,    "event:click:#post";      # click stream
open ENTER,   "event:keydown:#message"; # Enter stream

$name = <NAME>;
select POSTS;
print $name, "\n";
do watch(POST, "post");
do watch(ENTER, "post");

keydown event handles fire only for Enter and ignore IME composition (isComposing and key code 229). Output is written with textContent, so user input is not interpreted as HTML.

watch(HANDLE, "sub"), clear(), and the PerlUI primitives are intentional browser extensions. Everything else follows the versioned Perl 1 Web Profile 1.0.

Supported subset

  • Scalars, list expressions, arrays, hashes, strings, numbers, assignment and interpolation
  • Array/hash indexing, $#array, push, pop, shift, keys, values
  • Arithmetic, concatenation, string/numeric comparisons
  • Regular expressions and =~ / !~
  • if, unless, statement modifiers, while, return
  • sub, dynamic @_ arguments, do, open, select, print, <FILEHANDLE>

The parser intentionally rejects unsupported modern Perl instead of silently pretending to implement Perl as a whole.

Browser API

The IIFE bundle creates window.PerlScript:

const runtime = PerlScript.run(source);
await PerlScript.runScripts();
PerlScript.setErrorHandler(error => console.error(error.message, error.excerpt));
runtime.dispose();

ES modules expose the same lifecycle API without automatically scanning the document:

import { run, runScripts, setErrorHandler, Runtime, BrowserIO } from "perlscript-web";

const runtime = run(source);

runScripts() executes inline and external (src="./app.pl") text/perl scripts in document order. A successful rerun atomically replaces the previous runtime; a failed rerun leaves it active. setErrorHandler() receives structured top-level and event errors. Pass null to clear the handler, or use { onError } to override it for one run.

The source modules also export Lexer, Parser, Runtime, MemoryIO, and BrowserIO for tests and embedding.

Perl source executed by this package must be treated as page-authored code with the same trust level as JavaScript. The interpreter limits runaway while loops, but it is not a security sandbox for untrusted programs.

Development

Requires Node.js 20 or newer and pnpm 11. The exact pnpm version is pinned by the packageManager field.

pnpm install
pnpm test
pnpm run typecheck
pnpm run build
pnpm exec playwright install chromium firefox webkit
pnpm run test:e2e

pnpm run check runs the complete test suite, strict JSDoc type checking, and both distribution builds. Lexer tokens and AST nodes include source ranges; syntax and runtime errors expose range, excerpt, and line/column-aware messages.

Open examples/bbs.html through a local HTTP server to try the editable BBS demo:

python3 -m http.server 8000

Then visit http://localhost:8000/examples/bbs.html.

Project status

Stable version 1.0.0 implements the documented Perl 1 Web Profile 1.0 and PerlUI 1.0 Profile, not modern Perl and not full historical compatibility. See compatibility, changelog, and release procedure.

License

MIT