# Render without an editor

Generate SVG and PNG from an explicit language and source, with cancellation and cleanup.

Use `@quirekit/text-diagram/browser` when you only need an image. It requires neither Vue nor the authoring UI. The caller supplies the language explicitly; the renderer does not guess it from source.

## 1. Generate SVG from source

Provide a language, source and cancellation signal. In a browser, render a two-node flowchart:

```ts [Generate SVG]
import { renderTextDiagram, rasterizeTextDiagram } from '@quirekit/text-diagram/browser'
const controller = new AbortController()
const vector = await renderTextDiagram('mermaid', 'flowchart LR; A-->B', {
  ownerDocument: document,
  signal: controller.signal,
})
```

`ownerDocument` supplies browser measurement. `signal` allows cancellation when source changes or the page exits. The result retains this render's source and SVG.

## 2. Generate PNG from the same result

```ts [Generate PNG]
const raster = await rasterizeTextDiagram(vector, document, controller.signal)
```

`vector.svg` is a static SVG string; `raster.dataUrl` can be used as an image `src`. Both retain the rendered `language` and `source`. Before displaying a result, verify that its request is still current; never attach an old image to new source.

## Concurrency and cleanup

For successive edits, abort the previous controller before creating one for the new source. Cancellation prevents late results from being accepted; it does not promise immediate computation cancellation in every engine. Mermaid renders are serialized in a shared queue. PlantUML / DOT use independent sandbox frames removed on cancellation.

If you create a Blob URL from SVG, call `URL.revokeObjectURL` when replacing the image or destroying the host. The host still owns its images, containers and events. PNG has a white background and scales to the raster budget; its pixel dimensions may differ from the SVG.

## Keep source on failure

Blank or oversized source, syntax errors, unsupported external resources and engine timeouts can reject the Promise. Retiring an old request normally needs no error message. A current failure should show a short explanation, the original source and a retry action. Do not accept a diagnostic image as a valid preview.

Model functions do not validate DSL syntax. Editor highlighting is an authoring aid; successful engine rendering is the validation step.

## Server rendering

Source objects, templates and Markdown fence functions work in Node. These rendering functions require DOM, font measurement, iframes and Canvas: **they are not a Node rendering API**. SSR can display a saved PNG; open the workbench on the client. See [deployment](/en/guide/deployment) and the [browser API](/en/api/browser).

## Complete module reference

`recipes/render.ts` combines these steps in one function; `shared/types.ts` defines the two results. Inspect the complete files below:

### recipes/render.ts

```ts
import type { TextDiagramLanguage } from "@quirekit/text-diagram";
import { renderTextDiagram, rasterizeTextDiagram } from "@quirekit/text-diagram/browser";
import type { DiagramFiles } from "../shared/types";

/**
 * Renders both formats in a browser without mounting the authoring UI.
 * @param language - Explicit supported grammar.
 * @param source - Exact source, kept alongside the generated files.
 * @param owner - Browser document used for measurement and rasterization.
 * @param signal - Abort on source replacement or host destruction.
 * @returns Sanitized SVG and PNG tied to the same immutable source snapshot.
 */
export async function createDiagramFiles(language: TextDiagramLanguage, source: string, owner: Document, signal: AbortSignal): Promise<DiagramFiles> {
  const vector = await renderTextDiagram(language, source, { ownerDocument: owner, signal });
  const raster = await rasterizeTextDiagram(vector, owner, signal);
  signal.throwIfAborted();
  return { vector, raster };
}

```

### shared/types.ts

```ts
import type { TextDiagramEditRequest, TextDiagramEmbed, TextDiagramSnapshot, TextDiagramRaster } from "@quirekit/text-diagram";

/** Minimal synchronous host; durable storage belongs to its caller. */
export interface DiagramSession {
  /** @returns The last accepted immutable object. */
  read(): TextDiagramEmbed;
  /** @returns A new edit request capturing the current baseline. */
  capture(): TextDiagramEditRequest;
}

/** Two output formats generated from exactly the same source. */
export interface DiagramFiles {
  /** Sanitized vector snapshot. */
  readonly vector: TextDiagramSnapshot;
  /** Bounded PNG projection. */
  readonly raster: TextDiagramRaster;
}

```
