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

@ai-matrx/print

v0.8.13

Published

The AI Matrx print system: the BlockPrinter contract and print-window composition, the flashcards deck printer (duplex-mirrored cut sheets, Avery 5388, study sheets), QR generation with spec quiet zones and e-commerce payload builders, label-sheet printin

Readme

@ai-matrx/print

The AI Matrx print system — everything a browser app needs to turn structured content into paper: a tiny print contract, print-window composition, QR generation with e-commerce payload builders, label-sheet printing on Avery and roll stock with custom label formats, a full flashcard deck printer, a shipped markdown converter with two default print stylesheets, and DOM-capture/markdown → PDF.

Every entry is import-inert and safe to import during SSR — browser APIs are touched only when you call something. /react is the only React entry (a client component entry); everything else is framework-free.

Install

npm install @ai-matrx/print

React ≥18 is an optional peer, needed only for @ai-matrx/print/react.

Entries

@ai-matrx/print — types only

BlockPrinter, PrintVariant, PrintSetting, PrintSettings, LabelTemplate, LabelFormat, QrEcLevel, Flashcard, … — the shared vocabulary, no runtime.

@ai-matrx/print/core — the print contract & window composition

import { buildPrintDocument, openPrintWindow, printHtmlContent, escapeHtml, buildFitTextScript } from "@ai-matrx/print/core";

printHtmlContent("<h1>Report</h1><table>…</table>", "Q3 Report");

BlockPrinter is the one interface a host needs: label, variants, optional settings (boolean / range / number / select), and print(data, variantId, settings). openPrintWindow opens a styled window with Print / Close actions and falls back to an .html download when the popup is blocked. buildFitTextScript(selectors) returns the in-window auto-shrink script (0.5pt steps, 6pt floor) used by the flashcards engine.

@ai-matrx/print/qr — QR generation (not decoding)

import { generateQrDataUrl, generateQrSvg, minQrVersion, buildShortResolverUrl, buildGs1DigitalLink } from "@ai-matrx/print/qr";

const url = buildShortResolverUrl({ origin: "https://yourbrand.com", code: "a1B2c3" }); // https://yourbrand.com/l/a1B2c3
const png = await generateQrDataUrl(url);              // ECC "M", ≥4-module quiet zone — both enforced defaults
const gs1 = buildGs1DigitalLink({ origin: "https://id.yourbrand.com", gtin: "4006381333931", lot: "L42", serial: "S1001", expiry: "271231" });

Error correction defaults to M (never L — scuffed labels need margin) and the quiet zone is clamped to the ISO minimum of 4 modules. The code value in buildShortResolverUrl is an opaque input — mint identities server-side. minQrVersion(byteLen, ecc) / qrModuleCount(version) / qrByteCapacity(version, ecc) expose the symbol math (byte-mode capacities verified against the reference encoder).

@ai-matrx/print/labels — label sheets, roll stock, custom formats

import { qrLabelsPrinter, printQrLabelSheet, downloadLabelsPdf, printCalibrationSheet, applyLabelFormat, LABEL_FORMAT_PRESETS, assertScannable, getLabelTemplate } from "@ai-matrx/print/labels";

// One data shape, three lanes: print window, PDF download, calibration page.
const data = applyLabelFormat(
  LABEL_FORMAT_PRESETS.find((f) => f.id === "garment")!,
  [{ qrValue: "https://yourbrand.com/l/a1B2c3", size: "XL", sku: "TS-001", color: "Black", price: "$29" }],
);
await printQrLabelSheet({ ...data, templateId: "avery-5160" });

Built-in templates: Avery 5160/8160, 5163/8163, 5164/8164, 22806 (2″ square), 22807 (2″ round), plus roll stock — Brother DK-1202 / DK-11201, DYMO 30252, and generic 4×6″ thermal (kind: "roll"). Custom stock is just data via customLabelTemplate(geometry); a dev-time assertion proves every template tiles its sheet. Settings include startAtLabel (reuse a partially-used sheet), copiesPerCode, label ranges, and EC level (default M).

LabelFormat describes a label as ordered elements — qr, text with a title / detail / badge role, image (durable http(s) URLs only) — so clients can define their own layouts as data. Presets: qr-only, qr-caption, garment, asset-spec.

assertScannable(template, payloadByteLen, ecc) warns before anyone prints a payload too dense for the stock (module size below the ~0.4 mm thermal floor); the print lane surfaces it as an on-screen banner automatically.

Print fidelity: QRs are inlined data URIs rasterized at 300 dpi (a print window is a fresh, unauthenticated document — nothing is fetched), print-color-adjust: exact, inch-exact @page geometry, and a print-on-plain-paper calibration sheet per template. Print at 100% scale with no margins.

@ai-matrx/print/flashcards — the deck printer

import { flashcardsPrinter } from "@ai-matrx/print/flashcards";

flashcardsPrinter.print({ title: "Biology 101", cards }, "portrait-6up-duplex", { showCutLines: true });

Ten variants: portrait 6-up and landscape 4-up (each duplex-mirrored — backs column-swapped so long-edge duplex aligns perfectly — or stacked all-fronts-then-all-backs), Avery 5388 index cards, cut-out cards, both-sides, study-sheet table, questions-only self-test, answers-only. Settings: card ranges, cut tick marks / full cut lines, side labels, card numbers, and show-through countermeasures (gray back text, mirrored back text). Face images print from durable URLs only.

@ai-matrx/print/markdown — the shipped converter & print stylesheets

import { markdownToHtml, getMarkdownStylesheet, renderMarkdownDocument, printMarkdown, removeThinkingContent } from "@ai-matrx/print/markdown";

