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

@crowi/plugin-renderer-katex

v1.0.0-alpha.4

Published

KaTeX math renderer for Crowi 2.x. Parses `$inline$` and `$$display$$` via remark-math and renders to HTML server-side via katex.renderToString.

Readme

@crowi/plugin-renderer-katex

KaTeX math renderer for Crowi 2.x. Parses $inline$ and $$display$$ LaTeX via remark-math and renders each math node to HTML via katex.renderToString.

No I/O. No cache (every save re-renders).

What it does

Given a page body containing:

The Pythagorean theorem: $a^2 + b^2 = c^2$.

Display style:

$$
\int_0^1 x \,dx = \frac{1}{2}
$$

The plugin emits the corresponding <span class="katex-inline">…</span> and <div class="katex-block">…</div> wrappers carrying the KaTeX- generated HTML.

KaTeX CSS

KaTeX's HTML output references class="katex" rules that ship in katex/dist/katex.min.css. The plugin self-serves this CSS (and the webfonts it references) instead of requiring @crowi/web to carry a katex dependency or a global CSS import:

  • At build time, scripts/copy-katex-assets.mjs (a tsup onSuccess hook) copies katex/dist/katex.min.css and its referenced font files from the installed katex package into this plugin's own dist/assets/.
  • registerRoutes mounts GET /api/plugins/@crowi/plugin-renderer-katex/katex.min.css and a fonts/:filename route for each font, both public (unauthenticated), serving directly from the in-memory copy of those built-in assets — no filesystem path is built from the request, so there is no path-traversal surface.
  • registerRenderer advertises the CSS path via registry.addStylesheet(...). The API publishes it in GET /api/app/info's rendererStylesheets array once (and only once) registerRoutes above has succeeded, so the manifest never advertises an unreachable path.
  • The web app's RendererStylesheets component reads that manifest and injects a <link rel="stylesheet"> resolved against the runtime API origin (resolveApiUrl), the same origin resolver the rest of the API client uses. No web-side build step or dependency is required.

If the API and Web apps are deployed on different origins, make sure the API's CORS policy allows the Web origin (CLIENT_URL, already the default) and that any deployment CSP on the Web app allows the API origin in style-src and font-src — see apps/crowi-site/content/docs/{ja,en}/operations/configuration.mdx.

Strict mode

Both renderers pass strict: 'ignore' + throwOnError: false to KaTeX. Malformed LaTeX falls back to a red error frame in the rendered HTML without crashing the page.

Trust mode

trust is left at its KaTeX default (false). \href and other trust-gated commands are inert. Phase 6 does NOT expose a config toggle for this — the security trade-off is subtle and an operator-misconfiguration could enable JS injection. Phase 7+ may add a per-plugin admin option if real demand arrives.

Install

Bundled in the Crowi monorepo:

pnpm --filter @crowi/api add -D @crowi/plugin-renderer-katex
# or in a standalone runner:
npm install @crowi/plugin-renderer-katex

No web-side install step is required — the plugin self-serves its CSS/font assets from its own public route (see "KaTeX CSS" above), so @crowi/web never needs a katex dependency.

Configure

Enable in crowi.config.json

{
  "plugins": [
    "@crowi/plugin-renderer-katex"
  ]
}

A server restart is required for plugin-list changes.

Per-plugin config

None — the plugin uses vanilla KaTeX with sensible defaults baked in at registration time.

Out of scope (Phase 6)

  • KaTeX macros / \newcommand user-defined commands — vanilla KaTeX standard commands only.
  • MathJax compatibility — \[ \] / \( \) delimiters not parsed.
  • Inline trust opt-in — disabled by default for security.
  • Per-org / per-page enable toggle — Phase 7+.

See also

  • remark-math — upstream parser that emits math / inlineMath mdast nodes.
  • KaTeX docs — supported commands.
  • RFC-0002 §"Phase 6 — bundled renderer plugins" for the design rationale.