stnd.build · DocumentationSTANDARD MANUALSTD-STND-PRE · 2026-03-15
STD-STND-PRE

@stnd/press

@stnd/press

Markdown → Beautiful HTML with classical typography.

The rendering engine for Standard Garden. Built on markdown-it, enhanced with a typography pipeline inspired by 500 years of printing tradition.

Designed for Cloudflare Workers and edge environments.

Install

pnpm add @stnd/press

Quick Start

import { Press } from “@stnd/press”;

const press = new Press(“# Hello\n\nThis is **beautiful** text.”);
await press.parse();

console.log(press.html); // Rendered HTML with proper typography

With Astro Content Collections

When using Astro’s content collections, frontmatter is already parsed. Pass it directly to skip redundant parsing:

const { service } = Astro.props;
const press = new Press(service.body, { frontmatter: service.data });
await press.parse();

What it does

  1. Pre-processing::syntax patterns, Obsidian comment stripping
  2. Module plugins — Custom ::patterns from your index.module.js (passed explicitly)
  3. Markdown rendering — CommonMark via markdown-it with callouts, footnotes, heading anchors, and Prism syntax highlighting
  4. Post-processing — Smart quotes, em dashes, ellipses, fractions, orphan prevention, locale-aware spacing
  5. Sanitization — DOMPurify (opt-in, off by default)

Options

const press = new Press(content, {
  locale: “fr”, // Typography locale (en, fr, de, es, it)
  sanitize: false, // DOMPurify sanitization (default: false)
  renderHtmlAsRaw: false, // Render ```html blocks as raw HTML
  frontmatter: entry.data, // Pre-parsed frontmatter (skip re-parsing)
  plugins: [], // Module press plugins from index.module.js
  checkSyntax: true, // Warn about unprocessed ::patterns
  html: true, // Allow HTML in markdown
  breaks: true, // Convert \n to <br>
  linkify: true, // Auto-link URLs
});

API

Press class

const press = new Press(content, options);
await press.parse();

press.html; // Rendered HTML (headings include id attributes)
press.css; // Injected CSS from plugins
press.head; // Injected <head> content from plugins
press.frontmatter; // Parsed (or pre-provided) frontmatter
press.title; // Extracted title
press.readingTime; // “3 mins”
press.wordCount; // 450
press.preview; // Plain-text excerpt
press.isProcessed; // true after parse()

Lightweight Helpers

Import from @stnd/press/helpers to avoid pulling in the rendering engine:

import {
  parseFrontmatter, // Parse YAML frontmatter from markdown
  extractTitleFromContent, // Extract title from headings or first line
  createPreview, // Generate plain-text excerpt
  getReadingTime, // Estimate reading time
  applyFrontmatterEnrichment, // Add computed metadata to frontmatter
  extractCssVariables, // Convert stnd_* keys to CSS custom properties
  generateOgImageUrl, // Build OG image URL from metadata
  shouldShowIndex, // Check if content needs a table of contents
} from “@stnd/press/helpers”;

Typography (direct access)

import {
  runPreProcessing,
  runPostProcessing,
  getRulesForLocale,
} from “@stnd/press”;

// Or access configuration directly
import {
  typographyRules,
  orphanWords,
  fractionMap,
} from “@stnd/press/typography/config.js”;

Heading Anchors

All headings in rendered HTML automatically receive id attributes via markdown-it-anchor.
Fragment links like #my-heading work out of the box — no post-processing needed.

<!— Input —>
## My Heading

<!— Output —>
<h2 id="my-heading">My Heading</h2>

Typography

Press applies locale-aware typographic rules automatically:

Rule Example Result
Em dash
Ellipsis
Smart quotes “hello” “hello”
Fractions ½ ½
Arrows
Orphan prevention a cat a + non-breaking space + cat
French spacing Bonjour ! Thin space before !

Supported Locales

  • English (en) — Curly quotes "“‘’, comma thousands 1,000
  • French (fr) — Guillemets «», thin-space thousands 1 000
  • German (de) — Low quotes „”, dot thousands 1.000
  • Spanish (es) — Guillemets «», dot thousands 1.000
  • Italian (it) — Guillemets «», dot thousands 1.000

::syntax Patterns

Press includes a built-in pattern system for layout directives in markdown:

<div class=“hero”>

This text becomes a hero block.

</div>

<div class=“callout” data-callout=“tip”>
<div class=“callout-title”>
<span class=“callout-icon”>💡</span>
<span class=“callout-title-inner”>Tip</span>
</div>
<div class=“callout-content”>

This is a tip callout with an icon.

</div>
</div>


<div class=“columns-2”>
<div class=“column”>

Left column content.

</div>
<div class=“column”>

Right column content.

</div>
</div>


<aside class=“note”>This is an inline note.</aside>

See typography/SYNTAX_GUIDE.md for the full list of built-in patterns.

Syntax Highlighting

Prism.js with these languages out of the box:

bash, yaml, json, markdown, javascript, typescript, css

Need more? Import them before creating a Press instance:

import “prismjs/components/prism-python.js”;
import “prismjs/components/prism-ruby.js”;
import { Press } from “@stnd/press”;

Sanitization

Sanitization is off by default. Astro and most frameworks handle this already.

Enable it for user-generated content (e.g., Standard Garden’s paste feature):

const press = new Press(untrustedContent, { sanitize: true });

When enabled, DOMPurify strips dangerous tags/attributes while preserving semantic HTML, SVGs, <video>, <details>, and style attributes.

Relationship to other packages

Raw file (DOCX, PDF, etc.)
       ↓
  @stnd/ingest    →  “Here's clean Markdown”
       ↓
  @stnd/press     →  “Here's beautiful HTML”

@stnd/ingest handles messy input. @stnd/press handles beautiful output.

Changelog

0.7.0

  • Breaking: Renamed folios option → plugins (aligns with module architecture rename)
  • Breaking: Renamed all internal typography “folio” terminology → “plugin”
  • Renamed initializeTypographyFoliosinitializeTypographyPlugins
  • Renamed registerTypographyFolioregisterTypographyPlugin
  • Renamed getMarkdownItFoliosgetMarkdownItPlugins
  • Renamed getAllTypographyFoliosgetAllTypographyPlugins
  • Renamed clearTypographyFoliosclearTypographyPlugins
  • Renamed markdownFolio export → markdownPlugin (in tags.js, wikilinks.js)
  • Updated all references from index.folio.jsindex.module.js

0.6.0

  • Breaking: Removed document-converter.js → moved to @stnd/ingest
  • Breaking: Removed rehype-markdown/ plugins (use markdown-it pipeline instead)
  • Breaking: Sanitization now opt-in (sanitize: false by default)
  • Added frontmatter option to skip re-parsing
  • Added locale option (replaces lang)
  • Lazy-initialize typography plugins (no side effects on import)
  • Removed dead dependencies: cheerio, mammoth, pdfjs-dist, html-to-md
  • Removed @stnd/utils dependency
  • Added <video>, <section>, <aside>, <nav>, style to sanitization allowlist
  • Cleaner, more focused API
Standard OS — stnd.buildSTD-STND-PRE · rev. 2026-03-15