1+ let has_status status (item : Package.version_summary) =
2+ List.mem status item.statuses
3+
4+ let is_discouraged item =
5+ has_status Package.Avoided item || has_status Package.Deprecated item
6+
7+ let status_badge class_ label =
8+ <span class="inline-flex items-center whitespace-nowrap rounded border px-2 py-1 text-xs font-medium <%s class_ %>"><%s label %></span>
9+
10+ let ocaml_manual_version version =
11+ match String.split_on_char '.' version with
12+ | major :: minor :: _ ->
13+ let minor = List.hd (String.split_on_char '~' minor) in
14+ let minor = List.hd (String.split_on_char '+' minor) in
15+ Printf.sprintf "%s.%s" major minor
16+ | _ -> version
17+
18+ let documentation_href (package : Package.package) version =
19+ if package.name = "ocaml" then
20+ Printf.sprintf "/manual/%s/index.html" (ocaml_manual_version version)
21+ else Printf.sprintf "/p/%s/%s/doc/index.html" package.name version
22+
23+ let is_ocaml_compiler_package name =
24+ List.mem name
25+ [
26+ "ocaml";
27+ "ocaml-compiler";
28+ "ocaml-base-compiler";
29+ "ocaml-system";
30+ "ocaml-variants";
31+ ]
32+
33+ let render_statuses ~is_latest ~is_selected item =
34+ let previous = not is_latest && not (is_discouraged item) in
35+ let badges =
36+ [
37+ (if is_latest then
38+ Some
39+ (status_badge
40+ "border-primary bg-primary_25 text-title dark:border-dark-primary dark:bg-dark-primary_10 dark:text-dark-title"
41+ "Latest URL target")
42+ else None);
43+ (if previous then
44+ Some
45+ (status_badge
46+ "border-gray-300 bg-gray-100 text-title dark:border-gray-500 dark:bg-gray-700 dark:text-dark-title"
47+ "Previous")
48+ else None);
49+ (if has_status Package.Avoided item then
50+ Some
51+ (status_badge
52+ "border-yellow-600 bg-yellow-100 text-yellow-900 dark:border-yellow-500 dark:bg-yellow-900 dark:text-yellow-100"
53+ "Avoided by opam")
54+ else None);
55+ (if has_status Package.Deprecated item then
56+ Some
57+ (status_badge
58+ "border-red-600 bg-red-100 text-red-900 dark:border-red-500 dark:bg-red-900 dark:text-red-100"
59+ "Deprecated by opam")
60+ else None);
61+ (if is_selected then
62+ Some
63+ (status_badge
64+ "border-title bg-white text-title dark:border-dark-title dark:bg-dark-card dark:text-dark-title"
65+ "Selected")
66+ else None);
67+ ]
68+ |> List.filter_map Fun.id
69+ in
70+ <span class="flex flex-wrap gap-2"><%s! String.concat "" badges %></span>
71+
172let render
273(package : Package.package)
374=
75+ let selected_version = Package.specific_version package in
76+ let latest_versions, remaining_versions =
77+ List.partition
78+ (fun (item : Package.version_summary) ->
79+ item.version = package.latest_version)
80+ package.versions
81+ in
82+ let discouraged_versions, previous_versions =
83+ List.partition is_discouraged remaining_versions
84+ in
85+ let render_row (item : Package.version_summary) =
86+ let is_latest = item.version = package.latest_version in
87+ let is_selected = selected_version = item.version in
88+ let cell_background =
89+ if is_selected then
90+ "bg-primary_25 dark:bg-dark-primary_10"
91+ else "bg-white dark:bg-dark-card"
92+ in
93+ <tr>
94+ <th scope="row" class="rounded-l text-left text-title dark:text-dark-title <%s cell_background %>">
95+ <a href="/p/<%s package.name %>/<%s item.version %>" aria-current="<%s if is_selected then "page" else "false" %>"
96+ class="inline-flex min-h-[44px] items-center p-4 text-base hover:underline focus-visible:rounded focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-[-4px] focus-visible:outline-primary dark:focus-visible:outline-dark-primary">
97+ <%s item.version %>
98+ </a>
99+ </th>
100+ <td class="p-4 text-left text-title dark:text-dark-title <%s cell_background %>">
101+ <%s! render_statuses ~is_latest ~is_selected item %>
102+ </td>
103+ <td class="p-4 text-left text-sm text-title dark:text-dark-title <%s cell_background %>">
104+ <time datetime="<%s Utils.iso_date_of_timestamp item.opam_repository_date %>">
105+ <%s Utils.human_date_of_timestamp item.opam_repository_date %>
106+ </time>
107+ </td>
108+ <td class="rounded-r text-left text-sm <%s cell_background %>">
109+ <a href="<%s documentation_href package item.version %>"
110+ class="inline-flex min-h-[44px] items-center gap-2 p-4 font-medium text-primary hover:underline focus-visible:rounded focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-[-4px] focus-visible:outline-primary dark:text-dark-primary dark:focus-visible:outline-dark-primary">
111+ <span aria-hidden="true"><%s! Icons.document "h-5 w-5"; %></span>
112+ Documentation
113+ </a>
114+ </td>
115+ </tr>
116+ in
117+ let render_group title versions =
118+ match versions with
119+ | [] -> ""
120+ | versions ->
121+ <tbody>
122+ <tr>
123+ <th colspan="4" scope="rowgroup" class="pb-1 pt-6 text-left text-lg font-semibold text-title dark:text-dark-title"><%s title %></th>
124+ </tr>
125+ <%s! versions |> List.map render_row |> String.concat "" %>
126+ </tbody>
127+ in
4128Layout.render
5- ~title:(Printf.sprintf "%s Versions" package.name)
6- ~description:"Package Versions" @@
7- let version = Package.specific_version package in
8- <div class="bg-default dark:bg-dark-default py-8">
129+ ~title:(Printf.sprintf "%s opam package versions" package.name)
130+ ~description:(Printf.sprintf "Versions and opam status for the %s package" package.name) @@
131+ <div class="py-8">
9132 <div class="container-fluid flex items-center gap-2">
10- <a href="/p/<%s package.name %>" class="h-11 w-11 m-5 border-primary border-2 rounded-full flex items-center justify-center"><%s! Icons.arrow_left "h-6 w-6 text-primary"; %></a>
11- <h1 class="text-2xl text-title dark:text-dark-title font-medium"><%s package.name %> Versions (<%i List.length package.versions %>) </h1>
133+ <a href="/p/<%s package.name %>" aria-label="Back to <%s package.name %> package"
134+ class="m-5 flex h-11 w-11 shrink-0 items-center justify-center rounded-full border-2 border-primary focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary dark:border-dark-primary dark:focus-visible:outline-dark-primary">
135+ <span aria-hidden="true"><%s! Icons.arrow_left "h-6 w-6 text-primary dark:text-dark-primary"; %></span>
136+ </a>
137+ <h1 class="text-2xl font-medium text-title dark:text-dark-title"><%s package.name %> opam package versions (<%i List.length package.versions %>)</h1>
12138 </div>
13- <div class="container-fluid flex justify-center">
14- <table class="table-auto border-separate border-spacing-y-6">
15- <thead class="container-fluid text-md text-lighter text-left">
16- <tr class="py-4">
17- <th class="hidden sm:table-cell text-left text-title dark:text-dark-title font-normal border-b-2 border-gray-200 dark:border-gray-400 py-4 pl-3 md:pr-14"><%s! Icons.bars_3 "h-5 w-5"; %></th>
18- <th class="text-left text-title dark:text-dark-title font-normal border-b-2 border-gray-200 dark:border-gray-400 px-5 md:pr-12">Version</th>
19- <th class="text-left text-title dark:text-dark-title font-normal border-b-2 border-gray-200 dark:border-gray-400 md:pr-14">Release Date</th>
20- <th class="text-left text-title dark:text-dark-title font-normal border-b-2 border-gray-200 dark:border-gray-400 px-5 md:pr-14">Links</th>
21- </tr>
22- </thead>
23- <tbody>
24- <% package.versions |> List.iter (fun (item: Package.version_with_publication_date) -> %>
25- <tr class="tr-selected">
26- <td class="hidden sm:table-cell text-left font-normal py-5 px-4 <%s if version = item.version then "bg-primary-200 rounded-l" else "" %>">
27- <% if version = item.version then ( %><div class="bg-primary dark:bg-dark-primary h-3 w-3 rounded-full"></div><% ) else ( %><div class="bg-gray-200 dark:bg-gray-400 h-2 w-2 rounded-full ml-0.5"></div><% ); %>
28- <div class="absolute h-[4.5rem] pl-1">
29- <% if List.nth package.versions (List.length package.versions -1) <> item then ( %>
30- <div class="-ml-px w-1 border-solid border-r-2 border-gray-200 dark:border-gray-400 h-full"></div>
31- <% ); %>
32- </div>
33- </td>
34- <td class="text-left text-title dark:text-dark-title bg-primary-200">
35- <a href="/p/<%s package.name %>/<%s item.version %>" class="p-5 hover:no-underline hover:text-primary focus:text-primary focus:no-underline <%s if version = item.version then "font-bold focus:font-bold" else "" %> text-base md:mr-10">
36- <%s item.version %>
37- </a>
38- </td>
39- <td class="pr-4 text-left text-title dark:text-dark-title text-sm bg-primary-200">
40- <%s Utils.human_date_of_timestamp item.publication %>
41- </td>
42- <td class="text-left text-sm bg-primary-200 rounded-r">
43- <a href="/p/<%s package.name %>/<%s item.version %>/doc/index.html" class="text-primary dark:text-dark-primary flex items-center p-2 font-medium sm:p-4"><%s! Icons.document "h-5 w-5"; %> Documentation</a>
44- </td>
139+ <div class="container-fluid">
140+ <% if is_ocaml_compiler_package package.name then ( %>
141+ <aside aria-labelledby="official-ocaml-releases-title"
142+ class="mb-6 max-w-3xl rounded border-l-4 border-primary bg-primary_25 p-5 text-content dark:border-dark-primary dark:bg-dark-primary_10 dark:text-dark-content">
143+ <h2 id="official-ocaml-releases-title" class="text-lg font-semibold text-title dark:text-dark-title">Official OCaml releases</h2>
144+ <p class="mt-2">
145+ This page is an opam package listing, not the list of official OCaml releases.
146+ It may include compiler versions that have not been officially released.
147+ </p>
148+ <a href="<%s Url.releases %>"
149+ class="mt-2 inline-flex min-h-[44px] items-center font-medium text-primary underline underline-offset-4 focus-visible:rounded focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary dark:text-dark-primary dark:focus-visible:outline-dark-primary">
150+ View official OCaml releases
151+ </a>
152+ </aside>
153+ <% ); %>
154+ <p class="max-w-3xl text-content dark:text-dark-content">
155+ This page lists package versions found in opam-repository.
156+ On ocaml.org, the <code>latest</code> URL currently points to version <strong><%s package.latest_version %></strong>;
157+ this does not indicate an upstream release status.
158+ Versions marked Avoided or Deprecated are not normally selected by opam.
159+ </p>
160+ <div class="mt-4 overflow-x-auto">
161+ <table class="w-full min-w-[48rem] table-auto border-separate border-spacing-y-3">
162+ <caption class="sr-only">Versions and opam status for the <%s package.name %> package</caption>
163+ <thead class="text-left">
164+ <tr>
165+ <th scope="col" class="border-b-2 border-gray-200 px-4 py-4 font-normal text-title dark:border-gray-400 dark:text-dark-title">Version</th>
166+ <th scope="col" class="border-b-2 border-gray-200 px-4 py-4 font-normal text-title dark:border-gray-400 dark:text-dark-title">Status</th>
167+ <th scope="col" class="border-b-2 border-gray-200 px-4 py-4 font-normal text-title dark:border-gray-400 dark:text-dark-title">Added to opam-repository</th>
168+ <th scope="col" class="border-b-2 border-gray-200 px-4 py-4 font-normal text-title dark:border-gray-400 dark:text-dark-title">Links</th>
45169 </tr>
46- <% ); %>
47- </tbody>
48- </table>
170+ </thead>
171+ <%s! render_group "Version selected by the latest URL" latest_versions %>
172+ <%s! render_group "Previous versions" previous_versions %>
173+ <%s! render_group "Versions not normally selected by opam" discouraged_versions %>
174+ </table>
175+ </div>
49176 </div>
50- </div>
177+ </div>
0 commit comments