Skip to content

Instantly share code, notes, and snippets.

@donpark
Last active March 16, 2021 10:23
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save donpark/b61f7a989626988f5fd01871d13ff9ea to your computer and use it in GitHub Desktop.
Save donpark/b61f7a989626988f5fd01871d13ff9ea to your computer and use it in GitHub Desktop.
Rough first cut of JSON Feed types and interfaces
/** JSON Feed TypeScript Declaration
* Spec Version: 1
*/
declare namespace JSONFeed {
const MIME_TYPE = 'application/json'
type DATEstring = RFC3339string
type IDstring = string
type HTMLstring = string
type MIMETYPEstring = string
type RFC3339string = string
type TAGstring = string
type TEXTstring = string
type TITLEstring = string
type URLstring = string
type VERSIONstring = string
type HubType = 'rssCloud' | 'WebSub' | string
/**
* Publishers can use custom objects in JSON Feeds.
* Names must start with an _ character followed by a letter.
* Custom objects can appear anywhere in a feed.
*
* Feed readers that do not understand a given custom object must ignore it.
*
* This interface allows custom properties to be retrieved or set using TypeScript.
* and is not part of the spec.
*/
interface Extensible {
[key: string]: any // custom property key must start with underline
}
/**
* The JSON Feed format is a pragmatic syndication format,
* like RSS and Atom, but with one big difference: it’s JSON instead of XML.
*/
interface Feed extends Extensible {
/**
* (required, string) is the URL of the version of the format the feed uses.
* This should appear at the very top, though we recognize that not all JSON generators
* allow for ordering.
*/
version: VERSIONstring
/**
* (required, string) is the name of the feed, which will often correspond to the name
* of the website (blog, for instance), though not necessarily.
*/
title: TITLEstring
/**
* (optional, string) is a description of the purpose of the feed. This is for the use
* of people looking at the raw JSON, and should be ignored by feed readers.
*/
user_comment?: string
/**
* (optional, string) is the URL of an image for the feed suitable to be used in a timeline,
* much the way an avatar might be used. It should be square and relatively large — such as
* 512 x 512 — so that it can be scaled-down and so that it can look good on retina displays.
* It should use transparency where appropriate, since it may be rendered on a non-white background.
*/
icon?: URLstring
/**
* (optional, string) is the URL of an image for the feed suitable to be used in a source list.
* It should be square and relatively small, but not smaller than 64 x 64
* (so that it can look good on retina displays).
* As with icon, this image should use transparency where appropriate, since it may be rendered
* on a non-white background.
*/
favicon?: URLstring
/**
* (optional but strongly recommended, string) is the URL of the resource that the feed describes.
* This resource may or may not actually be a “home” page, but it should be an HTML page.
* If a feed is published on the public web, this should be considered as required.
* But it may not make sense in the case of a file created on a desktop computer,
* when that file is not shared or is shared only privately.
*/
home_page_url?: URLstring
/**
* (optional but strongly recommended, string) is the URL of the feed, and serves as the
* unique identifier for the feed. As with home_page_url, this should be considered required
* for feeds on the public web.
*/
feed_url?: URLstring
/**
* (optional, string) is the URL of a feed that provides the next n items,
* where n is determined by the publisher.
* This allows for pagination, but with the expectation that reader software is not required
* to use it and probably won’t use it very often.
* next_url must not be the same as feed_url, and it must not be the same as a previous
* next_url (to avoid infinite loops).
*/
next_url?: URLstring
/**
* (optional, boolean) says whether or not the feed is finished —
* that is, whether or not it will ever update again.
* A feed for a temporary event, such as an instance of the Olympics, could expire.
* If the value is true, then it’s expired. Any other value, or the absence of expired,
* means the feed may continue to update.
*/
expired?: boolean
/**
* (optional, object) specifies the feed author.
*/
author?: Author
/**
* (very optional) array of objects
*/
hubs?: Hub[]
/**
* is an array of objects, and is required.
*/
items: Item[]
}
interface Item extends Extensible {
/**
* (required, string) is unique for that item for that feed over time.
* If an item is ever updated, the id should be unchanged.
* New items should never use a previously-used id.
* If an id is presented as a number or other type, a JSON Feed reader must coerce it to a string.
* Ideally, the id is the full URL of the resource described by the item,
* since URLs make great unique identifiers.
*/
id: IDstring
/**
* (optional, string) is plain text. Microblog items in particular may omit titles.
*/
title?: TITLEstring
/**
* (optional, string) is a plain text sentence or two describing the item.
* This might be presented in a timeline, for instance,
* where a detail view would display all of content_html or content_text.
*/
summary?: TEXTstring
/**
* (optional, string) is the URL of the resource described by the item. It’s the permalink.
* This may be the same as the id — but should be present regardless.
*/
url?: URLstring
/**
* (very optional, string) is the URL of a page elsewhere.
* This is especially useful for linkblogs.
* If url links to where you’re talking about a thing,
* then external_url links to the thing you’re talking about.
*/
external_url?: URLstring
/**
* (optional, string) is the URL of the main image for the item.
* This image may also appear in the content_html —
* if so, it’s a hint to the feed reader that this is the main, featured image.
* Feed readers may use the image as a preview
* (probably resized as a thumbnail and placed in a timeline).
*/
image?: URLstring
/**
* (optional, string) is the URL of an image to use as a banner.
* Some blogging systems (such as Medium) display a different banner image chosen to
* go with each post, but that image wouldn’t otherwise appear in the content_html.
* A feed reader with a detail view may choose to show this banner image at the top of the detail view,
* possibly with the title overlaid.
*/
banner_image?: URLstring
/**
* (optional if content_text exists, required otherwise)
* This is the HTML of the item.
* Important: This is the only place HTML is allowed in this format
*/
content_html?: HTMLstring
/**
* (optional if content_html exists, required otherwise)
* This is the plain text of the item.
*/
content_text?: TEXTstring
/**
* (optional, string) specifies the date in RFC 3339 format. (Example: 2010-02-07T14:04:00-05:00.)
*/
date_published?: DATEstring
/**
* (optional, string) specifies the modification date in RFC 3339 format.
*/
date_modified?: DATEstring
/**
* (optional, object) has the same structure as the top-level author.
* If not specified in an item, then the top-level author, if present, is the author of the item.
*/
author?: Author
/**
* (optional, array of strings) can have any plain text values you want.
* Tags tend to be just one word, but they may be anything.
* Note: they are not the equivalent of Twitter hashtags.
* Some blogging systems and other feed formats call these categories.
*/
tags?: TAGstring[]
/**
* (optional, array) lists related resources.
* Podcasts, for instance, would include an attachment that’s an audio or video file.
*/
attachments?: Attachment[]
}
interface Attachment extends Extensible {
/**
* (optional, string) is a name for the attachment.
* Important: if there are multiple attachments,
* and two or more have the exact same title (when title is present),
* then they are considered as alternate representations of the same thing.
* In this way a podcaster, for instance, might provide an audio recording in different formats.
*/
title?: TITLEstring
/**
* (required, string) specifies the type of the attachment, such as "audio/mpeg."
*/
mime_type: MIMETYPEstring
/**
* (required, string) specifies the location of the attachment.
*/
url: URLstring
/**
* (optional, number) specifies how large the file is.
*/
size_in_bytes?: number
/**
* (optional, number) specifies how long it takes to listen to or watch, when played at normal speed.
*/
duration_in_seconds?: number
}
interface Author extends Extensible {
/**
* (optional, string) is the author’s name.
*/
name?: string
/**
* (optional, string) is the URL of a site owned by the author.
* It could be a blog, micro-blog, Twitter account, and so on.
* Ideally the linked-to page provides a way to contact the author, but that’s not required.
* The URL could be a mailto: link, though we suspect that will be rare.
*/
url?: URLstring
/**
* (optional, string) is the URL for an image for the author.
* As with icon, it should be square and relatively large — such as 512 x 512 — and
* should use transparency where appropriate, since it may be rendered on a non-white background.
*/
avatar?: URLstring
}
/**
* describes endpoints that can be used to subscribe to
* real-time notifications from the publisher of this feed.
* Each object has a type and url, both of which are required.
* See the section “Subscribing to Real-time Notifications” below for details.
*/
interface Hub extends Extensible {
/**
* (required) string representing type of endpoint
*/
type: HubType
/**
* (required) endpoint URL
*/
url: URLstring
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment