OCaml library for JSONfeed parsing and creation
1(** Feed items in a JSON Feed. 2 3 An item represents a single entry in a feed, such as a blog post, podcast episode, 4 or microblog entry. Each item must have a unique identifier and content. 5 6 @see <https://www.jsonfeed.org/version/1.1/> JSON Feed Specification *) 7 8 9(** The type representing a feed item. *) 10type t 11 12(** Content representation for an item. 13 14 The JSON Feed specification requires that each item has at least one 15 form of content. This type enforces that requirement at compile time. 16 17 - [`Html s]: Item has HTML content only 18 - [`Text s]: Item has plain text content only 19 - [`Both (html, text)]: Item has both HTML and plain text versions *) 20type content = 21 [ `Html of string 22 | `Text of string 23 | `Both of string * string 24 ] 25 26 27(** {1 Construction} *) 28 29(** [create ~id ~content ?url ?external_url ?title ?summary ?image ?banner_image 30 ?date_published ?date_modified ?authors ?tags ?language ?attachments ()] 31 creates a feed item. 32 33 @param id Unique identifier for the item (required). Should be a full URL if possible. 34 @param content The item's content in HTML and/or plain text (required) 35 @param url Permalink to the item 36 @param external_url URL of an external resource (useful for linkblogs) 37 @param title Plain text title of the item 38 @param summary Plain text summary/excerpt of the item 39 @param image URL of the main featured image for the item 40 @param banner_image URL of a banner image for the item 41 @param date_published Publication date/time (RFC 3339 format) 42 @param date_modified Last modification date/time (RFC 3339 format) 43 @param authors Item-specific authors (overrides feed-level authors) 44 @param tags Plain text tags/categories for the item 45 @param language Primary language of the item (RFC 5646 format, e.g. ["en-US"]) 46 @param attachments Related resources like audio files or downloads 47 @param references References to cited sources (extension) 48 49 {b Examples:} 50 {[ 51 (* Simple blog post *) 52 let item = Item.create 53 ~id:"https://example.com/posts/42" 54 ~content:(`Html "<p>Hello, world!</p>") 55 ~title:"My First Post" 56 ~url:"https://example.com/posts/42" () 57 58 (* Microblog entry with plain text *) 59 let item = Item.create 60 ~id:"https://example.com/micro/123" 61 ~content:(`Text "Just posted a new photo!") 62 ~date_published:(Ptime.of_float_s (Unix.time ()) |> Option.get) () 63 64 (* Article with both HTML and plain text *) 65 let item = Item.create 66 ~id:"https://example.com/article/99" 67 ~content:(`Both ("<p>Rich content</p>", "Plain version")) 68 ~title:"Article Title" 69 ~tags:["ocaml"; "programming"] () 70 71 (* Podcast episode with attachment *) 72 let attachment = Attachment.create 73 ~url:"https://example.com/ep1.mp3" 74 ~mime_type:"audio/mpeg" 75 ~duration_in_seconds:1800 () in 76 let item = Item.create 77 ~id:"https://example.com/podcast/1" 78 ~content:(`Html "<p>Episode description</p>") 79 ~title:"Episode 1" 80 ~attachments:[attachment] () 81 82 (* Article with references *) 83 let reference = Reference.create 84 ~url:"https://doi.org/10.5281/zenodo.16755947" 85 ~doi:"10.5281/zenodo.16755947" 86 ~cito:[`CitesAsRecommendedReading; `UsesMethodIn] () in 87 let item = Item.create 88 ~id:"https://doi.org/10.59350/krw9n-dv417" 89 ~content:(`Html "<p>Research article content</p>") 90 ~title:"One Million IUPAC names #4: a lot is happening" 91 ~url:"https://chem-bla-ics.linkedchemistry.info/2025/08/09/one-million-iupac-names-4.html" 92 ~references:[reference] () 93 ]} *) 94val create : 95 id:string -> 96 content:content -> 97 ?url:string -> 98 ?external_url:string -> 99 ?title:string -> 100 ?summary:string -> 101 ?image:string -> 102 ?banner_image:string -> 103 ?date_published:Ptime.t -> 104 ?date_modified:Ptime.t -> 105 ?authors:Author.t list -> 106 ?tags:string list -> 107 ?language:string -> 108 ?attachments:Attachment.t list -> 109 ?references:Reference.t list -> 110 unit -> 111 t 112 113 114(** {1 Accessors} *) 115 116(** [id t] returns the item's unique identifier. *) 117val id : t -> string 118 119(** [content t] returns the item's content. *) 120val content : t -> content 121 122(** [url t] returns the item's permalink URL, if set. *) 123val url : t -> string option 124 125(** [external_url t] returns the external resource URL, if set. *) 126val external_url : t -> string option 127 128(** [title t] returns the item's title, if set. *) 129val title : t -> string option 130 131(** [summary t] returns the item's summary, if set. *) 132val summary : t -> string option 133 134(** [image t] returns the item's featured image URL, if set. *) 135val image : t -> string option 136 137(** [banner_image t] returns the item's banner image URL, if set. *) 138val banner_image : t -> string option 139 140(** [date_published t] returns the item's publication date, if set. *) 141val date_published : t -> Ptime.t option 142 143(** [date_modified t] returns the item's last modification date, if set. *) 144val date_modified : t -> Ptime.t option 145 146(** [authors t] returns the item's authors, if set. *) 147val authors : t -> Author.t list option 148 149(** [tags t] returns the item's tags, if set. *) 150val tags : t -> string list option 151 152(** [language t] returns the item's language code, if set. *) 153val language : t -> string option 154 155(** [attachments t] returns the item's attachments, if set. *) 156val attachments : t -> Attachment.t list option 157 158(** [references t] returns the item's references, if set. *) 159val references : t -> Reference.t list option 160 161 162(** {1 Content Helpers} *) 163 164(** [content_html t] extracts HTML content from the item. 165 166 Returns [Some html] if the item has HTML content (either [Html] or [Both]), 167 [None] otherwise. *) 168val content_html : t -> string option 169 170(** [content_text t] extracts plain text content from the item. 171 172 Returns [Some text] if the item has plain text content (either [Text] or [Both]), 173 [None] otherwise. *) 174val content_text : t -> string option 175 176 177(** {1 Comparison} *) 178 179(** [equal a b] tests equality between two items. 180 181 Items are considered equal if they have the same ID. *) 182val equal : t -> t -> bool 183 184(** [compare a b] compares two items by their publication dates. 185 186 Items without publication dates are considered older than items with dates. 187 Useful for sorting items chronologically. *) 188val compare : t -> t -> int 189 190 191(** {1 Pretty Printing} *) 192 193(** [pp ppf t] pretty prints an item to the formatter. 194 195 The output is human-readable and suitable for debugging. 196 197 {b Example output:} 198 {v [2024-11-03] My First Post (https://example.com/posts/42) v} *) 199val pp : Format.formatter -> t -> unit 200 201(** [pp_content ppf content] pretty prints content to the formatter. 202 203 {b Example output:} 204 {v HTML (123 chars) v} 205 {v Text (56 chars) v} 206 {v Both (HTML: 123 chars, Text: 56 chars) v} *) 207val pp_content : Format.formatter -> content -> unit