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 48 {b Examples:} 49 {[ 50 (* Simple blog post *) 51 let item = Item.create 52 ~id:"https://example.com/posts/42" 53 ~content:(`Html "<p>Hello, world!</p>") 54 ~title:"My First Post" 55 ~url:"https://example.com/posts/42" () 56 57 (* Microblog entry with plain text *) 58 let item = Item.create 59 ~id:"https://example.com/micro/123" 60 ~content:(`Text "Just posted a new photo!") 61 ~date_published:(Ptime.of_float_s (Unix.time ()) |> Option.get) () 62 63 (* Article with both HTML and plain text *) 64 let item = Item.create 65 ~id:"https://example.com/article/99" 66 ~content:(`Both ("<p>Rich content</p>", "Plain version")) 67 ~title:"Article Title" 68 ~tags:["ocaml"; "programming"] () 69 70 (* Podcast episode with attachment *) 71 let attachment = Attachment.create 72 ~url:"https://example.com/ep1.mp3" 73 ~mime_type:"audio/mpeg" 74 ~duration_in_seconds:1800 () in 75 let item = Item.create 76 ~id:"https://example.com/podcast/1" 77 ~content:(`Html "<p>Episode description</p>") 78 ~title:"Episode 1" 79 ~attachments:[attachment] () 80 ]} *) 81val create : 82 id:string -> 83 content:content -> 84 ?url:string -> 85 ?external_url:string -> 86 ?title:string -> 87 ?summary:string -> 88 ?image:string -> 89 ?banner_image:string -> 90 ?date_published:Ptime.t -> 91 ?date_modified:Ptime.t -> 92 ?authors:Author.t list -> 93 ?tags:string list -> 94 ?language:string -> 95 ?attachments:Attachment.t list -> 96 unit -> 97 t 98 99 100(** {1 Accessors} *) 101 102(** [id t] returns the item's unique identifier. *) 103val id : t -> string 104 105(** [content t] returns the item's content. *) 106val content : t -> content 107 108(** [url t] returns the item's permalink URL, if set. *) 109val url : t -> string option 110 111(** [external_url t] returns the external resource URL, if set. *) 112val external_url : t -> string option 113 114(** [title t] returns the item's title, if set. *) 115val title : t -> string option 116 117(** [summary t] returns the item's summary, if set. *) 118val summary : t -> string option 119 120(** [image t] returns the item's featured image URL, if set. *) 121val image : t -> string option 122 123(** [banner_image t] returns the item's banner image URL, if set. *) 124val banner_image : t -> string option 125 126(** [date_published t] returns the item's publication date, if set. *) 127val date_published : t -> Ptime.t option 128 129(** [date_modified t] returns the item's last modification date, if set. *) 130val date_modified : t -> Ptime.t option 131 132(** [authors t] returns the item's authors, if set. *) 133val authors : t -> Author.t list option 134 135(** [tags t] returns the item's tags, if set. *) 136val tags : t -> string list option 137 138(** [language t] returns the item's language code, if set. *) 139val language : t -> string option 140 141(** [attachments t] returns the item's attachments, if set. *) 142val attachments : t -> Attachment.t list option 143 144 145(** {1 Content Helpers} *) 146 147(** [content_html t] extracts HTML content from the item. 148 149 Returns [Some html] if the item has HTML content (either [Html] or [Both]), 150 [None] otherwise. *) 151val content_html : t -> string option 152 153(** [content_text t] extracts plain text content from the item. 154 155 Returns [Some text] if the item has plain text content (either [Text] or [Both]), 156 [None] otherwise. *) 157val content_text : t -> string option 158 159 160(** {1 Comparison} *) 161 162(** [equal a b] tests equality between two items. 163 164 Items are considered equal if they have the same ID. *) 165val equal : t -> t -> bool 166 167(** [compare a b] compares two items by their publication dates. 168 169 Items without publication dates are considered older than items with dates. 170 Useful for sorting items chronologically. *) 171val compare : t -> t -> int 172 173 174(** {1 Pretty Printing} *) 175 176(** [pp ppf t] pretty prints an item to the formatter. 177 178 The output is human-readable and suitable for debugging. 179 180 {b Example output:} 181 {v [2024-11-03] My First Post (https://example.com/posts/42) v} *) 182val pp : Format.formatter -> t -> unit 183 184(** [pp_content ppf content] pretty prints content to the formatter. 185 186 {b Example output:} 187 {v HTML (123 chars) v} 188 {v Text (56 chars) v} 189 {v Both (HTML: 123 chars, Text: 56 chars) v} *) 190val pp_content : Format.formatter -> content -> unit