printMarkdown(markdown, { title: "Report" });                       // markdown → print window, one call
const html = markdownToHtml(markdown);                              // → .matrx-* classed body HTML
const css  = getMarkdownStylesheet({ skin: "article" });             // → the matching stylesheet
const page = renderMarkdownDocument(markdown, { title: "Report" });  // → a complete <!DOCTYPE html> page

Two skins off one vocabulary. "document" (default) emits .matrx-* classed HTML — headings, nested lists, markdown tables, images, links, code, FAQ promotion, <flashcards> blocks — inside .matrx-content-container, and its stylesheet is what pastes into a WordPress theme. "article" emits bare semantic tags with the serif AI-response look for print windows (code fences are HTML-escaped there, because a print window does not re-escape). removeThinkingContent strips <thinking> / <think> / <reasoning> — all three, which is why a model switching tag names cannot leak reasoning into a printed page.

Colours are var(--matrx-print-<role>, <default>) throughout (C26): the inline fallbacks make a fresh app render correctly with zero setup, and a host brands it by passing tokens: ":root{--matrx-print-accent:#0f766e}" — appended last, so the host wins. Both sheets carry the print hard parts (@media print, page-break avoidance, orphans/widows, print-color-adjust).

@ai-matrx/print/directives — page breaks, one grammar everywhere

import { isPageBreakLine, splitAtPageBreaks, PAGE_BREAK_MARKDOWN } from "@ai-matrx/print/directives";

Put <!-- pagebreak --> on its own line to start a new printed page (\pagebreak, \newpage, <!-- newpage --> and <div style="page-break-after: always"></div> are accepted too). Both converters render it as <div class="matrx-page-break"> — a dashed "Page break" rule on screen, a real page break on paper — and markdownToPdfBlob starts a new PDF page there. The entry has no dependencies, so a chat or editor renderer can recognise the same syntax without loading the stylesheets.

@ai-matrx/print/pdf — DOM capture & markdown → PDF

import { captureToPDF, captureElementsToPDF, markdownToPdfBlob } from "@ai-matrx/print/pdf";

await captureToPDF(document.getElementById("report")!, { filename: "report", orientation: "landscape" });
const blob = await markdownToPdfBlob(markdown);                                    // converter + stylesheet included
const branded = await markdownToPdfBlob(markdown, { skin: "article", tokens });    // tune without replacing
const custom = await markdownToPdfBlob(markdown, { convertToHtml, loadCss });      // override either port

markdownToPdfBlob needs nothing from you. Both ports ship a working default (they were REQUIRED injections until 0.3.0); supplying one replaces that default and leaves the other alone. The defaults load through a lazy import("@ai-matrx/print/markdown"), so a consumer that only does DOM capture never pulls in the stylesheets.

Nothing degrades silently: a flashcard missing its Front:/Back:, markdown that converts to an empty document, an image that 404s or never finishes loading (html2canvas would paint a blank rectangle and say nothing), and a failed rasterization all report through onNotice — or console.warn with the remedy when no sink is given. imageTimeoutMs (default 8000) bounds the wait.

html2canvas + jsPDF, lazy-loaded on use. Handles the Tailwind v4 problem (oklch/lab colors html2canvas can't parse) via a scoped getComputedStyle patch that is always restored. captureElementsToPDF renders deliberately paginated report pages one-per-PDF-page; the single-element lane slices one tall canvas across pages.

@ai-matrx/print/react — the options dialog & sheet preview

import { PrintOptionsDialog, usePrintOptions, LabelSheetPreview } from "@ai-matrx/print/react";

PrintOptionsDialog renders any BlockPrinter's variants + settings (desktop dialog, mobile bottom drawer) and runs the print. LabelSheetPreview shows a scaled, exact-proportion preview of a label sheet, with a calibration outline mode. Tailwind CSS classes; Radix dialog + vaul drawer are bundled dependencies.

License

MIT

@ai-matrx/print/document — print-grade documents (PDF, Word, EPUB, HTML)

import { exportDocument, downloadDocumentExport } from "@ai-matrx/print/document";

const exp = await exportDocument(markdown, "docx"); // "pdf" | "docx" | "epub" | "html" | "markdown"
downloadDocumentExport(exp);                         // browser: saves "<title>.docx"

Settings ride in the markdown's frontmatter:

---
title: Quarterly Review
subtitle: Operations
author: Jane Park
date: today
cover: true
toc: true                      # or { depth: 2, title: Contents }
page: { size: a4, orientation: portrait, margins: 1in }
header: "{title} | | {date}"   # left | center | right
footer: "Page {page} of {pages}"
columns: 1
numberSections: true
csl: apa                       # apa | mla | chicago
references:
  - { id: smith2020, title: Paper Cuts, author: "Smith, Jane", issued: 2020, publisher: Acme }
---

In the body: <!-- pagebreak -->, <!-- section landscape columns=2 -->, [[toc]], ![Caption](url){#fig:chart}, Table: Caption {#tbl:sales}, ## Methods {#sec:methods}, see @fig:chart, [@smith2020, p. 4]. All four formats come from one parsed tree (parseDocument), so they agree.

Citations are formatted by citeproc-js over the official CSL styles: csl: accepts any style name from the CSL repository (zotero.org/styles) or a .csl URL; apa, mla, chicago, chicago-notes, ieee and harvard are bundled (offline). References come from the frontmatter and from your app via exportDocument(md, fmt, { resolveReferences: async (keys) => cslItems }). PDFs are hyphenated with Knuth–Liang patterns for the document's lang, and emoji / symbols print through Noto Emoji and Noto Sans Math.

CSL styles and locales © the Citation Style Language project, CC BY-SA 3.0. Noto Emoji and Noto Sans Math are SIL Open Font License fonts (loaded at export time from jsDelivr). DocumentPrintPreview (in /react) shows the real PDF pages with Print and every download.