Source file frontmatter_extractor.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
type extracted = { matter : string option; body : string }

let of_string ?(delimiter_char = '-') str =
  let start_matter_index = ref 0
  and end_matter_index = ref 0
  and started = ref false
  and new_line = ref true
  and count_delimiter_char = ref 0 in

  let min_delimiter_chars = 3 in

  begin
    let exception Break in
    try
      for i = 0 to String.length str - 1 do
        if !new_line && str.[i] = delimiter_char then incr count_delimiter_char
        else if str.[i] = '\n' then begin
          new_line := true;

          if (not !started) && !count_delimiter_char >= min_delimiter_chars then begin
            started := true;
            start_matter_index := i
          end
          else if !count_delimiter_char >= min_delimiter_chars then begin
            end_matter_index := i;
            raise_notrace Break
          end;

          count_delimiter_char := 0
        end
        else if str.[i] <> delimiter_char then new_line := false
      done
    with Break -> ()
  end;

  if !end_matter_index <> 0 then
    let matter =
      String.sub str !start_matter_index
        (!end_matter_index - !start_matter_index - !count_delimiter_char)
    in
    let body =
      String.sub str !end_matter_index (String.length str - !end_matter_index)
    in

    { matter = Some matter; body }
  else { matter = None; body = str }