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

homespring.js

v1.0.1

Published

A JS Homespring interpreter

Readme

homespring.js - A JavaScript interpreter for Homespring

Build Status Coverage Status

Homespring (or HOtMEfSPRIbNG) is the pinnacle of programming language design. With this interpreter you can finally use Homespring code in your browser to make any webpage more dynamic.

This JavaScript interpreter fully implements 2026 Updated Language Standard and is capable of running all known Homespring programs.

Example

Homespring programs are as beautiful as they are effective:

Universe bear hatchery Hello. World!.
 Powers   marshy marshy snowmelt

We can use the interpreter to model the program:

var HS = require('./lib/homespring.js');
var src = 'Universe bear hatchery Hello. World!.\n Powers   marshy marshy snowmelt';
var program = new HS.Program(src);
var output = program.runSync();
console.log(output);

The code (unsurprisingly) outputs Hello World!\n, as is appropriate.

Commandline Usage

A simple node-based CLI wrapper is included:

./bin/hs.js examples/hello-1.hs

Several options are available:

./bin/hs.js --help

JavaScript API

Constructor

var program = new HS.Program(source[, options]);

The source of the program must be passed when creating a new program object. The source is tokenized at the river-system built at this time. Exceptions are thrown for invalid programs. The optional options argument must contain a hash of possible options:

  • strictMode (bool) : controls whether an exception is thrown when programs traverse beyond their root or contain invalid escape sequences (default: false).
  • traceTicks (bool) : controls whether certain debug output is shown, such as start and end of each tick (default: false).

Execution

program.runSync([max_ticks]);
program.run([max_ticks]);
program.tick();

There are three ways to execute the program.

runSync() will run the program to completion and return. This is done completely synchronously. This method will return when the program terminates, or when max_ticks have been reached. In the case of a non-terminating program, this method will not return unless max_ticks was specified. This method also returns the output as a single string, although the output callback (see below) can also be used. Any input must be immediaetly available in the input property (see below), so is not suitable for an interactive process or one that needs multiple inputs.

run() is similar to runSync(), but each tick of execution happens using setTimeout(). Because of this, the method will return immediately. You will need to hook up a termination callback (see below) to watch for program completion. Output is not returned, so the callback must be used.

tick() synchronously executes a single tick of the program, then returns. This can be used for building an interactive debugger. Callbacks must be used for output. Termination can be detected either via a callback or checking the .terminated property.

Callbacks

You can hook up to several optional callbacks to capture certain events during execution:

program.onOutput = function(str, fish){};
program.onTerminate = function(){};
program.onTickStart = function(){};
program.onTickEnd = function(){};

The output callback is called whenever the program produces output. The first argument is the string to be ouput, while the second is the fish that created the output.

The terminate callback is called when the program exits, either by reaching the end of execution (when universe is destroyed, etc.) or by hitting max_ticks number of ticks.

The tick start and end callbacks are called as each execution step starts and ends.

Properties

program.input
program.terminated
program.tickNum
program.events

The input property is used to supply input to the program. See bin/hs.js for an example of how to hook this up to an interactive process.

The terminated property is set to true when the program reaches the end of execution or reaches max_ticks number of ticks.

The tickNum property identifies the last tick to start. This is set to zero when a program is created, and incremented just before onTickStart() is called.

The events property contains an array of event objects generated during the most recent tick. It is cleared at the start of each tick. See the Events section below for details.

Events

After each call to tick(), the program.events array contains a log of everything that happened during that tick. This is useful for building visualizations that can animate salmon movement, show deaths, and display spawning behavior.

Each event is an object with a type property and additional fields depending on the type:

move — Salmon moved between nodes

{ type: 'move', salmon: <uid>, from: <nodeUid>, to: <nodeUid> }

Emitted when a salmon (upstream or downstream) moves from one node to an adjacent node in the river system.

create — New salmon created

{ type: 'create', salmon: <uid>, node: <nodeUid>, source: <string> }

Emitted when a new salmon is added to the river system. The source field indicates how it was created:

  • 'hatchery' — created by a powered hatchery node during the fish hatch tick.
  • 'input' — created from program input during the input tick.

spawn — Salmon spawned

{ type: 'spawn', salmon: <uid>, child: <childUid>, node: <nodeUid> }

Emitted when an upstream salmon spawns. The spawning salmon (salmon) becomes mature and changes direction to downstream. A new young downstream salmon (child) is created at the same node with the node's name.

die — Salmon killed

{ type: 'die', salmon: <uid>, node: <nodeUid>, cause: <string> }

Emitted when a salmon is killed by a node. The cause field indicates what killed it:

  • 'bear' — a bear node ate a mature salmon.
  • 'bird' — a bird node ate a young salmon.

output — Salmon exited the river

{ type: 'output', salmon: <uid>, node: <nodeUid>, name: <string> }

Emitted when a downstream salmon reaches the mouth of the river (the root node has no parent). The salmon's name is printed as output. The name field contains the output string.

Example

var program = new HS.Program('Universe bear hatchery Hello. World!.\n Powers   marshy marshy snowmelt');
program.tick();
console.log(program.events);
// [
//   { type: 'create', salmon: 1, node: 3, source: 'hatchery' }
// ]
program.tick();
console.log(program.events);
// [
//   { type: 'move', salmon: 1, from: 3, to: 4 },
//   { type: 'create', salmon: 2, node: 3, source: 'hatchery' }
// ]

Language Specifications

This interpreter introduces a new version of the language standard, updated to allow a conformant interpreter to run all of the examples and the clarify some undefined behaviors.

The updated 2026 spec has the following important changes:

  • when an invalid escape sequence is encountered (a period followed by anything other than a newline or space), push the current token (if any), add a blank token and advance the parser by one character
  • a token can't start with a period
  • a blank token that would traverse tree-building beyond the root node adds a blank token as a child of the root node instead
  • the snow tick is propogated pre-order, not post-order
  • the water tick is propogated pre-order, not post-order
  • salmon created in the hatchery are young, not mature
  • the hatchery node can be destroyed
  • when a node is destroyed by snowmelt, it keeps its name (rather than having the name set to "")
  • reverse up and reverse down change salmon direction to upstream if they're able to move them
  • split adds the new fish to the bottom of the list, so ['ab', 'cd'] becomes ['a','b','c','d']
  • the young bear starts eating at the second salmon, not the first
  • in the fish up tick, if an upstream salmon name matches the node name, it spawns immediately. this happens only once the salmon is ready to leave, so on the second tick after entering a shallows or rapids node.

Other Links

  • Esolang page: https://esolangs.org/wiki/Homespring
  • Mirror of Jeff Binder's original distribution: https://github.com/iamcal/Homespring
  • Joe Neeman's homepage: http://xeny.net/Homespring
  • Joe Neeman's Ocaml version: https://github.com/jneem/homespring
  • Quin Kennedy's NodeJS version: https://github.com/quinkennedy/Homespring
  • Alternative syntax processor: https://github.com/benibela/home-river
  • My (partial) Perl implementation: http://search.cpan.org/dist/Language-Homespring/Homespring.pm
  • Martijn Arts' JS implementation: https://github.com/martijnarts/homespring-js