package b0

  1. Overview
  2. Docs
Software construction and deployment kit

Install

dune-project
 Dependency

Authors

Maintainers

Sources

b0-0.0.6.tbz
sha512=e9aa779e66c08fc763019f16d4706f465d16c05d6400b58fbd0313317ef33ddea51952e2b058db28e65f7ddb7012f328c8bf02d8f1da17bb543348541a2587f0

doc/src/b0.std/b0_adhoc.ml.html

Source file b0_adhoc.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
(*---------------------------------------------------------------------------
   Copyright (c) 2025 The b0 programmers. All rights reserved.
   SPDX-License-Identifier: ISC
  ---------------------------------------------------------------------------*)

open B0_std

(* CommonMark *)

let commonmark_first_section ~preamble md =
  let atx_heading s (* trimmed *) =
    (* approximate https://spec.commonmark.org/0.29/#atx-headings *)
    let num, title = String.cut_first_while (Char.equal '#') s in
    let num = String.length num and tlen = String.length title in
    if num = 0 || num > 6 then None else
    if tlen = 0 then Some (num, "") else
    if title.[0] <> ' ' then None else
    Some (num, String.trim title)
  in
  let setex_heading s (* trimmed *) =
    (* approximate https://spec.commonmark.org/0.29/#setext-headings *)
    if String.starts_with ~prefix:"==" s then Some 1 else
    if String.starts_with ~prefix:"--" s then Some 2 else
    None
  in
  let nl = "\n" in
  let prev_lines prev = String.trim (String.concat nl (List.rev prev)) in
  let rec find_content num title prev = function
  | [] -> Some (title, String.concat nl (List.rev prev))
  | l :: ls ->
      let ltrim = String.trim l in
      match atx_heading ltrim with
      | Some (n, _) when n <= num || preamble -> Some (title, prev_lines prev)
      | Some _ -> find_content num title (l :: prev) ls
      | None ->
          match setex_heading ltrim with
          | Some n when n <= num || preamble ->
              let prev = match prev with [] -> [] | _ :: prev -> prev in
              Some (title, prev_lines prev)
          | Some _ | None -> find_content num title (l :: prev) ls
  and find_heading prev = function
  | [] -> None
  | l :: ls ->
      let l = String.trim l in
      if String.is_empty l then find_heading [] ls else
      match atx_heading l with
      | Some (num, title) -> find_content num title [] ls
      | None ->
          match setex_heading l with
          | None -> find_heading (l :: prev) ls
          | Some num ->
              let title = prev_lines prev in
              find_content num title [] ls
  in
  let add_line _ ls l = l :: ls in
  let rev_lines = String.fold_ascii_lines ~strip_newlines:true add_line [] md in
  find_heading [] (List.rev rev_lines)