Open Source · MIT · A Lossless Group package

Lossless Flavored Markdown

MDX power without MDX's opinions.

A polyglot extended-markdown pipeline — authors keep authoring, LFM normalizes the variations. Identify the syntaxes worth supporting (and the variations on intent inside each one), then parse and render beautifully. Ready for any framework, no lock-in to someone else's flavor.

8+Plugins
1Canonical AST
v0.3Latest Release
  • Directives
  • Callouts
  • Citations
  • Wikilinks
  • Bare-link Embeds
  • OG Enrichment
  • GFM Tables
install
$ pnpm add jsr:@lossless-group/lfm
STC — Syntax · Trigger · Component

Three steps from your markdown to your renderer.

LFM owns the trigger → tokenize → normalize path. Your framework owns rendering. The shape between them is one canonical AST.

01

Declare Syntax

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

02

Parse Trigger

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

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, end to end.

A bare URL on its own line becomes the embedded player. The same content can also be authored as a directive — both end up as the same node, rendered by the same component.

Syntax

Bare URL

https://youtu.be/jCe2wg1ulus

Directive

:::youtube-share[https://youtu.be/jCe2wg1ulus]
Parse

remark-link-preview.ts

The plugin recognizes the trigger and emits one canonical AST node — regardless of whether it came from a bare URL or a directive.

Component

YoutubeShareEmbed--Base.astro

Your renderer maps the AST node to a component (or a chain of them). Authors keep authoring; the renderer takes over.

What's in the box

Triggers, normalizers, and build-time enrichment.

All wired together by remarkLfm; cherry-pick what you need.

Polyglot pipeline

Stable

Many authoring conventions, one canonical AST.

Obsidian callouts, remark-directive blocks, and (eventually) Markdoc all produce the same MDAST node. Adding a new authoring syntax means a new normalizer plugin — no consumer changes, no renderer rewrites.

CoreASTNormalization

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 are also the substrate for the bare-link auto-unfurl detector.

GFMTables

remark-directive

Stable

Block, leaf, and inline directives — :::box, ::badge, :abbr — for naming regions of content.

Directive nodes are the lingua franca your renderer dispatches on. LFM normalizers emit directive nodes from many input syntaxes so one downstream component handles them all.

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.

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.

CitationsFootnotes

link-preview · og-fetcher

Stable

Build-time OpenGraph enrichment. Cards and rollups carry full metadata before the page ships.

remarkOgFetcher walks the tree, finds external links and :::link-preview directives, fetches OG metadata, and annotates the AST with LinkPreviewData. Configurable cache, separate TTLs for hits and failures.

OpenGraphBuild-timeCards

Bare-link provider catalog

Beta

A URL on its own line becomes the embedded player or rich card the author meant.

Strict matching: the paragraph must have exactly one child that is a link whose visible text equals its URL. v0.2.2 ships YouTube video / shorts / playlist and Vimeo as stable, with Loom, Spotify, and SoundCloud planned.

EmbedsYouTubeVimeo

remarkLosslessWikilinks

New in 0.3.0

Site-resolved Obsidian wikilinks for the LFM pipeline.

Turns [[Page|Display]] into proper hyperlinks with one design constraint: LFM never decides where a wikilink points. Sites supply a resolver function; LFM owns the syntax. Internal vs external routing, anchors, alias displays, and graceful plain-text fallback for unresolved links.

WikilinksObsidianResolver
Recent

What shipped lately.

May 8, 2026 0.3.0

remarkLosslessWikilinks ships in 0.3.0

Site-resolved Obsidian wikilinks for the LFM pipeline. LFM owns the syntax; sites supply the resolver. Internal vs external routing, anchors, alias displays, and graceful plain-text fallback — all behind one new option on parseMarkdown.

May 8, 2026 callouts

New callout features in @lossless-group/lfm

Multi-line callouts no longer silently fall through. Hyphenated type names like [!llm-response] now parse. Obsidian foldable [!type]- syntax is supported. The pipeline doc codifies that callout bodies must support every LFM feature — directives, citations, embeds, even nested callouts.

May 7, 2026 splash

Initial pass at a Lossless Flavored Markdown splash page

LFM gets its own GitHub Pages landing page — three-stage STC diagram, asymmetric hero, manuscript-flavored type, and a package boundary that will not let the splash bleed into JSR.

Read the full changelog