Markdown
Renders markdown as themed HTML, as a document or as an inline label, with an optional source view.
Live demo
Markdown renders GitHub-Flavored Markdown into HTML that themes entirely from the token register: headings ride the type scale, rules and quotes ride the border and surface ramps, and fenced code borrows the same --code-* family the Code component owns, so a fence inside a document and an <xtyle-code> beside it agree in any theme. GFM is on — tables, task lists, strikethrough, and autolinks all render.
inline switches to a label render: emphasis, code, links and strikethrough, but no blocks and no paragraph wrapper, so it drops into a tab title or a chip and inherits its type — a generated label that opens with # stays text instead of erupting a heading into a tab strip. editable adds a source view the reader can switch to, emitting input as it is typed. It ships no sanitizer, by design. Raw HTML in the source is escaped to text rather than rendered, and link and image URLs are written from a scheme allowlist, so everything that reaches the DOM is markup the renderer generated itself from a closed token set. There is no allow-html escape hatch: it would reintroduce the arbitrary-HTML problem the design exists to avoid.
When to use
How this component composes with the rest of the set.
Props
4 props, straight from the manifest.
| Prop | Type | Default | Bindings | Description |
|---|---|---|---|---|
Appearance
States
editing
The source view is showing: the body is swapped for the textarea and the toggle reads as pressed.
inert-link
A link whose URL the renderer refused — a javascript: href, say. It keeps its text but loses its href, and reads dimmed and unclickable rather than lying about being a link.
Anatomy
The named parts that make up the component, with their selectors.
body
Where the rendered markdown lands. Every rule is scoped inside it and styles element types rather than named parts, since the content's structure is the author's, not ours — so nothing here reaches a consumer's own headings.
heading
Document headings, on the type scale; h1 and h2 carry a rule beneath them.
code
Inline code and fenced blocks, borrowing the Code component's --code-fg / --code-bg rather than deriving a second opinion about what code looks like.
table
A GFM table: striped rows, a filled header, and its own horizontal scroll so a wide table never pushes the document sideways.
quote
A blockquote, marked by a leading edge and dimmed a step off the body text.
editor
The source textarea shown while editing, in the mono face on the field surface.
toggle
The edit/view switch. Chrome the component invents, so it is a real node in the fragment fill: a mod can reword it, make it an icon, or move it, and the element keeps working.
Tokens & coverage
What the component consumes, checked live against what the algorithm produces.
Live coverage check against the xtyle-default register
(derive(xtyleDefault, { anchors }) →
coverComponent(manifest, register)). Every token this component
consumes must be a key the algorithm produces.
--accent
--accent-text
--bg-1
--bg-2
--border-normal
--border-thin
--code-bg
--code-fg
--duration-fast
--ease-standard
--fg-0
--fg-1
--fg-2
--field-bg
--field-border
--font-mono
--font-sans
--leading-normal
--leading-tight
--neutral-bg
--neutral-text
--radius-md
--radius-sm
--space-1
--space-2
--space-3
--space-4
--space-5
--space-6
--text-2xl
--text-body
--text-lg
--text-sm
--text-xl
--text-xs
--weight-bold
--weight-semibold
Slots
The markdown as text content (html/svelte). For Astro, pass it via the source prop instead.
Accessibility
Code
A document
The block render: headings, emphasis, links and lists, themed from the register.
<xtyle-markdown source="## Release notes
The **tooltip** now tracks its trigger. See [the changelog](/changelog).
- fixed placement under scroll
- `Escape` dismisses a hover-raised hint"></xtyle-markdown>
<script lang="ts">
import { Markdown } from "@xtyle/svelte";
const notes = `## Release notes
The **tooltip** now tracks its trigger. See [the changelog](/changelog).`;
</script>
<Markdown source={notes} />
---
import Markdown from "@xtyle/astro/Markdown.astro";
const notes = `## Release notes
The **tooltip** now tracks its trigger. See [the changelog](/changelog).`;
---
<Markdown source={notes} />
An inline label
inline renders emphasis without blocks and without a paragraph wrapper, so a generated tab title or chip inherits its surroundings. Block syntax stays literal — a leading # is text, not a heading.
<!-- a label, not a document: emphasis renders, blocks stay literal -->
<xtyle-markdown inline source="Fix **tooltip** in `AnchorTracker`"></xtyle-markdown>
<script lang="ts">
import { Markdown } from "@xtyle/svelte";
// a tab title an LLM formatted, dropped straight into a tab strip
export let title = "Fix **tooltip** in `AnchorTracker`";
</script>
<Markdown inline source={title} />
---
import Markdown from "@xtyle/astro/Markdown.astro";
---
<Markdown inline source="Fix **tooltip** in `AnchorTracker`" />
Tables and task lists
GFM is on: tables, task lists, strikethrough and autolinks all render. A wide table scrolls inside its own box.
<xtyle-markdown source="| component | state |
| --- | --- |
| tooltip | fixed |
| swatch | fixed |
- [x] track the anchor
- [ ] name the version"></xtyle-markdown>
<script lang="ts">
import { Markdown } from "@xtyle/svelte";
</script>
<Markdown source={`| component | state |
| --- | --- |
| tooltip | fixed |
- [x] track the anchor
- [ ] name the version`} />
---
import Markdown from "@xtyle/astro/Markdown.astro";
---
<Markdown source={`| component | state |
| --- | --- |
| tooltip | fixed |
- [x] track the anchor`} />
An editable source view
editable adds a toggle between the render and its markdown source, emitting input with the source as it's typed.
<xtyle-markdown editable source="# Draft
Switch to the source and edit it."></xtyle-markdown>
<script lang="ts">
import { Markdown } from "@xtyle/svelte";
let draft = "# Draft\n\nSwitch to the source and edit it.";
</script>
<Markdown editable source={draft} on:input={(e) => (draft = e.detail.source)} />
---
import Markdown from "@xtyle/astro/Markdown.astro";
---
<Markdown editable source={"# Draft\n\nSwitch to the source and edit it."} />