My agentic slop goes here. Not intended for anyone else!
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(** This module determines an image to be used as preview of a website.
19
20 It does this by following the same logic Google+ and other websites use, and
21 described in this article:
22 https://www.raymondcamden.com/2011/07/26/How-are-Facebook-and-Google-creating-link-previews *)
23
24let og_image html =
25 let open Soup in
26 let soup = parse html in
27 try soup $ "meta[property=og:image]" |> R.attribute "content" |> Option.some
28 with Failure _ -> None
29
30let image_src html =
31 let open Soup in
32 let soup = parse html in
33 try soup $ "link[rel=\"image_src\"]" |> R.attribute "href" |> Option.some
34 with Failure _ -> None
35
36let twitter_image html =
37 let open Soup in
38 let soup = parse html in
39 try
40 soup $ "meta[name=\"twitter:image\"]" |> R.attribute "content"
41 |> Option.some
42 with Failure _ -> None
43
44let og_description html =
45 let open Soup in
46 let soup = parse html in
47 try
48 soup $ "meta[property=og:description]" |> R.attribute "content"
49 |> Option.some
50 with Failure _ -> None
51
52let description html =
53 let open Soup in
54 let soup = parse html in
55 try
56 soup $ "meta[property=description]" |> R.attribute "content" |> Option.some
57 with Failure _ -> None
58
59let preview_image html =
60 let preview_image =
61 match og_image html with
62 | None -> (
63 match image_src html with
64 | None -> twitter_image html
65 | Some x -> Some x)
66 | Some x -> Some x
67 in
68 match Option.map String.trim preview_image with
69 | Some "" -> None
70 | Some x -> Some x
71 | None -> None
72
73let description html =
74 let preview_image =
75 match og_description html with None -> description html | Some x -> Some x
76 in
77 match Option.map String.trim preview_image with
78 | Some "" -> None
79 | Some x -> Some x
80 | None -> None