-
Notifications
You must be signed in to change notification settings - Fork 0
API Reference
The public surface re-exported from src/index.ts. The two classes you will use most are RSSFeed and HTMLMapper.
← Back to Home · Related: RSS Feeds · HTML Mapping · Component Types
For any string input and any params/root config, new RSSFeed(...),
validate(), and build() never throw — problems are reported through
errors/warnings instead:
-
Malformed XML — the constructor wraps
XMLParser.parsein atry/catch; a parse failure becomes anXML_PARSE_ERRORissue on bothfeed.errorsandfeed.rss.errors, andthis.datais left empty sovalidate()/build()still run to completion. -
Malformed URLs reachable from feed content — the channel
<link>, iframe embeds (YouTube/TikTok/Vimeo/Dailymotion/Twitter/Infogram/Apple Podcasts), anchor-based embeds, relativemedia:contentURL resolution, and the item-<link>-based resolution of relative image/gallery/video/audio URLs inside a built item'scomponents(resolveComponentMediaUrls) are all guarded withURL.canParsebefore construction; an unparseable URL becomes a warning, is left untouched, or becomes an error-annotated component instead of throwing. -
Invalid
params/root— never silently dropped. The constructor always stores what it's given;build()is the one place that validates them (RSSFeed.validateParams) and reports the result. -
Network I/O —
getRecipeFromUrl/getHtmlContent(see below) still reject on a genuine network failure or non-okresponse — that's aPromiserejection, not a thrown exception fromRSSFeeditself, and is the one place this library performs I/O you didn't explicitly ask for.
Verified by a seeded property-test suite
(src/rss/__tests__/rss-feed.fuzz.test.ts) driving the constructor →
validate() → build() lifecycle over hand-picked edge cases and random
XML/params input. See ADR-0007
(docs/adr/0007-throw-surface-inventory.md) for the full throw-surface
inventory and how each site was fixed.
errors/warnings throughout this library — RSS, Channel, Item,
Enclosure, MediaGroup, MediaContent, RSSFeed.errors,
RSSFeed.validateParams()'s return value, and every Component's
errors/warnings — are arrays of:
interface FeedIssue {
code: FeedIssueCode; // stable string union, exported from '@canvasflow/feed'
severity: 'error' | 'warning';
message: string; // human-readable, for logging/display
path?: string; // e.g. "cf:thumbnail.url", the tag/field the issue is about
}FeedIssueCode is a large, stable, switchable union (XML_PARSE_ERROR,
MISSING_REQUIRED_TAG, INVALID_PARAMS, MISSING_IMAGE_SRC,
INVALID_YOUTUBE_URL, ... — see src/feed-issue.ts for the full list).
Branch on .code for programmatic handling; use .message for display.
See the CHANGELOG's migration guide for the string[] → FeedIssue[]
transition.
-
validate()populateserrors/warningsagainst the tag allow-lists intag.ts. It does not mutate the parsed input (nodelete), and it resets its own accumulators at the start, so calling it more than once is idempotent. -
build()callsvalidate()automatically if it hasn't run yet, then constructs the typedRSS. Ifrss.errorsis non-empty after validation,build()returns early with thatRSS(no items are built). - Both are
asynceven though today's implementation is fully synchronous internally — see ADR-0008 (docs/adr/0008-keep-validate-build-async.md) for why the sync conversion is deferred rather than done now.
import { RSSFeed } from '@canvasflow/feed';| Member | Signature | Description |
|---|---|---|
| constructor | new RSSFeed(content: string, params?: Params) |
Parse the feed XML; optional Params configures HTML conversion. |
content |
string |
The original XML passed in. |
rss |
RSS |
The typed result, populated by validate() / build(). |
errors |
FeedIssue[] |
Top-level errors collected during validation. |
root (setter) |
set root(mapping?: Mapping) |
Scope content extraction to a sub-element before conversion. |
validate() |
Promise<void> |
Validate required tags; fill errors/warnings. |
build() |
Promise<RSS> |
Build the typed RSS; attach a components array to each item. |
| Member | Signature | Description |
|---|---|---|
validateParams |
(params?: Params, root?: Mapping) => FeedIssue[] |
Validate params/root against the Zod schemas; returns structured issues (code is 'INVALID_PARAMS' | 'INVALID_ROOT_MAPPING'). |
toJSON |
(rss: RSS) => unknown |
Serialize then re-parse an RSS (round-trips errors via toString). |
toString |
(rss: RSS) => string |
JSON string of an RSS (Error values are flattened). |
getRecipeFromUrl |
(url: string) => Promise<Recipe | null> |
Deprecated thin wrapper around getRecipeFromUrl from ../rss/recipe (see below). |
getHtmlContent |
(url: string, headers?: HeadersInit) => Promise<string> |
Deprecated thin wrapper around getHtml from ../utils/http (see below) — kept as an identical-behaviour alias. |
getRecipeFromUrl/getHtmlContentperform network I/O (fetch); everything else is pure.
Extracted out of RSSFeed (Section 3, "Network I/O extraction") so the
XML-parsing library doesn't hide unbounded fetch calls behind its public
API. All are exported from @canvasflow/feed directly:
import {
fetchUrl,
getHtml,
getHtmlContent,
getJson,
nodeHttpsFetch,
getRecipeFromUrl,
} from '@canvasflow/feed';| Function | Signature | Description |
|---|---|---|
fetchUrl(url, options?) |
(url: string, options?: FetchOptions) => Promise<string> |
Fetch url as text — status check + body cap only, no Content-Type opinion. |
getHtml(url, options?) |
(url: string, options?: FetchOptions) => Promise<string> |
fetchUrl plus a Content-Type: text/html check; rejects a 2xx response whose body isn't actually HTML. |
getHtmlContent(url, options?) |
same as getHtml
|
Deprecated alias for getHtml, kept for backward compatibility. |
getJson<T>(url, options?) |
(url: string, options?: FetchOptions) => Promise<T> |
fetchUrl plus a Content-Type: application/json check, then JSON.parses the body. |
nodeHttpsFetch |
Node https-backed fetch-compatible implementation |
Injectable as options.fetch when the global fetch isn't suitable. |
getRecipeFromUrl(url, options?) |
(url: string, options?: FetchOptions) => Promise<Recipe | null> |
Fetch url and extract the first LD+JSON Recipe (top-level or nested in @graph); malformed JSON-LD blocks are skipped. |
FetchOptions: { fetch?: typeof fetch; headers?: HeadersInit; timeoutMs?: number /* default 10000 */; maxBytes?: number /* default 5MB */ }. The request is aborted via AbortSignal.timeout(timeoutMs); the response body is read through a size-capped stream. fetchUrl/getHtml/getJson share one internal request helper and only differ in what they do with the response afterward.
import { HTMLMapper } from '@canvasflow/feed';| Member | Signature | Description |
|---|---|---|
toComponents |
(html: string, params?: Params) => Component[] |
Convert an HTML string into components. |
getRootElement |
(html: string, mapping: Mapping) => string | null |
Serialize the first element matching mapping. |
splitParagraphImages |
(html: string, tag: string) => string |
Split elements of the given tag that contain <img> so each image becomes its own block. |
See HTML Mapping.
From the mapping module:
| Function | Purpose |
|---|---|
processTextLinks(html, link?) |
Rewrite relative/protocol-relative/unsafe links in text HTML. |
isValidMapping(value), isValidParams(value)
|
Boolean validation against the Zod schemas. |
validateParams(value) |
Parse-or-throw, returning a typed Params. |
These four are the only mapping.ts helpers re-exported from src/index.ts. mapping.ts and its sibling modules export a good deal more at the module level for use within src/ — reduceComponents, fromNode, getRootElement (the node-array version; HTMLMapper.getRootElement is the public string version), reduceEmptyTextNode/filterEmptyTextNode, mapLivePost, resolveMediaUrl/resolveComponentMediaUrls, isEmpty, and the textTags/textTagsSet/mappingTagsSet constants — but none of those are part of the published @canvasflow/feed package; they are internal implementation detail. See Architecture if you're reading the source rather than consuming the package.
The is* component guards (e.g. isImageComponent, isVideoComponent) and isValidTextRole are exported from the component module — see Component Types.
| Group | Types |
|---|---|
| Feed |
RSS, Channel, ChannelImage, Item, MutableItem, Thumbnail, Enclosure, Source, MediaContent, MediaGroup
|
| Errors |
FeedIssue, FeedIssueCode, FeedIssueSeverity — see "Error model" above |
| Config |
Params, Mapping, ComponentMapping, MatchType, Filter, TagFilter, ClassFilter, AttributeFilter, AttributeValueFilter, AttributePatternFilter
|
| Component mappings |
ContainerMapping, ColumnsMapping, LiveContainerMapping, RecipeMapping, CustomMapping, TextMapping, GalleryMapping, DividerMapping, SpacerMapping
|
| Components |
Component, ComponentType, TextType, ComponentLink, ImageSource, GalleryImage, and every *Component interface |
| Schema |
Recipe and related schema types (Thing, Person, Organization, NutritionInformation, …) |
Exact signatures are the source of truth — see
src/index.tsand the files it re-exports. Note that none of the Zod schema objects (ComponentSchema,ImageComponentSchema,MappingSchema,ParamsSchema,RecipeSchema, etc.) are re-exported — they live incomponent.ts/mapping.schema.ts/schema/recipe-schema.tsfor internal validation only. UseisValidParams/isValidMapping/validateParams(above) or theis*Componenttype guards instead of importing a schema directly.
Start here
Reference
Operations