@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.
Maintainers
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:
- A recorded click for this page slug, corroborated against
consuming. - A cached subject from an earlier bind, revalidated.
- Exactly one candidate in
consuming. - Several candidates → return them for a picker; the caller must not guess.
- 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() // idempotentSaving 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.
