48 lines
1.7 KiB
OCaml
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
|