Welcome to Vanilla Breeze
This bell pulls live notifications from /go/notify/messages — the same contract documented at /docs/concepts/service-contracts/. Static articles like this one are the no-JS / no-backend fallback.
This bell pulls live notifications from /go/notify/messages — the same contract documented at /docs/concepts/service-contracts/. Static articles like this one are the no-JS / no-backend fallback.
Render markdown with progressive enhancement. Supports external files, inline content, pluggable parsers, and VB theme integration.
A platform-native markdown viewer custom element. Renders markdown into light DOM so VB's CSS cascade, themes, and component styles apply automatically. Progressive enhancement via the <pre> slot ensures content is readable without JavaScript.
The component resolves content using this priority chain:
<pre>Raw markdown is visible as readable text if JS is disabled. Hidden after render.
<markdown-viewer> <pre># Hello world This is **inline** markdown with a graceful fallback.The raw text is visible if JS is disabled. </pre></markdown-viewer>
<script>If a <script> has an unknown MIME type the browser does not execute or render it. Here we use text/markdown to create a markdown block to render. Like the next approach using <template>, there is no fallback without JavaScript support.
<markdown-viewer> <script type="text/markdown"># Hello world This content is **invisible** without JavaScript. </script></markdown-viewer>
<template>Inert DOM node can be consulted as long as you put the data-md attribute on it, framework-friendly. No fallback without JS.
<markdown-viewer> <template data-md># Hello world | Name | Role ||-------|----------|| Alice | Engineer || Bob | Designer | </template></markdown-viewer>
srcFetch external markdown using the JS fetch() API. CORS rules apply.
<markdown-viewer src="/path/to/document.md"></markdown-viewer>
Set data-theme on the viewer or let it inherit from the nearest ancestor with [data-theme]. The theme propagates to the .md-content container.
<!-- Explicit theme --><markdown-viewer data-theme="brutalist"> <pre># Themed content</pre></markdown-viewer> <!-- Inherited from ancestor --><section data-theme="editorial"> <markdown-viewer> <pre># Inherits editorial theme</pre> </markdown-viewer></section>
The default parser is marked with GFM enabled. Override it with any function that accepts a markdown string and returns an HTML string:
const viewer = document.querySelector('markdown-viewer');viewer.parser = (md) => myCustomRenderer(md);
Add the highlight attribute to fire markdown-viewer:highlight events for each code block. Bring your own highlighter:
<markdown-viewer highlight> <pre># Code Blocks ```javascriptconsole.log('hello');``` </pre></markdown-viewer> <script type="module"> document.addEventListener('markdown-viewer:highlight', ({ detail }) => { // detail.node = the code element // detail.language = e.g. "javascript" hljs.highlightElement(detail.node); });</script>
Listen for markdown-viewer:rendered and lazy-load Mermaid only when needed:
document.addEventListener('markdown-viewer:rendered', ({ detail }) => { const diagrams = detail.node.querySelectorAll('code.language-mermaid'); if (diagrams.length) { import('mermaid').then(m => m.default.run({ nodes: diagrams })); }});
Register the optional callout extension with marked for :::type blocks (warning, info, tip, danger, note):
import { marked } from 'marked';import { calloutExtension } from './markdown-viewer/vb-extensions.js';marked.use({ extensions: [calloutExtension] });
| Attribute | Values | Default | Description |
|---|---|---|---|
src | string | — | URL of external markdown file |
loading | "eager", "lazy" | eager | Defer fetch until element enters viewport (Phase 3) |
highlight | boolean | — | Fire per-block markdown-viewer:highlight events after render |
ping | string | — | URL to ping with render metadata via sendBeacon |
data-theme | string | — | Theme name propagated to .md-content container |
| Event | Detail | Description |
|---|---|---|
markdown-viewer:fetch | { src } | Fired when external fetch begins |
markdown-viewer:rendered | { src, node } | Fired after parse and render complete |
markdown-viewer:highlight | { node, language } | Fired per code block when highlight attribute is set |
markdown-viewer:error | { error } | Fired on fetch or parse failure |
| Property / Method | Description |
|---|---|
.parser | Get/set custom parser function (md → html string). Overrides the default marked parser. |
.render() | Force a re-render from the current content source. Returns a Promise. |
.reload() | Re-fetch the src URL and re-render. Returns a Promise. |
The <pre> slot provides the best progressive enhancement:
| Slot | JS disabled | Crawlable | Recommended for |
|---|---|---|---|
src | Nothing visible | No | External files |
<script> | Nothing visible | No | Build-time content |
<template> | Nothing visible | No | Framework content |
<pre> | Raw text visible | Yes | Progressive enhancement |