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

@soufianeh/annotate-code

v0.1.1

Published

Link code lines to explanations — an Astro integration and remark plugin with hover highlighting.

Readme

annotate-code

A lightweight widget for linking code lines to explanations — inspired by diveintopython3.net.

Mark specific lines (or multiline chunks) with [N] inline comments. Hovering an explanation highlights the matching code, and vice versa.

annotate-code demo


Usage with Astro

Integration (recommended)

The Astro integration registers the remark plugin and injects the stylesheet automatically — nothing else to configure.

npx astro add @soufianeh/annotate-code

Or manually:

// astro.config.mjs
import { defineConfig } from 'astro/config';
import annotateCode from '@soufianeh/annotate-code';

export default defineConfig({
  integrations: [annotateCode({ theme: 'github-light' })],
});

Then write annotated code blocks in any .md or .mdx page — no imports needed:

```python annotate
def fibonacci(n):
    if n <= 1:    # [1]
        return n
    a, b = 0, 1
    for _ in range(n - 1): # [2]
        a, b = b, a + b    # [3]
    return b               # [4]
---
1: Base cases: fibonacci(0) = 0 and fibonacci(1) = 1.
2: We already know fib(1) = 1, so we only need n - 1 more steps.
3: Simultaneous assignment — both sides evaluate before either variable updates.
4: b always holds the latest value in the sequence.
```

Integration options

annotateCode({
  theme: 'github-dark',  // any Shiki theme — default: 'github-light'
})

Remark plugin (manual)

If you need more control (e.g. you're using the remark plugin outside Astro, or you want to manage the stylesheet yourself):

// astro.config.mjs
import { defineConfig } from 'astro/config';
import remarkAnnotateCode from '@soufianeh/annotate-code/remark';

export default defineConfig({
  markdown: {
    remarkPlugins: [
      [remarkAnnotateCode, { theme: 'github-light' }],
    ],
  },
});

Add the stylesheet to your layout's <head>:

// src/layouts/Layout.astro
import '@soufianeh/annotate-code/styles';

Plugin options

remarkAnnotateCode({
  theme: 'github-dark',        // any Shiki theme — default: 'github-light'
  stylesheetHref: '/ac.css',   // inject a <link> tag per widget — optional
})

How it works

The remark plugin runs at build time and replaces each annotated fenced code block with static HTML:

  1. AST traversal — finds every code node whose meta string includes "annotate".
  2. Block parsing — splits the block on ---: code (with [N] markers) above, N: text annotations below.
  3. Marker stripping — removes [N] markers from each line and records a lineIndex → annotationId map.
  4. Shiki highlighting — highlights the clean code server-side.
  5. HTML generation — wraps each line in a .ac-line span with data-ann-id, adds callout badges, builds an .ac-list of annotation items.
  6. Node replacement — swaps the code AST node for a html node with the widget HTML and a one-time inline hover script.

No client-side framework or runtime highlighter required.


Vanilla JS usage

For plain HTML pages without a build pipeline.

1. Call annotate()

import { annotate } from '@soufianeh/annotate-code/browser';

annotate(document.getElementById('demo'), {
  code: `def fibonacci(n):
    if n <= 1:    # [1]
        return n
    a, b = 0, 1
    for _ in range(n - 1): # [2]
        a, b = b, a + b    # [3]
    return b               # [4]`,
  annotations: [
    { id: 1, text: 'Base cases: fibonacci(0) = 0 and fibonacci(1) = 1.' },
    { id: 2, text: 'We already know fib(1) = 1, so we only need n - 1 more steps.' },
    { id: 3, text: 'Simultaneous assignment — both sides evaluate before either variable updates.' },
    { id: 4, text: 'b always holds the latest value in the sequence.' },
  ],
  highlight: (code) =>          // optional — bring your own highlighter
    Prism.highlight(code, Prism.languages.python, 'python'),
});

2. Include the stylesheet

<link rel="stylesheet" href="node_modules/@soufianeh/annotate-code/demo/styles.css" />

Or import via a bundler:

import '@soufianeh/annotate-code/styles';

Annotation syntax

Single-line:

import os   # [1]

Multiline — use the same number on consecutive lines; the callout badge appears on the last one:

def fibonacci(n): # [3]
    if n <= 1:    # [3]
        return n  # [3]

Supported comment styles: // [N], # [N], -- [N], or bare [N].


API

// Astro integration  ('@soufianeh/annotate-code')
type AnnotateCodeOptions = { theme?: string };  // Shiki theme — default: 'github-light'
export default function annotateCode(options?: AnnotateCodeOptions): AstroIntegration;

// Remark plugin  ('@soufianeh/annotate-code/remark')
type RemarkAnnotateCodeOptions = {
  theme?: string;           // Shiki theme — default: 'github-light'
  stylesheetHref?: string;  // inject a <link> tag per widget — optional
};
export default function remarkAnnotateCode(options?: RemarkAnnotateCodeOptions): Plugin;

// Browser  ('@soufianeh/annotate-code/browser')
type AnnotateOptions = {
  code: string;
  annotations: Array<{ id: number; text: string }>;
  highlight?: (code: string) => string;  // receives clean code (markers stripped)
};
function annotate(container: HTMLElement, options: AnnotateOptions): void;

Dev

pnpm install
pnpm dev             # build + browser-sync with live reload
pnpm build           # compile TypeScript once
pnpm demo:remark     # regenerate demo/remark.html (remark plugin output)

Open http://localhost:3000:

  • demo/index.html — vanilla JS demo (Prism highlighting, runtime)
  • demo/remark.html — remark plugin demo (Shiki highlighting, build-time)