OCaml library for JSONfeed parsing and creation

complete the implementation for references

+216 -4
+1
.gitignore
··· 1 1 _build 2 + blog-feed.json
+1 -1
jsonfeed.opam
··· 9 9 homepage: "https://tangled.sh/@anil.recoil.org/ocaml-jsonfeed" 10 10 bug-reports: "https://tangled.sh/@anil.recoil.org/ocaml-jsonfeed" 11 11 depends: [ 12 - "dune" {>= "3.20"} 12 + "dune" {>= "3.18"} 13 13 "ocaml" {>= "5.2.0"} 14 14 "jsonm" {>= "1.0.0"} 15 15 "ptime" {>= "1.2.0"}
+161
lib/cito.ml
··· 1 + type t = [ 2 + | `Cites 3 + | `CitesAsAuthority 4 + | `CitesAsDataSource 5 + | `CitesAsEvidence 6 + | `CitesForInformation 7 + | `UsesDataFrom 8 + | `UsesMethodIn 9 + | `UsesConclusionsFrom 10 + | `AgreesWith 11 + | `DisagreesWith 12 + | `Confirms 13 + | `Refutes 14 + | `Disputes 15 + | `Critiques 16 + | `Qualifies 17 + | `Corrects 18 + | `Updates 19 + | `Extends 20 + | `Parodies 21 + | `Plagiarizes 22 + | `Derides 23 + | `Ridicules 24 + | `Describes 25 + | `Documents 26 + | `CitesAsSourceDocument 27 + | `CitesAsMetadataDocument 28 + | `Compiles 29 + | `Reviews 30 + | `Retracts 31 + | `Supports 32 + | `GivesSupportTo 33 + | `ObtainsSupportFrom 34 + | `GivesBackgroundTo 35 + | `ObtainsBackgroundFrom 36 + | `SpeculatesOn 37 + | `CitesAsPotentialSolution 38 + | `CitesAsRecommendedReading 39 + | `CitesAsRelated 40 + | `IncludesQuotationFrom 41 + | `IncludesExcerptFrom 42 + | `RepliesTo 43 + | `HasReplyFrom 44 + | `LinksTo 45 + | `SharesAuthorWith 46 + | `SharesJournalWith 47 + | `SharesPublicationVenueWith 48 + | `SharesFundingAgencyWith 49 + | `SharesAuthorInstitutionWith 50 + | `Other of string 51 + ] 52 + 53 + let to_string = function 54 + | `Cites -> "cites" 55 + | `CitesAsAuthority -> "citesAsAuthority" 56 + | `CitesAsDataSource -> "citesAsDataSource" 57 + | `CitesAsEvidence -> "citesAsEvidence" 58 + | `CitesForInformation -> "citesForInformation" 59 + | `UsesDataFrom -> "usesDataFrom" 60 + | `UsesMethodIn -> "usesMethodIn" 61 + | `UsesConclusionsFrom -> "usesConclusionsFrom" 62 + | `AgreesWith -> "agreesWith" 63 + | `DisagreesWith -> "disagreesWith" 64 + | `Confirms -> "confirms" 65 + | `Refutes -> "refutes" 66 + | `Disputes -> "disputes" 67 + | `Critiques -> "critiques" 68 + | `Qualifies -> "qualifies" 69 + | `Corrects -> "corrects" 70 + | `Updates -> "updates" 71 + | `Extends -> "extends" 72 + | `Parodies -> "parodies" 73 + | `Plagiarizes -> "plagiarizes" 74 + | `Derides -> "derides" 75 + | `Ridicules -> "ridicules" 76 + | `Describes -> "describes" 77 + | `Documents -> "documents" 78 + | `CitesAsSourceDocument -> "citesAsSourceDocument" 79 + | `CitesAsMetadataDocument -> "citesAsMetadataDocument" 80 + | `Compiles -> "compiles" 81 + | `Reviews -> "reviews" 82 + | `Retracts -> "retracts" 83 + | `Supports -> "supports" 84 + | `GivesSupportTo -> "givesSupportTo" 85 + | `ObtainsSupportFrom -> "obtainsSupportFrom" 86 + | `GivesBackgroundTo -> "givesBackgroundTo" 87 + | `ObtainsBackgroundFrom -> "obtainsBackgroundFrom" 88 + | `SpeculatesOn -> "speculatesOn" 89 + | `CitesAsPotentialSolution -> "citesAsPotentialSolution" 90 + | `CitesAsRecommendedReading -> "citesAsRecommendedReading" 91 + | `CitesAsRelated -> "citesAsRelated" 92 + | `IncludesQuotationFrom -> "includesQuotationFrom" 93 + | `IncludesExcerptFrom -> "includesExcerptFrom" 94 + | `RepliesTo -> "repliesTo" 95 + | `HasReplyFrom -> "hasReplyFrom" 96 + | `LinksTo -> "linksTo" 97 + | `SharesAuthorWith -> "sharesAuthorWith" 98 + | `SharesJournalWith -> "sharesJournalWith" 99 + | `SharesPublicationVenueWith -> "sharesPublicationVenueWith" 100 + | `SharesFundingAgencyWith -> "sharesFundingAgencyWith" 101 + | `SharesAuthorInstitutionWith -> "sharesAuthorInstitutionWith" 102 + | `Other s -> s 103 + 104 + let of_string s = 105 + match String.lowercase_ascii s with 106 + | "cites" -> `Cites 107 + | "citesasauthority" -> `CitesAsAuthority 108 + | "citesasdatasource" -> `CitesAsDataSource 109 + | "citesasevidence" -> `CitesAsEvidence 110 + | "citesforinformation" -> `CitesForInformation 111 + | "usesdatafrom" -> `UsesDataFrom 112 + | "usesmethodin" -> `UsesMethodIn 113 + | "usesconclusionsfrom" -> `UsesConclusionsFrom 114 + | "agreeswith" -> `AgreesWith 115 + | "disagreeswith" -> `DisagreesWith 116 + | "confirms" -> `Confirms 117 + | "refutes" -> `Refutes 118 + | "disputes" -> `Disputes 119 + | "critiques" -> `Critiques 120 + | "qualifies" -> `Qualifies 121 + | "corrects" -> `Corrects 122 + | "updates" -> `Updates 123 + | "extends" -> `Extends 124 + | "parodies" -> `Parodies 125 + | "plagiarizes" -> `Plagiarizes 126 + | "derides" -> `Derides 127 + | "ridicules" -> `Ridicules 128 + | "describes" -> `Describes 129 + | "documents" -> `Documents 130 + | "citesassourcedocument" -> `CitesAsSourceDocument 131 + | "citesasmetadatadocument" -> `CitesAsMetadataDocument 132 + | "compiles" -> `Compiles 133 + | "reviews" -> `Reviews 134 + | "retracts" -> `Retracts 135 + | "supports" -> `Supports 136 + | "givessupportto" -> `GivesSupportTo 137 + | "obtainssupportfrom" -> `ObtainsSupportFrom 138 + | "givesbackgroundto" -> `GivesBackgroundTo 139 + | "obtainsbackgroundfrom" -> `ObtainsBackgroundFrom 140 + | "speculateson" -> `SpeculatesOn 141 + | "citesaspotentialsolution" -> `CitesAsPotentialSolution 142 + | "citesasrecommendedreading" -> `CitesAsRecommendedReading 143 + | "citesasrelated" -> `CitesAsRelated 144 + | "includesquotationfrom" -> `IncludesQuotationFrom 145 + | "includesexcerptfrom" -> `IncludesExcerptFrom 146 + | "repliesto" -> `RepliesTo 147 + | "hasreplyfrom" -> `HasReplyFrom 148 + | "linksto" -> `LinksTo 149 + | "sharesauthorwith" -> `SharesAuthorWith 150 + | "sharesjournalwith" -> `SharesJournalWith 151 + | "sharespublicationvenuewith" -> `SharesPublicationVenueWith 152 + | "sharesfundingagencywith" -> `SharesFundingAgencyWith 153 + | "sharesauthorinstitutionwith" -> `SharesAuthorInstitutionWith 154 + | _ -> `Other s 155 + 156 + let equal a b = 157 + match a, b with 158 + | `Other sa, `Other sb -> sa = sb 159 + | _ -> a = b 160 + 161 + let pp ppf t = Format.fprintf ppf "%s" (to_string t)
+1 -2
lib/dune
··· 1 1 (library 2 2 (name jsonfeed) 3 3 (public_name jsonfeed) 4 - (libraries jsonm ptime fmt) 5 - (modules_without_implementation cito reference)) 4 + (libraries jsonm ptime fmt))
+32 -1
lib/jsonfeed.ml
··· 260 260 | None -> None 261 261 in 262 262 263 + let parse_reference = function 264 + | Object obj -> 265 + let url = require_string "url" obj in 266 + let doi = optional_string "doi" obj in 267 + Reference.create ~url ?doi () 268 + | _ -> raise (Invalid_feed "Reference must be an object") 269 + in 270 + 271 + let references = 272 + match optional_array "_references" obj with 273 + | Some arr -> 274 + let parsed = List.map parse_reference arr in 275 + if parsed = [] then None else Some parsed 276 + | None -> None 277 + in 278 + 263 279 Item.create ~id ~content ?url ?external_url ?title ?summary ?image 264 280 ?banner_image ?date_published ?date_modified ?authors ?tags ?language 265 - ?attachments () 281 + ?attachments ?references () 266 282 267 283 let parse_item = function 268 284 | Object obj -> parse_item_obj obj ··· 390 406 ignore (Jsonm.encode enc (`Lexeme `Oe)) 391 407 in 392 408 409 + let enc_reference ref = 410 + ignore (Jsonm.encode enc (`Lexeme `Os)); 411 + enc_field "url" (fun () -> enc_string (Reference.url ref)); 412 + enc_opt (fun doi -> enc_field "doi" (fun () -> enc_string doi)) 413 + (Reference.doi ref); 414 + enc_opt (fun cito_list -> 415 + enc_field "cito" (fun () -> 416 + enc_list (fun cito -> enc_string (Cito.to_string cito)) cito_list)) 417 + (Reference.cito ref); 418 + ignore (Jsonm.encode enc (`Lexeme `Oe)) 419 + in 420 + 393 421 let enc_hub hub = 394 422 ignore (Jsonm.encode enc (`Lexeme `Os)); 395 423 enc_field "type" (fun () -> enc_string (Hub.type_ hub)); ··· 438 466 enc_opt (fun atts -> 439 467 enc_field "attachments" (fun () -> enc_list enc_attachment atts)) 440 468 (Item.attachments item); 469 + enc_opt (fun refs -> 470 + enc_field "_references" (fun () -> enc_list enc_reference refs)) 471 + (Item.references item); 441 472 442 473 ignore (Jsonm.encode enc (`Lexeme `Oe)) 443 474 in
+20
lib/reference.ml
··· 1 + type t = { 2 + url : string; 3 + doi : string option; 4 + cito : Cito.t list option; 5 + } 6 + 7 + let create ~url ?doi ?cito () = { url; doi; cito } 8 + 9 + let url t = t.url 10 + let doi t = t.doi 11 + let cito t = t.cito 12 + 13 + let equal a b = String.equal a.url b.url 14 + 15 + let pp ppf t = 16 + let open Format in 17 + fprintf ppf "%s" t.url; 18 + match t.doi with 19 + | Some d -> fprintf ppf " [DOI: %s]" d 20 + | None -> ()