OCaml library for JSONfeed parsing and creation

complete the implementation for references

+1
.gitignore
···
_build
···
_build
+
blog-feed.json
+1 -1
jsonfeed.opam
···
homepage: "https://tangled.sh/@anil.recoil.org/ocaml-jsonfeed"
bug-reports: "https://tangled.sh/@anil.recoil.org/ocaml-jsonfeed"
depends: [
-
"dune" {>= "3.20"}
"ocaml" {>= "5.2.0"}
"jsonm" {>= "1.0.0"}
"ptime" {>= "1.2.0"}
···
homepage: "https://tangled.sh/@anil.recoil.org/ocaml-jsonfeed"
bug-reports: "https://tangled.sh/@anil.recoil.org/ocaml-jsonfeed"
depends: [
+
"dune" {>= "3.18"}
"ocaml" {>= "5.2.0"}
"jsonm" {>= "1.0.0"}
"ptime" {>= "1.2.0"}
+161
lib/cito.ml
···
···
+
type t = [
+
| `Cites
+
| `CitesAsAuthority
+
| `CitesAsDataSource
+
| `CitesAsEvidence
+
| `CitesForInformation
+
| `UsesDataFrom
+
| `UsesMethodIn
+
| `UsesConclusionsFrom
+
| `AgreesWith
+
| `DisagreesWith
+
| `Confirms
+
| `Refutes
+
| `Disputes
+
| `Critiques
+
| `Qualifies
+
| `Corrects
+
| `Updates
+
| `Extends
+
| `Parodies
+
| `Plagiarizes
+
| `Derides
+
| `Ridicules
+
| `Describes
+
| `Documents
+
| `CitesAsSourceDocument
+
| `CitesAsMetadataDocument
+
| `Compiles
+
| `Reviews
+
| `Retracts
+
| `Supports
+
| `GivesSupportTo
+
| `ObtainsSupportFrom
+
| `GivesBackgroundTo
+
| `ObtainsBackgroundFrom
+
| `SpeculatesOn
+
| `CitesAsPotentialSolution
+
| `CitesAsRecommendedReading
+
| `CitesAsRelated
+
| `IncludesQuotationFrom
+
| `IncludesExcerptFrom
+
| `RepliesTo
+
| `HasReplyFrom
+
| `LinksTo
+
| `SharesAuthorWith
+
| `SharesJournalWith
+
| `SharesPublicationVenueWith
+
| `SharesFundingAgencyWith
+
| `SharesAuthorInstitutionWith
+
| `Other of string
+
]
+
+
let to_string = function
+
| `Cites -> "cites"
+
| `CitesAsAuthority -> "citesAsAuthority"
+
| `CitesAsDataSource -> "citesAsDataSource"
+
| `CitesAsEvidence -> "citesAsEvidence"
+
| `CitesForInformation -> "citesForInformation"
+
| `UsesDataFrom -> "usesDataFrom"
+
| `UsesMethodIn -> "usesMethodIn"
+
| `UsesConclusionsFrom -> "usesConclusionsFrom"
+
| `AgreesWith -> "agreesWith"
+
| `DisagreesWith -> "disagreesWith"
+
| `Confirms -> "confirms"
+
| `Refutes -> "refutes"
+
| `Disputes -> "disputes"
+
| `Critiques -> "critiques"
+
| `Qualifies -> "qualifies"
+
| `Corrects -> "corrects"
+
| `Updates -> "updates"
+
| `Extends -> "extends"
+
| `Parodies -> "parodies"
+
| `Plagiarizes -> "plagiarizes"
+
| `Derides -> "derides"
+
| `Ridicules -> "ridicules"
+
| `Describes -> "describes"
+
| `Documents -> "documents"
+
| `CitesAsSourceDocument -> "citesAsSourceDocument"
+
| `CitesAsMetadataDocument -> "citesAsMetadataDocument"
+
| `Compiles -> "compiles"
+
| `Reviews -> "reviews"
+
| `Retracts -> "retracts"
+
| `Supports -> "supports"
+
| `GivesSupportTo -> "givesSupportTo"
+
| `ObtainsSupportFrom -> "obtainsSupportFrom"
+
| `GivesBackgroundTo -> "givesBackgroundTo"
+
| `ObtainsBackgroundFrom -> "obtainsBackgroundFrom"
+
| `SpeculatesOn -> "speculatesOn"
+
| `CitesAsPotentialSolution -> "citesAsPotentialSolution"
+
| `CitesAsRecommendedReading -> "citesAsRecommendedReading"
+
| `CitesAsRelated -> "citesAsRelated"
+
| `IncludesQuotationFrom -> "includesQuotationFrom"
+
| `IncludesExcerptFrom -> "includesExcerptFrom"
+
| `RepliesTo -> "repliesTo"
+
| `HasReplyFrom -> "hasReplyFrom"
+
| `LinksTo -> "linksTo"
+
| `SharesAuthorWith -> "sharesAuthorWith"
+
| `SharesJournalWith -> "sharesJournalWith"
+
| `SharesPublicationVenueWith -> "sharesPublicationVenueWith"
+
| `SharesFundingAgencyWith -> "sharesFundingAgencyWith"
+
| `SharesAuthorInstitutionWith -> "sharesAuthorInstitutionWith"
+
| `Other s -> s
+
+
let of_string s =
+
match String.lowercase_ascii s with
+
| "cites" -> `Cites
+
| "citesasauthority" -> `CitesAsAuthority
+
| "citesasdatasource" -> `CitesAsDataSource
+
| "citesasevidence" -> `CitesAsEvidence
+
| "citesforinformation" -> `CitesForInformation
+
| "usesdatafrom" -> `UsesDataFrom
+
| "usesmethodin" -> `UsesMethodIn
+
| "usesconclusionsfrom" -> `UsesConclusionsFrom
+
| "agreeswith" -> `AgreesWith
+
| "disagreeswith" -> `DisagreesWith
+
| "confirms" -> `Confirms
+
| "refutes" -> `Refutes
+
| "disputes" -> `Disputes
+
| "critiques" -> `Critiques
+
| "qualifies" -> `Qualifies
+
| "corrects" -> `Corrects
+
| "updates" -> `Updates
+
| "extends" -> `Extends
+
| "parodies" -> `Parodies
+
| "plagiarizes" -> `Plagiarizes
+
| "derides" -> `Derides
+
| "ridicules" -> `Ridicules
+
| "describes" -> `Describes
+
| "documents" -> `Documents
+
| "citesassourcedocument" -> `CitesAsSourceDocument
+
| "citesasmetadatadocument" -> `CitesAsMetadataDocument
+
| "compiles" -> `Compiles
+
| "reviews" -> `Reviews
+
| "retracts" -> `Retracts
+
| "supports" -> `Supports
+
| "givessupportto" -> `GivesSupportTo
+
| "obtainssupportfrom" -> `ObtainsSupportFrom
+
| "givesbackgroundto" -> `GivesBackgroundTo
+
| "obtainsbackgroundfrom" -> `ObtainsBackgroundFrom
+
| "speculateson" -> `SpeculatesOn
+
| "citesaspotentialsolution" -> `CitesAsPotentialSolution
+
| "citesasrecommendedreading" -> `CitesAsRecommendedReading
+
| "citesasrelated" -> `CitesAsRelated
+
| "includesquotationfrom" -> `IncludesQuotationFrom
+
| "includesexcerptfrom" -> `IncludesExcerptFrom
+
| "repliesto" -> `RepliesTo
+
| "hasreplyfrom" -> `HasReplyFrom
+
| "linksto" -> `LinksTo
+
| "sharesauthorwith" -> `SharesAuthorWith
+
| "sharesjournalwith" -> `SharesJournalWith
+
| "sharespublicationvenuewith" -> `SharesPublicationVenueWith
+
| "sharesfundingagencywith" -> `SharesFundingAgencyWith
+
| "sharesauthorinstitutionwith" -> `SharesAuthorInstitutionWith
+
| _ -> `Other s
+
+
let equal a b =
+
match a, b with
+
| `Other sa, `Other sb -> sa = sb
+
| _ -> a = b
+
+
let pp ppf t = Format.fprintf ppf "%s" (to_string t)
+1 -2
lib/dune
···
(library
(name jsonfeed)
(public_name jsonfeed)
-
(libraries jsonm ptime fmt)
-
(modules_without_implementation cito reference))
···
(library
(name jsonfeed)
(public_name jsonfeed)
+
(libraries jsonm ptime fmt))
+32 -1
lib/jsonfeed.ml
···
| None -> None
in
Item.create ~id ~content ?url ?external_url ?title ?summary ?image
?banner_image ?date_published ?date_modified ?authors ?tags ?language
-
?attachments ()
let parse_item = function
| Object obj -> parse_item_obj obj
···
ignore (Jsonm.encode enc (`Lexeme `Oe))
in
let enc_hub hub =
ignore (Jsonm.encode enc (`Lexeme `Os));
enc_field "type" (fun () -> enc_string (Hub.type_ hub));
···
enc_opt (fun atts ->
enc_field "attachments" (fun () -> enc_list enc_attachment atts))
(Item.attachments item);
ignore (Jsonm.encode enc (`Lexeme `Oe))
in
···
| None -> None
in
+
let parse_reference = function
+
| Object obj ->
+
let url = require_string "url" obj in
+
let doi = optional_string "doi" obj in
+
Reference.create ~url ?doi ()
+
| _ -> raise (Invalid_feed "Reference must be an object")
+
in
+
+
let references =
+
match optional_array "_references" obj with
+
| Some arr ->
+
let parsed = List.map parse_reference arr in
+
if parsed = [] then None else Some parsed
+
| None -> None
+
in
+
Item.create ~id ~content ?url ?external_url ?title ?summary ?image
?banner_image ?date_published ?date_modified ?authors ?tags ?language
+
?attachments ?references ()
let parse_item = function
| Object obj -> parse_item_obj obj
···
ignore (Jsonm.encode enc (`Lexeme `Oe))
in
+
let enc_reference ref =
+
ignore (Jsonm.encode enc (`Lexeme `Os));
+
enc_field "url" (fun () -> enc_string (Reference.url ref));
+
enc_opt (fun doi -> enc_field "doi" (fun () -> enc_string doi))
+
(Reference.doi ref);
+
enc_opt (fun cito_list ->
+
enc_field "cito" (fun () ->
+
enc_list (fun cito -> enc_string (Cito.to_string cito)) cito_list))
+
(Reference.cito ref);
+
ignore (Jsonm.encode enc (`Lexeme `Oe))
+
in
+
let enc_hub hub =
ignore (Jsonm.encode enc (`Lexeme `Os));
enc_field "type" (fun () -> enc_string (Hub.type_ hub));
···
enc_opt (fun atts ->
enc_field "attachments" (fun () -> enc_list enc_attachment atts))
(Item.attachments item);
+
enc_opt (fun refs ->
+
enc_field "_references" (fun () -> enc_list enc_reference refs))
+
(Item.references item);
ignore (Jsonm.encode enc (`Lexeme `Oe))
in
+20
lib/reference.ml
···
···
+
type t = {
+
url : string;
+
doi : string option;
+
cito : Cito.t list option;
+
}
+
+
let create ~url ?doi ?cito () = { url; doi; cito }
+
+
let url t = t.url
+
let doi t = t.doi
+
let cito t = t.cito
+
+
let equal a b = String.equal a.url b.url
+
+
let pp ppf t =
+
let open Format in
+
fprintf ppf "%s" t.url;
+
match t.doi with
+
| Some d -> fprintf ppf " [DOI: %s]" d
+
| None -> ()