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

@dodona/trace-component

v1.6.4

Published

- [Trace component](#trace-component) - [Usage](#usage) - [How it works](#how-it-works) - [Translations](#translations) - [CSS variables](#css-variables) - [Contributing](#contributing) - [Setup](#setup) - [Build](#build) - [Testing](#testin

Readme

Table of contents

Trace component

Trace component is a modern webcomponent that visualizes the trace of a program. It is a reimplementation of pythontutor. All credits for the original idea go to Philip Guo.

img.png

Usage

To use the webcomponent, import the js and simply use the component in your html:

<tc-trace .trace=${trace} .translations="translations"></tc-trace>

This trace is preferably generated by our json tracer. But you can write your own trace generator as long as it follows the format specified in our types. This component should also be compatible with the pythontutor trace format for now, but this might change in the future.

translations is an optional object that translates the information card shown at the first frame, plus the accessible names that screen readers announce. It should be of type TraceTranslations as defined in TraceComponent.ts. See Translations for the full list of keys.

You can listen to frame-change events to get the current frame of the trace for example to indicate the current line of code.

You can also add your trace frame by frame using the addFrame method. This method takes a Frame as defined in types.

const traceComponent = document.querySelector('tc-trace');
traceComponent.addFrame({...});

A frame that you add or pass in the trace may share the entries of globals and heap that did not change with the frame before it, the way a consumer that receives the trace as deltas builds it. The component never uses the identity of an entry to detect a new step. An entry whose content changed has to be a new object: the component renders an object again when its identity changes, so an entry that is changed in place keeps its old rendering.

How it works

A trace is a list of frames, one per execution step. A frame holds the variables in scope and the heap they point into, and every value in it is either a primitive or an array whose first entry names its kind. trace_types.ts describes the whole format.

<tc-trace> turns each frame into a HeapLayout, which decides where every object of that step goes. It then renders the frame the reader picks: the first step shows the help card, a step that raises an uncaught exception shows a message, and every other step renders as a <tc-frame>.

Elements

| Element | Renders | | --- | --- | | <tc-trace> | the whole trace, under the step picker | | <tc-frame-picker> | the slider and the buttons that pick a step | | <tc-help-card> | the card that the first step shows | | <tc-frame> | one step: its stack, its heap, and the arrows between them | | <tc-stack>, <tc-stack-element> | the call stack, and one box on it | | <tc-heap>, <tc-heap-element> | the objects of a step, and one of them | | <tc-sub-element>, <tc-primitive>, <tc-reference> | a value, as text or as the start of an arrow | | <tc-list>, <tc-tuple>, <tc-set>, <tc-dict>, <tc-grid> | a container, one element per type | | <tc-instance>, <tc-class>, <tc-function> | an instance, a class, and a function | | <tc-heap-primitive>, <tc-imported-faux-primitive>, <tc-other> | the remaining kinds of object | | <tc-attribute-map> | the rows that pair a name with a value | | <tc-exception-card> | an exception, at the top of a step or on its own |

Layout

HeapLayout places the objects of a step in rows:

  • A chain of objects that link to one another shares a row, so that a linked list reads from left to right. Two objects belong to the same chain when they have the same shape and one references the other.
  • A container of plain values that one value references renders inside that value, rather than in a box of its own. An object that more than one value references always keeps its box, so that the reader can see that the two share it.
  • A sequence of at least two references, where each one leads to a sequence of plain values that nothing else references, renders as a grid: one row per inner sequence, with the outer indexes down the left and the inner ones along the top. A row that the object holds twice, as in [[0] * 3] * 3, keeps the plain rendering, which shows that the rows are one and the same.
  • A method, a property and a few related types always render inside the object that holds them.

Every layout starts from the layout of the step before it, so an object stays in place for as long as the program can reach it, and a step only costs the work its own objects need.

Arrows

A value that points into the heap renders as a <tc-reference>, which announces its target to the heap and to the frame around it. ConnectionLayer then draws a curve from the reference to the object, in one SVG overlay that covers the step.

An arrow needs the position of elements that sit several shadow roots deep, which Lit reports per element only. DeepAwaitMixin closes that gap: an element that carries it waits for everything below it, and sends a deep-update event once it has rendered. <tc-frame> holds the arrows still while the elements move, and draws them once the whole subtree has settled. <tc-heap> uses the same moment to give an object a left margin, which keeps every arrow pointing to the right, away from the object it starts at.

Translations

The component ships English defaults only. Consumers pass a translations object to tc-trace; any key left out falls back to the English default, so partial objects are fine. Placeholders use the %{name} syntax and are substituted by fillTemplate.

Most keys are accessible names that are never shown on screen but are read aloud by screen readers, so they are easy to miss when translating.

| Key | Default | Defined in | | --- | --- | --- | | title | Drag the slider to walk through your code. | HelpCard.ts | | text_1 | This window shows how your program works step by step. … | HelpCard.ts | | text_2 | You can also use the %{previous} and %{next} buttons … | HelpCard.ts | | picker_label | Execution steps | FramePicker.ts | | slider_label | Execution step | FramePicker.ts | | step_of | Step %{step} of %{total} | FramePicker.ts | | first_step | First step | FramePicker.ts | | previous_step | Previous step | FramePicker.ts | | next_step | Next step | FramePicker.ts | | last_step | Last step | FramePicker.ts | | current_step | Current step | FramePicker.ts | | call_stack | Call stack | FrameComponent.ts | | heap_objects | Heap objects | FrameComponent.ts | | exception_title | The debugger crashed | FrameComponent.ts | | reference_to | reference to %{type} #%{id} | FrameComponent.ts | | trace_label | Execution trace | TraceComponent.ts |

Python type names used as captions (list, dict, set, …) are deliberately left untranslated.

The fold/expand button in FoldableComponent.ts has no key on purpose: its accessible name is its visible caption (dict (512)), and aria-expanded carries the collapsed/expanded state, which screen readers announce in their own language. Prefer this over adding a translatable aria-label whenever a control's visible text is already a good name.

[!IMPORTANT] Adding a key here is only half the job. The keys are not translated in this repository — consumers own the translations. When you add one, it also has to be added to Papyros (both en and nl, under Papyros.debugger in src/frontend/state/Translations.ts), which is where the Dutch strings actually live, and from there it propagates to Dodona. A key that is added here but not in Papyros silently falls back to English.

CSS variables

To adjust the look of the trace, you can adjust the css variables defined in the styles file. Each colour carries the tone it comes from in the Material palette, where 0 is black and 100 is white.

Contributing

Setup

Install dependencies:

yarn install

Build

To build the JavaScript version of your component:

yarn build

To watch files and rebuild when the files are modified, run the following command in a separate shell:

yarn build:watch

Testing

yarn test

This builds the project and runs every test/*_test.js file in headless Chromium, against dist/ rather than src/, so the tests exercise the same entrypoint consumers import.

test/smoke_test.js renders every trace fixture in traces/ and fails on any rendering error. Any .json trace dropped into traces/ is picked up automatically, without touching the test. Other files in test/ cover specific behaviour and are named after the area they exercise.

Dev Server

This project uses modern-web.dev's @web/dev-server for previewing the project without additional build steps. Web Dev Server handles resolving Node-style "bare" import specifiers, which aren't supported in browsers. It also automatically transpiles JavaScript and adds polyfills to support older browsers. See modern-web.dev's Web Dev Server documentation for more information.

To run the dev server and open the project in a new browser tab:

yarn serve

There is a development HTML file located at /dev/index.html that you can view at http://localhost:8000/dev/index.html. Note that this command will serve your code using Lit's development mode (with more verbose errors).

Releasing

npm version 1.5.0
git push --follow-tags

npm version bumps package.json, commits, and creates the matching v1.5.0 tag. Pushing the tag triggers publish.yml, which runs the linters, verifies that the tag matches package.json, publishes @dodona/trace-component to npm, and creates a GitHub release with generated notes. Pre-release versions (e.g. 1.5.0-beta.1) must be valid semver and are published under the next dist-tag instead of latest.