Skip to content

Output annotations: let a snippet explain its own engine output #72

Description

@pavlof01

Context

Bytecode and %DebugPrint dumps are the point of jslab, and they are unreadable
to the people most likely to be learning from them. The built-in opcode
reference explains what LdaSmi does in general; it cannot say why this line
matters in this snippet — that an elements kind just went from packed to
holey, or that the second Star is where a closure captures its variable.

Today that explanation has nowhere to live. It ends up in ordinary //
comments next to the code, where the reader has to map it onto the right line
of the dump themselves, or outside the tool entirely — in the article, the
lesson, or the chat message the link was pasted into. None of it survives the
link being shared onward, which is exactly when the explanation is needed most.

Proposal

An @annotation comment in the snippet attaches an explanation to matching text
in the engine output. The matched fragment gets a highlight; clicking it opens
the explanation.

/* @annotation
match: elements kind: HOLEY_SMI_ELEMENTS
highlight: HOLEY_SMI_ELEMENTS
title: PACKED_SMI_ELEMENTS → HOLEY_SMI_ELEMENTS
text: |
  Growing length creates the missing indexes 3–9.
  V8 therefore switches the array representation from packed to holey.
*/
arr.length = 10;
%DebugPrint(arr);

Why in the source rather than in the UI. The snippet is already the unit
that gets shared, saved and embedded. Keeping the explanations in a comment
means they travel with the code through share links, /embed/bytecode and the
sample catalog with no extra plumbing, and they can be reviewed in a diff like
any other code. It also means the author of an example — not the site — decides
what is worth explaining.

Directive format, one block per rule:

Field Meaning
match Required. Exact text to look for; case, whitespace and punctuation count.
text Required. The explanation, as plain text.
highlight Optional substring of match to underline. Must occur inside match exactly once.
title Optional heading; defaults to the highlighted text.
occurrence all (default) or a match number starting at 1, per output channel.

text: | keeps line breaks and strips the common indent. Values are literal
text — Markdown and HTML are not interpreted.

Design constraints worth stating, because they rule out simpler designs:

  • The raw output is never modified. Copy still yields exactly what the
    engine printed; annotations are a rendering layer over unchanged text.
  • Matching is literal, not regex. An annotation cannot quietly start
    matching something else after an engine upgrade.
  • A rule that matches nothing is normal, not an error. One snippet runs on
    four engines that print different text, and stdout/stderr are matched
    separately.
  • Mistakes in the directives are reported. An unknown field, an empty
    match, a highlight that is not inside match — each surfaces as a warning
    next to the output, so a typo does not fail silently as "no highlight".

Acceptance criteria

  • An @annotation block in a snippet highlights the matching output fragment on
    every engine that prints it, and the explanation opens on click and on Enter.
  • Directive errors are shown next to the output with the source line number.
  • The raw output and the Copy button are byte-identical to the un-annotated run.
  • Annotations survive a share link and a /embed/bytecode snapshot.
  • In diff mode, rules apply to the current run's rows only.

Related

Gives #35 (Learn section) its mechanism: an explainer can embed a live run whose
output explains itself, instead of pairing a screenshot with prose that drifts
out of sync with the engine.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestfrontendUI and visual features

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions