logarion/src/core/note.ml

48 lines
1.7 KiB
OCaml

type t = {
meta: Meta.t;
body: string;
} [@@deriving lens { submodule = true }]
let blank ?(uuid=(Meta.Id.generate ())) () = { meta = Meta.blank ~uuid (); body = "" }
let title ymd =
let mtitle = ymd.meta.Meta.title in
if String.length mtitle > 0 then mtitle else
let open Omd in
try List.find (function H1 _ -> true | _ -> false) (Omd.of_string ymd.body)
|> function H1 h -> to_text h | _ -> ""
with Not_found -> ""
let categorised categs ymd = Meta.CategorySet.categorised categs ymd.meta.Meta.categories
let with_kv ymd (k,v) = match k with
| "body" -> { ymd with body = String.trim v }
| _ -> { ymd with meta = Meta.with_kv ymd.meta (k,v) }
let meta_pair_of_string line = match Re.Str.(bounded_split (regexp ": *")) line 2 with
| [ key; value ] -> Re.Str.(replace_first (regexp "^#\\+") "" key), value
| [ key ] -> Re.Str.(replace_first (regexp "^#\\+") "" key), ""
| _ -> prerr_endline line; ("","")
let meta_of_string front_matter =
let fields = List.map meta_pair_of_string (String.split_on_char '\n' front_matter) in
List.fold_left Meta.with_kv (Meta.blank ()) fields
exception Syntax_error of string
let front_matter_body_split s =
if Re.Str.(string_match (regexp ".*:.*")) s 0
then match Re.Str.(bounded_split (regexp "\n\n")) s 2 with
| front::body::[] -> (front, body)
| _ -> ("", s)
else ("", s)
let of_string s =
let (front_matter, body) = front_matter_body_split s in
try
let note = { meta = meta_of_string front_matter; body } in
{ note with meta = { note.meta with title = title note } }
with _ -> prerr_endline ("Failed parsing" ^ s); blank ()
let to_string ymd = Meta.to_string ymd.meta ^ "\n" ^ ymd.body