diff --git a/lib/frontmatter.ml b/lib/frontmatter.ml index 86774dc..3100347 100644 --- a/lib/frontmatter.ml +++ b/lib/frontmatter.ml @@ -1,8 +1,6 @@ module Y = Hl_yaml.Unix module StringMap = Map.Make (String) -exception Frontmatter_parse_error of string - (* Type for frontmatter data *) type t = Yojson.Safe.t StringMap.t @@ -56,15 +54,10 @@ let yojson_to_string_map = function StringMap.empty assoc) | _ -> Error "Frontmatter must be a YAML object/map" -let parse_frontmatter (yaml_content : string) : t = - if String.trim yaml_content = "" then StringMap.empty - else - try - let options = Y.make_options ~enable_imports:false () in - let result = - Y.parse ~options ~of_yojson:yojson_to_string_map yaml_content - in - Y.ok_or_raise result - with exn -> - raise - (Frontmatter_parse_error ("Parsing failed: " ^ Printexc.to_string exn)) +let parse_frontmatter (yaml_content : string) : (t, string) Result.t = + let options = Y.make_options ~enable_imports:false () in + match Y.parse ~options ~of_yojson:yojson_to_string_map yaml_content with + | Ok fm -> Ok fm + | Error error_list -> + Error + (List.map Hl_yaml.Spec.error_to_string error_list |> String.concat "\n") diff --git a/lib/frontmatter.mli b/lib/frontmatter.mli index 196b89f..051658b 100644 --- a/lib/frontmatter.mli +++ b/lib/frontmatter.mli @@ -25,9 +25,6 @@ module StringMap : Map.S with type key = string type t = Yojson.Safe.t StringMap.t (** Type representing the frontmatter as a map of string keys to JSON values. *) -exception Frontmatter_parse_error of string -(** Exception raised when frontmatter parsing fails. *) - val extract_frontmatter : string -> string * string (** [extract_frontmatter content] extracts the YAML frontmatter from the beginning of the markdown content. It returns the YAML part and the rest of @@ -45,22 +42,17 @@ val extract_frontmatter : string -> string * string markdown file, it must not be silently parsed as content. A YAML parsing error whenever the parsing happens is desired instead. *) -val parse_frontmatter : string -> t +val parse_frontmatter : string -> (t, string) Result.t (** [parse_frontmatter content] parses YAML frontmatter from a string. @param content The frontmatter part of the markdown content @return - A map where keys are frontmatter field names and values are the - corresponding JSON values preserving their original types - - @raise Frontmatter_parse_error - if the YAML parsing fails or if the frontmatter is not a valid YAML - object/map + A result object which when Ok, contains a map where keys are frontmatter + field names and values are the corresponding JSON values preserving their + original types. When error, contains an error message indicating the + parsing failure(s). Returns an empty map if: - The frontmatter section is empty - The function expects frontmatter to be: - - Valid YAML that parses to an object/map structure - Security note: File imports are disabled during parsing for security. *) diff --git a/lib/page.ml b/lib/page.ml index d834c88..b1d8bc0 100644 --- a/lib/page.ml +++ b/lib/page.ml @@ -1,7 +1,3 @@ module UserPage = struct type t = { frontmatter : Frontmatter.t; content : string } - - (* let of_string (content : string) : t = - match Frontmatter.extract_frontmatter content with - | (yaml_content, remaining_content) -> *) end diff --git a/test/test_frontmatter.ml b/test/test_frontmatter.ml index 826de6d..9661f83 100644 --- a/test/test_frontmatter.ml +++ b/test/test_frontmatter.ml @@ -75,19 +75,20 @@ let%test "extract content from md with invalid frontmatter" = String.trim content = {|" # bad yaml|} let%test "parse valid yaml" = - let fm = parse_frontmatter simple_markdown_yaml_section in - let expected = - StringMap.of_list - [ - ("Title", `String "Test Document"); - ("Draft", `Bool true); - ("Date", `String "2023-10-01"); - ] - in - StringMap.equal Yojson.Safe.equal fm expected + match parse_frontmatter simple_markdown_yaml_section with + | Error _ -> false + | Ok fm -> + let expected = + StringMap.of_list + [ + ("Title", `String "Test Document"); + ("Draft", `Bool true); + ("Date", `String "2023-10-01"); + ] + in + StringMap.equal Yojson.Safe.equal fm expected -let%test "parse invalid yaml raises Frontmatter_parse_error" = - try - ignore (parse_frontmatter invalid_yaml_frontmatter); - false - with Frontmatter_parse_error _ -> true +let%test "parse invalid yaml should error" = + match parse_frontmatter invalid_yaml_frontmatter with + | Error _ -> true + | Ok _ -> false