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

@fortyfoxes/wiki-toolcontext

v0.1.0

Published

How a Federated Wiki tool page learns which item summoned it — a capture-phase click recorder, subject resolution over plugin.consumes, and guarded write-back to the source item.

Readme

@fortyfoxes/wiki-toolcontext

How a Federated Wiki tool page learns which item summoned it.

A wiki link cannot carry a parameter. [[Edit Diagram]] renders to a fixed anchor, doInternalLink(title, $page, site) takes three arguments, and refresh.cycle rebuilds the new page from {slug, rev, site} scraped back out of the DOM. Anything you hand the click dies at that boundary, and query strings do not survive the next pushState.

It does not need to. The client already computes the answer.

The mechanism

plugin.consumes is shipped, and until now unused by any of our plugins. A plugin that declares it gets $item[0].consuming filled before every bind with `${pageKey}/${itemId}` for each matching item to its left in the lineup — and the client awaits those items' binds first, so they are fully rendered before yours resolves.

That is the missing half of look-left. Look-left names the page; consumes names the item.

window.plugins['diagram-editor'] = { emit, bind, consumes: ['.diagram', '.svg'] }

consumes is read off the plugin object, not factory.json — no server change.

This library adds the one thing consumes cannot know (which of several candidates was actually clicked) and the guards needed to write back without corrupting a page.

Resolution ladder

Re-run on every bind, never consume-once:

  1. A recorded click for this page slug, corroborated against consuming.
  2. A cached subject from an earlier bind, revalidated.
  3. Exactly one candidate in consuming.
  4. Several candidates → return them for a picker; the caller must not guess.
  5. None → say so and offer nothing.

The [[Edit Diagram]] link normally sits in a markdown item, not in the diagram — so the recorded item id is usually not itself a candidate. It is read as a position: the subject is the last candidate above the link on that page.

Where state lives

In a module Map keyed by the tool item's pageKey/itemId. Not in $item.data()refresh.rebuildPage destroys and rebuilds every item div on every edit-toggle and fork. Not in the tool page's own item JSON — that page is shared, and it would persist one reader's subject into everyone's copy.

$page.data('key') is set once in refresh.buildPage and never cleared, which is what makes the key durable.

Installing the click recorder

Capture phase on document, so it beats the bubble-phase jQuery handler bound on .main. It runs synchronously in the same dispatch, long before the new page's fetch resolves.

It cannot ship as a plugin of its own: plugin client code is fetched lazily when an item of that type first renders, so a standalone context plugin would not be loaded at the moment of the click it exists to observe. Install it from a plugin already on the page — the one rendering the thing being edited.

import { installClickRecorder } from '@fortyfoxes/wiki-toolcontext'
installClickRecorder()   // idempotent

Saving back

revision.js case 'edit' pushes the item onto the end of the story when its id is not found, instead of erroring — a stale id silently appends a duplicate diagram. saveSubject checks membership first, along with ghost pages, _rev views, pages that have left the lineup, and login state, and reports remote-fork and localStorage-only saves as warnings rather than doing them silently.

rerenderItem re-renders one item through the wrapped plugin object. Do not use wiki.renderFrom for this: it slices $('.item') from the given index to the end of the document, which includes the editor doing the calling.

API

| Export | Purpose | |---|---| | installClickRecorder() | Idempotent capture-phase listener on a.internal | | resolveSubject(div, item) | { subject, candidates, how } | | chooseSubject(div, item, 'key/id') | Pin a picker choice | | forgetSubject(div, item) | Drop the cached subject | | subjectNote(subject) | Human label for the chrome | | saveSubject(subject, newItem) | Guarded put + re-render | | saveBlockers / saveWarnings | The guard table, for pre-flight display | | rerenderItem($item, item, $page) | Re-render one item safely | | pageFor(key) / itemFor('key/id') | The target.js idiom, which core does not export |

See

  • wiki-plugin-diagram-editor — the first consumer.
  • The Tool Page page on plugin.fedwiki.club — the look-left half of the pattern.