mark↓ Angular Adapter

February 20, 2026 · View on GitHub

(published as @mzebley/mark-down-angular)

Angular bindings for the mark↓ core runtime. This package wraps SnippetClient with Angular-friendly providers, services, and components so you can render Markdown snippets safely inside your application. For background on the monorepo, see the root README.

Table of contents

  1. Installation
  2. Bootstrap configuration
  3. Consuming snippets
  4. <snippet-view> component
  5. Server-side rendering
  6. Testing tips
  7. Roadmap
  8. Related packages

Installation

Install the Angular adapter alongside the core runtime:

npm install @mzebley/mark-down-angular @mzebley/mark-down

You will also need a manifest generated by the CLI.

Bootstrap configuration

Provide a shared SnippetClient from your root bootstrap call or feature module:

import { bootstrapApplication } from "@angular/platform-browser";
import { provideSnippetClient } from "@mzebley/mark-down/angular";

bootstrapApplication(AppComponent, {
  providers: [
    ...provideSnippetClient({
      manifest: "/assets/content/snippets/manifest.json",
      base: "/assets/content/snippets",
    }),
  ],
});

provideSnippetClient wires up the client as an Angular provider using the same options supported by the core runtime (manifest, base, fetch, frontMatter, cache, verbose). Prefer the scoped @mzebley/mark-down/angular entry point for tree-shaking and clearer typing. For backwards compatibility this package also re-exports provideMarkDown, MARK_DOWN_CLIENT, and the legacy SnippetService name.

Angular compatibility

Angular versionStatus
17.x✅ Supported
18.x✅ Supported
19.x✅ Supported
20.x✅ Supported

The package declares peer dependency ranges >=17 <21 so projects running any currently supported Angular major release can install without --legacy-peer-deps.

Consuming snippets

Inject MarkdownSnippetService into components or services to access Observables for snippets:

import { Component, inject } from "@angular/core";
import { MarkdownSnippetService } from "@mzebley/mark-down/angular";

@Component({
  selector: "docs-hero",
  template: `
    <ng-container *ngIf="hero$ | async as hero">
      <h1>{{ hero.title }}</h1>
      <div [innerHTML]="hero.html"></div>
    </ng-container>
  `,
})
export class DocsHeroComponent {
  private readonly snippets = inject(MarkdownSnippetService);
  readonly hero$ = this.snippets.get("getting-started-welcome");
}

The service mirrors the core client APIs (get, listAll, listByType, listByGroup, search) but returns cold Observables that share cached results across subscribers.

<snippet-view> component

Render snippets declaratively with the bundled standalone component:

<snippet-view
  [slug]="'components-button'"
  (loaded)="onSnippetLoaded($event)"
></snippet-view>

Features:

  • Uses Angular's DomSanitizer for trusted HTML binding and DOMPurify in browser rendering.
  • Emits a loaded event once the snippet resolves so parent components can react.
  • Provides a loading placeholder and gracefully emits undefined when the slug cannot be resolved.
  • Supports class/ngClass bindings for styling since it renders a standard <div>.

Security warning

The Angular adapter is intentionally compatible with untrusted/unsanitized snippet pipelines. That flexibility is a feature, but it means you must decide where sanitization happens:

  • For untrusted content, sanitize in SnippetClient (sanitize option) and/or during build with mark-down compile-page --sanitize.
  • If sanitization is disabled, snippet HTML is treated as trusted and may include dangerous markup.

Server-side rendering

When running in Angular Universal, supply a server-compatible fetch implementation:

import fetch from "node-fetch";

provideSnippetClient({
  manifest: () => import("../snippets-index.json"),
  fetch: (url) =>
    fetch(url).then((response) => {
      if (!response.ok) {
        throw new Error(`Request failed with status ${response.status}`);
      }
      return response;
    }),
});

The provider forwards all options to the underlying SnippetClient, so SSR, custom cache policies, and preloaded manifests work exactly like the core package.

Testing tips

  • Provide a mock manifest array during tests: provideSnippetClient({ manifest: mockManifest }).
  • Use MarkdownSnippetService with the Angular TestBed to assert filtering behaviour.
  • Pair with the example application to see how snippets integrate with routing and feature modules.

Roadmap

  • Template primitives – structural directives for rendering snippet lists via *markDownSnippets.
  • AsyncPipe optimisations – helpers that automatically unsubscribe / reuse cached Observables when using standalone components.
  • Schematics – Angular CLI generator for wiring provideMarkDown + SnippetViewComponent.
  • SSR hydration helpers – share manifest snapshots between server and browser to avoid double fetching.