A Lossless Group package · MIT

Lossless Flavored Markdown

MDX power without MDX's opinions. A polyglot extended-markdown pipeline — authors keep authoring, LFM normalizes the variations.

Let content creators be content creators. Identify the syntaxes worth supporting — and the variations on intent inside each one — then parse and render beautifully. LFM flexibly handles the rest.

$ pnpm add jsr:@lossless-group/lfm

STC — Syntax · Trigger · Component

Three steps from your markdown to your renderer.

  1. 01

    Declare Syntax

    Add the syntax you want rendered as a component, plus the params or props it should carry.

  2. 02

    Parse Trigger

    Wire the parser to recognize it — a peer remark plugin file that emits one canonical AST node.

  3. 03

    Component Pipeline

    Map the AST node to a component, or a chain of them. Authors keep authoring; the renderer takes over.

Live example

Video Embeds

live
Syntax

bare URL or directive

  • bare youtu.be/share={id}
  • directive :::youtube-share[https://youtu.be/jCe2wg1ulus?si=oplqTdsbv8sv2JfH]
Parse
src/plugins/remark-link-preview.ts
Component
components/YoutubeShareEmbed--Base.astro

Features

What's in the box

Triggers, normalizers, and build-time enrichment. All wired together by remarkLfm; cherry-pick what you need.

remark-gfm

Stable

Tables, task lists, strikethrough, autolinks — GitHub-flavored markdown enabled by default.

GFM is the floor, not the ceiling. Tables and task lists come for free; they’re also the substrate for the bare-link auto-unfurl detector — a paragraph with a single autolink child is the GFM signal that LFM uses to dispatch embeds.

GFMTables

remark-directive

Stable

Directive syntax for tagging blocks, leaves, and inline runs as components.

Block, leaf, and text directives — :::box, ::badge, :abbr — give authors a typographically lightweight way to name a region. LFM’s normalizers emit directive nodes from many input syntaxes, so directives are also the lingua franca your renderer dispatches on.

DirectivesSyntax

remark-callouts

Stable

Obsidian `> [!type] Title` blocks normalized into directive nodes — same downstream shape, two upstream syntaxes.

Authors writing in Obsidian get callout previews in their editor. Authors writing in plain markdown can use :::callout{type="warning"}. Both end up as the same :::callout directive node — your <Callout> component renders one shape regardless of which tool wrote the file.

CalloutsObsidian

remark-citations

Stable

Hex-code footnotes get renumbered to display indices and lifted into a structured citation dataset.

Author with stable hex IDs ([^a1b2c3]); LFM renumbers them to readable indices at parse time and assembles the full dataset on tree.data.citations.ordered — parsed dates, source domains, raw text — so a Sources component can render the canonical bibliography at the bottom of the article.

CitationsFootnotes

Bare-link provider catalog

Beta

A URL on its own line becomes the embedded player or rich card the author meant. The catalog ships in the package.

src/plugins/Bare-Link-Provider-Catalog.md is the canonical record of supported providers. v0.2.2 ships YouTube video / shorts / playlist and Vimeo as stable, with Loom, Spotify, and SoundCloud planned.

The matching rule is strict: the paragraph must have exactly one child that’s a link whose visible text equals its URL. So Check this out https://... mid-sentence stays a clickable link; only an isolated bare URL becomes an embed.

Recent

What shipped lately

Read the full changelog →