My agentic slop goes here. Not intended for anyone else!
at main 5.8 kB view raw
1(* 2 * Copyright (c) 2014, OCaml.org project 3 * Copyright (c) 2015 KC Sivaramakrishnan <sk826@cl.cam.ac.uk> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 *) 17 18(** Feed format conversion and export. *) 19 20module Atom : sig 21 (** Atom 1.0 format support. *) 22 23 val entry_of_post : Post.t -> Syndic.Atom.entry 24 (** [entry_of_post post] converts a post to an Atom entry. *) 25 26 val entries_of_posts : Post.t list -> Syndic.Atom.entry list 27 (** [entries_of_posts posts] converts posts to Atom entries. *) 28 29 val feed_of_entries : 30 title:string -> 31 ?id:string -> 32 ?authors:(string * string option) list -> 33 Syndic.Atom.entry list -> 34 Syndic.Atom.feed 35 (** [feed_of_entries ~title entries] creates an Atom feed from entries. 36 37 @param title The feed title 38 @param id Optional feed ID (default: "urn:river:merged") 39 @param authors Optional list of (name, email) tuples *) 40 41 val to_string : Syndic.Atom.feed -> string 42 (** [to_string feed] serializes an Atom feed to XML string. *) 43end 44 45module Rss2 : sig 46 (** RSS 2.0 format support. *) 47 48 val of_feed : Feed.t -> Syndic.Rss2.channel option 49 (** [of_feed feed] extracts RSS2 channel if the feed is RSS2 format. 50 51 Returns None if the feed is not RSS2. *) 52end 53 54module Jsonfeed : sig 55 (** JSON Feed 1.1 format support. *) 56 57 val item_of_post : Post.t -> Jsonfeed.Item.t 58 (** [item_of_post post] converts a post to a JSONFeed item. *) 59 60 val items_of_posts : Post.t list -> Jsonfeed.Item.t list 61 (** [items_of_posts posts] converts posts to JSONFeed items. *) 62 63 val feed_of_items : 64 title:string -> 65 ?home_page_url:string -> 66 ?feed_url:string -> 67 ?description:string -> 68 ?icon:string -> 69 ?favicon:string -> 70 Jsonfeed.Item.t list -> 71 Jsonfeed.t 72 (** [feed_of_items ~title items] creates a JSONFeed from items. 73 74 @param title The feed title (required) 75 @param home_page_url The URL of the website the feed represents 76 @param feed_url The URL of the feed itself 77 @param description A description of the feed 78 @param icon URL of an icon for the feed (512x512 recommended) 79 @param favicon URL of a favicon for the feed (64x64 recommended) *) 80 81 val feed_of_posts : 82 title:string -> 83 ?home_page_url:string -> 84 ?feed_url:string -> 85 ?description:string -> 86 ?icon:string -> 87 ?favicon:string -> 88 Post.t list -> 89 Jsonfeed.t 90 (** [feed_of_posts ~title posts] creates a JSONFeed from posts. 91 92 Convenience function that combines [items_of_posts] and [feed_of_items]. *) 93 94 val to_string : ?minify:bool -> Jsonfeed.t -> (string, string) result 95 (** [to_string ?minify feed] serializes a JSONFeed to JSON string. 96 97 @param minify If true, output compact JSON; if false, pretty-print (default: false) *) 98 99 val of_feed : Feed.t -> Jsonfeed.t option 100 (** [of_feed feed] extracts JSONFeed if the feed is JSONFeed format. 101 102 Returns None if the feed is not JSONFeed. *) 103end 104 105module Html : sig 106 (** HTML static site generation. *) 107 108 val format_date : Ptime.t -> string 109 (** [format_date date] formats a date in human-readable format (e.g., "November 23, 2025"). *) 110 111 val html_escape : string -> string 112 (** [html_escape s] escapes HTML special characters in string. *) 113 114 val full_content_from_html : string -> string 115 (** [full_content_from_html html_content] converts HTML content to clean markdown-derived HTML. 116 117 @param html_content The HTML content to convert *) 118 119 val post_excerpt_from_html : string -> max_length:int -> string 120 (** [post_excerpt_from_html html_content ~max_length] generates an excerpt from HTML content. 121 122 Converts HTML to markdown, truncates to max_length, and converts back to simple HTML. 123 124 @param html_content The HTML content to excerpt 125 @param max_length Maximum length of the excerpt in characters *) 126 127 val render_post_html : post:Post.t -> author_username:string -> string 128 (** [render_post_html ~post ~author_username] renders a single post as HTML. 129 130 @param post The post to render 131 @param author_username The username of the author (for linking) *) 132 133 val render_posts_page : 134 title:string -> 135 posts:string list -> 136 current_page:int -> 137 total_pages:int -> 138 base_path:string -> 139 nav_current:string -> 140 string 141 (** [render_posts_page ~title ~posts ~current_page ~total_pages ~base_path ~nav_current] 142 renders a complete HTML page with posts and pagination. 143 144 @param title Page title 145 @param posts List of pre-rendered post HTML strings 146 @param current_page Current page number (1-indexed) 147 @param total_pages Total number of pages 148 @param base_path Base path for pagination links (e.g., "" for root, "authors/" for author pages) 149 @param nav_current Which nav item is current ("posts", "authors", "categories", "links") *) 150 151 val page_template : title:string -> nav_current:string -> string -> string 152 (** [page_template ~title ~nav_current content] wraps content in the HTML page template. 153 154 @param title Page title 155 @param nav_current Which nav item is current 156 @param content The main content HTML *) 157end