feat add highlighted_code_listing UI component

New Ui.highlighted_code_listing function that accepts pre-highlighted lines (node list list) and renders them with the same line-number/anchor grid layout as the existing code_listing. This allows server-rendered syntax highlighting spans to be displayed with clickable line numbers.

Commit
e00b08194a49bcb8b5ecca73604a8e392424833b
Author
Marius Peter <dev@marius-peter.com>
Author date
Committer
Marius Peter <dev@marius-peter.com>
Committer date
Changed files
lib/views/ui.ml
index 1fd3c040..7ad72d4b 100644..100644
@@ -291,6 +291,27 @@
291 291 block ?id ?class_
292 292 (String.split_on_char '\n' content |> List.mapi numbered_line |> List.concat)
293 293
294 Added: let highlighted_code_listing ?id ?class_ ?(anchor_prefix = "") lines =
295 Added: (* Same grid layout as code_listing, but each line is a list of pre-rendered
296 Added: nodes (highlighted spans) rather than plain text. The tab/newline framing
297 Added: is identical so copy-paste behaviour is preserved. *)
298 Added: let numbered_line index line_nodes =
299 Added: let number = index + 1 in
300 Added: let name = Printf.sprintf "%s%d" anchor_prefix number in
301 Added: [
302 Added: HTML.a
303 Added: [
304 Added: HTML.id "%s" name;
305 Added: HTML.class_ "line-anchor";
306 Added: HTML.href "#%s" name;
307 Added: Aria.label "Line %d" number;
308 Added: ]
309 Added: [ text (string_of_int number) ];
310 Added: HTML.span [ HTML.class_ "line" ] (txt "\t" :: line_nodes);
311 Added: ]
312 Added: in
313 Added: block ?id ?class_ (List.mapi numbered_line lines |> List.concat)
314 Added:
294 315 (* Diffs *)
295 316
296 317 module Diff = struct
lib/views/ui.mli
index ce5f8074..da2d15cb 100644..100644
@@ -306,6 +306,15 @@
306 306 Content is emitted verbatim as text; syntax colouring, if any, is a
307 307 progressive enhancement layered on top. *)
308 308
309 Added: val highlighted_code_listing :
310 Added: ?id:string -> ?class_:string -> ?anchor_prefix:string -> node list list -> node
311 Added: (** A line-numbered listing of pre-highlighted source code.
312 Added:
313 Added: Like {!code_listing} but accepts lines already tokenized into styled spans
314 Added: (e.g. from {!Highlight.highlight}). Each inner list represents one line's
315 Added: worth of nodes; the function adds line numbers and anchors in the same
316 Added: grid layout as [code_listing]. *)
317 Added:
309 318 (** {1 Diffs} *)
310 319
311 320 (** A viewer for line-oriented change sets. The data types are deliberately