agmission/Development/server/docs/MARKDOWN_VIEWER.md
Devin Major ad7db99f07
Some checks failed
Server Tests / Mocha – Unit & Utility Tests (push) Successful in 1m29s
Server Tests / Jest – Integration Tests (push) Failing after 1m57s
all Data Export API changes until may 8 2026
2026-05-08 11:48:21 -04:00

3.8 KiB

MarkdownViewerComponent

Selector: app-markdown-viewer
Module: AppSharedModule (already exported — no extra import needed)

A generic, self-contained markdown renderer. Handles parsing, heading-based section splitting, Mermaid diagrams, inline video embeds, syntax-highlighted find-in-page, and emits a table-of-contents item list for the host to render wherever it likes.


Inputs

Input Type Default Description
src string undefined URL of a remote .md file to fetch and render. Mutually exclusive with markdown.
markdown string undefined Raw markdown string to render inline. Takes precedence over src if both are set.
showFindBar boolean false Show the find-in-page bar above the content.

Outputs

Output Payload Description
tocItemsChange { label: string; anchorId: string }[] Emitted after content loads. Each item corresponds to a top-level heading in the document. Use this to render a Table of Contents outside the component.

Public Methods

Method Signature Description
scrollToId (anchorId: string) => void Scrolls the content area to the element with the given id. Use in conjunction with tocItemsChange to implement external TOC navigation.

Usage Examples

Render a remote file

<app-markdown-viewer src="/assets/docs/readme.md"></app-markdown-viewer>

Render an inline string

<app-markdown-viewer [markdown]="myMarkdownString"></app-markdown-viewer>

With find-in-page bar

<app-markdown-viewer [markdown]="content" [showFindBar]="true"></app-markdown-viewer>

With an external Table of Contents

The component emits TOC items but does not render a TOC sidebar itself. The host component is responsible for displaying the list and wiring up scroll navigation.

Template:

<!-- TOC rendered by the host -->
<ul>
  <li *ngFor="let item of tocItems">
    <a href="#" (click)="scrollToHeading($event, item.anchorId)">{{ item.label }}</a>
  </li>
</ul>

<!-- Viewer -->
<app-markdown-viewer
  #viewer
  [markdown]="content"
  (tocItemsChange)="tocItems = $event">
</app-markdown-viewer>

Component:

import { ViewChild } from '@angular/core';
import { MarkdownViewerComponent } from '../shared/markdown-viewer/markdown-viewer.component';

export class MyComponent {
  @ViewChild(MarkdownViewerComponent) viewer?: MarkdownViewerComponent;

  tocItems: { label: string; anchorId: string }[] = [];
  content = '# Hello\n\nSome text.\n\n## Section Two\n\nMore text.';

  scrollToHeading(event: MouseEvent, anchorId: string): void {
    event.preventDefault();
    this.viewer?.scrollToId(anchorId);
  }
}

Content Features

Mermaid diagrams

Fenced code blocks with language mermaid are automatically rendered as SVG diagrams:

```mermaid
graph TD
  A --> B
```

Inline video embeds

Use the custom !video[title](url) syntax to embed video files (.mp4, .webm, .ogg) or iframes (YouTube, Vimeo, etc.):

!video[Demo walkthrough](https://example.com/demo.mp4)

!video[YouTube video](https://www.youtube.com/embed/abc123)

Tables

Standard markdown tables are styled with borders and alternating row colours automatically.


Notes

  • Content is split into sections at every heading. The text before the first heading becomes an "intro" block.
  • src and markdown are mutually exclusive. If both are provided, markdown wins.
  • scrollToId is a no-op if the component has not yet rendered or the anchor does not exist in the current content.
  • The component is part of AppSharedModule and does not need to be imported separately in feature modules that already import AppSharedModule.