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

@clean-jsdoc-theme/utils

v5.0.5

Published

Shared types and schemas for clean-jsdoc-theme

Readme

@clean-jsdoc-theme/utils

The shared core every other package imports: the type contracts that define the setu→dwar boundary and the slug rules used on both sides, plus one block of pure runtime logic — opts validation, the build report, and the diagnostics spine. It stays browser-safe (rang imports it into the browser) by injection: the network (fetch) and the node:zlib gzip sizer are passed in by the caller, never imported here.

What's inside

src/
├── doclet-schema.ts   # JSDoc doclet shape (TDoclet, kinds, params, meta, …)
├── salty.ts           # salty (taffy) collection helpers + types
├── site/              # the setu↔dwar contract (types-first)
│   ├── page.ts        # Page (+ PageKind, 'source' body), Frontmatter, Heading
│   ├── manifest.ts    # SiteManifest, NavNode, SearchEntry, ExtractManifest, BuildSpec
│   ├── render.ts      # OutputFile, RenderOptions, RenderResult, RenderError, RenderWarning
│   ├── theme.ts       # ThemeTokens, ThemeColors, ThemeConfig, ComponentOverrides
│   ├── site-name.ts   # SiteName (text | logo set) + siteNameText / resolveSiteLogo
│   ├── islands.ts     # IslandName union + IslandPropsMap
│   └── slug-rules.ts  # slugifyHeading / slugifyPath / slugifySourcePath
└── config/            # PURE opts validation + build report (network/zlib injected)
    ├── diagnostics.ts # Diagnostic model + DiagnosticBag + formatDiagnostics
    ├── opts-schema.ts # zod schemas + THEME_OPT_KEYS
    ├── validate-opts.ts # validateThemeOpts → { value, diagnostics }
    ├── site-name.ts   # validateSiteName (shape only)
    ├── fonts.ts       # validateFonts (heading/body existence-checked; per-locale keys)
    ├── locales.ts     # validateLocales (opts.locales/defaultLocale → ValidatedLocales)
    ├── google-fonts.ts# createGoogleFontResolver (injectable fetch; fail-open)
    ├── suggest.ts     # near-miss "did you mean X?" key suggestions
    ├── report.ts      # formatBuildReport (per-route sizes + optional gzip)
    └── format.ts      # humanFileSize, byteLength, ANSI helpers

Public API

The package is types-first; everything is re-exported from the barrel:

import type {
  SiteManifest,
  Page,
  PageKind,
  NavNode,
  SearchEntry,
  Frontmatter,
  Heading,
  OutputFile,
  RenderOptions,
  RenderResult,
  RenderError,
  ThemeConfig,
  ThemeTokens,
  ThemeColors,
  ComponentOverrides,
  SiteName,
  IslandName,
  IslandPropsMap,
  TDoclet,
} from '@clean-jsdoc-theme/utils';

import {
  // slug rules (shared by setu + dwar)
  slugifyHeading,
  slugifyPath,
  slugifySourcePath,
  // opts validation + build report (the bridges call these)
  validateThemeOpts,
  formatBuildReport,
  DiagnosticBag,
  formatDiagnostics,
  // the i18n contract (setu emits, aadesh reads)
  toExtractManifest,
} from '@clean-jsdoc-theme/utils';

Slug helpers

  • slugifyHeading(text, registry?) — heading text → anchor id. Pass a shared Map to dedupe colliding ids on a page (-1, -2).
  • slugifyPath(parts) — longname parts → a URL path segment.
  • slugifySourcePath(path) — a source file path → its source/<file> slug.

Opts validation + report (config/)

  • validateThemeOpts(input){ value, diagnostics } — normalizes + validates the theme options (zod schemas, a live Google-Font existence check, unknown-key "did you mean?" suggestions). The bridges call this early; a bad font/typo only warns unless strict escalates it.
  • formatBuildReport(input) — the Next.js-style per-route size table (gzip sizer injected, so this module stays browser-safe).
  • DiagnosticBag / formatDiagnostics — the diagnostics spine reused by setu, the bridges, and bhasha's validation primitives.

The i18n / build contract

ExtractManifest + toExtractManifest(manifest) (what aadesh reads in extract mode) and BuildSpec (the per-locale render spec) live here so setu, the bridges, and aadesh all agree on the shape.

Why it exists

The setu↔dwar contract lives here exactly once, so both sides import the same shapes and can never drift. The slug rules are shared for the same reason: setu generates the nav/TOC anchors and dwar emits the rendered heading ids — using one implementation guarantees the two agree. The config/ logic lives here (rather than in a bridge) so JSDoc and TypeDoc validate options and print reports identically.

License

MIT.