Canvasflow utility for processing feeds.
A TypeScript library that parses RSS/Atom feeds and transforms their HTML
content into structured Canvasflow components. It validates feeds against
Canvasflow's required-tag rules and converts each item's content:encoded HTML
into a typed components array ready to be consumed by Canvasflow.
The package is published as an ESM module (with TypeScript declarations) to GitHub Packages.
📖 Full documentation lives in the project wiki. This README is a quick introduction; the wiki covers the architecture, the mapping model, and the complete API.
- Parse and validate RSS/Atom feeds (
fast-xml-parserunder the hood). - Build a strongly-typed
RSSobject from raw feed XML. - Convert HTML into Canvasflow
Component[]— images, galleries, video, audio, embeds (Twitter/X, Instagram, YouTube, TikTok, Vimeo, Dailymotion, Infogram, Apple Podcasts), recipes, HTML tables, columns, containers, live posts, and more. - Configurable HTML → component mapping via
Params/Mapping. - Canvasflow
cf:namespace extensions (cf:hasAffiliateLinks,cf:isSponsored,cf:isPaid,cf:liveCoverageState,cf:thumbnail). - Pure and side-effect-free: malformed input is reported through
errors/warningsrather than thrown.
- Node.js
>=20.19.2 - Access to the
@canvasflowscope on GitHub Packages (for installation).
This package lives on GitHub Packages, so point the @canvasflow scope at the
GitHub registry. Add an .npmrc to your project:
@canvasflow:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}Then install:
npm install @canvasflow/feedimport { RSSFeed } from '@canvasflow/feed';
const xml = await fetch('https://example.com/feed.xml').then((r) => r.text());
const feed = new RSSFeed(xml);
// Validate the feed — populates `errors`/`warnings` on the RSS / channel / items.
await feed.validate();
// Build a typed RSS object. Each item's `content:encoded` HTML is converted
// into a `components` array automatically.
const rss = await feed.build();
for (const item of rss.channel.items) {
console.log(item.title, item.components);
}import { HTMLMapper } from '@canvasflow/feed';
const components = HTMLMapper.toComponents(
'<h1>Title</h1><p>Hello <a href="https://canvasflow.io">world</a></p>'
);By default <h1> → headline, <h2> → title, <p> → body, and so on; a
text element's role attribute overrides the default (e.g. <p role="crosshead">).
Detection of images, embeds, tables, and containers — and how to configure it —
is documented on the HTML Mapping
and Custom Mappings wiki pages.
Two cooperating pipelines drive the library:
- Feed pipeline (
src/rss/) —RSSFeedwrapsfast-xml-parser, validates required tags, and builds the typedRSSobject. - HTML pipeline (
src/component/) —HTMLMapper.toComponents()pre-processes the HTML, parses it withhimalaya, and reduces the node tree intoComponent[]through the detection engine incomponent/mapping/.
build() runs each item's content:encoded through the HTML pipeline, so the two
connect automatically.
src/
├── index.ts # Public entry point (re-exports the API)
├── rss/ # Feed pipeline: RSSFeed, RSS/ParsedXml types, Tag allow-lists, Attributes
└── component/
├── Component.ts # Component types and is* type guards
├── html/ # HTMLMapper — HTML → Component[] entry point
├── mapping/ # Detection engine + per-family converters, Zod schemas, constants, utils
├── node/ # himalaya AST node helpers
└── schema/ # Zod schemas for recipe (JSON-LD) extraction
See Architecture and Project Structure for the full picture.
The project wiki is the source of in-depth documentation:
| Page | What it covers |
|---|---|
| Getting Started | Install, quick usage, and contributor commands. |
| Architecture | The two pipelines and the detection engine. |
| API Reference | RSSFeed / HTMLMapper members, helpers, and exported types. |
| RSS Feeds | validate()/build(), supported tags, and namespaces. |
| HTML Mapping | The conversion pipeline and default rules. |
| Custom Mappings | The Params/Mapping model: filters, match modes, and component mappings. |
| Component Types | The component union, interfaces, and type guards. |
The wiki is generated from the Markdown in
docs/wiki/and synced on release.
This project uses vite-plus (vp)
for development, building, testing, linting, and formatting.
npm install # install dependencies
npm run build # compile + bundle into dist/ (ESM + .d.mts)
npm test # run the full test suite once
npm run lint # lint the source
npm run coverage # run tests with a coverage report (v8, threshold-gated)Run a single test file with npx vitest run src/rss/RSSFeed.test.ts. The full
script list, test tags, and coverage thresholds are documented on the
Testing wiki page.
Commits follow Conventional Commits
(enforced by commitlint; npm run commit opens the commitizen prompt). See the
Contributing page.
Publishing is automated by the 🚀 Publish GitHub Actions workflow
(.github/workflows/publish.yml): on a v* tag it runs the test suite, reports
coverage, publishes the package to GitHub Packages, and syncs the wiki. Details
are on the Build & Publishing
page.
Proprietary — © Canvasflow.