OCaml codecs for the Citation File Format (CFF)

merge

+376 -431
+161 -2
lib/cff.ml
··· 27 27 module Identifier = Cff_identifier 28 28 module Reference = Cff_reference 29 29 30 - (* Include the root type *) 31 - include Cff_root 30 + (* Root CFF type - integrated directly *) 31 + 32 + type t = { 33 + cff_version : string; 34 + message : string; 35 + title : string; 36 + authors : Cff_author.t list; 37 + abstract : string option; 38 + commit : string option; 39 + contact : Cff_author.t list option; 40 + date_released : Cff_date.t option; 41 + doi : string option; 42 + identifiers : Cff_identifier.t list option; 43 + keywords : string list option; 44 + license : Cff_license.t option; 45 + license_url : string option; 46 + preferred_citation : Cff_reference.t option; 47 + references : Cff_reference.t list option; 48 + repository : string option; 49 + repository_artifact : string option; 50 + repository_code : string option; 51 + type_ : Cff_enums.Cff_type.t option; 52 + url : string option; 53 + version : string option; 54 + } 55 + 56 + let default_cff_version = "1.2.0" 57 + let default_message = "If you use this software, please cite it using the metadata from this file." 58 + 59 + let make 60 + ?(cff_version = default_cff_version) 61 + ?(message = default_message) 62 + ~title 63 + ~authors 64 + ?abstract 65 + ?commit 66 + ?contact 67 + ?date_released 68 + ?doi 69 + ?identifiers 70 + ?keywords 71 + ?license 72 + ?license_url 73 + ?preferred_citation 74 + ?references 75 + ?repository 76 + ?repository_artifact 77 + ?repository_code 78 + ?type_ 79 + ?url 80 + ?version 81 + () = 82 + { cff_version; message; title; authors; 83 + abstract; commit; contact; date_released; doi; 84 + identifiers; keywords; license; license_url; 85 + preferred_citation; references; repository; 86 + repository_artifact; repository_code; type_; url; version } 87 + 88 + (* Required field accessors *) 89 + let cff_version t = t.cff_version 90 + let message t = t.message 91 + let title t = t.title 92 + let authors t = t.authors 93 + 94 + (* Optional field accessors *) 95 + let abstract t = t.abstract 96 + let commit t = t.commit 97 + let contact t = t.contact 98 + let date_released t = t.date_released 99 + let doi t = t.doi 100 + let identifiers t = t.identifiers 101 + let keywords t = t.keywords 102 + let license t = t.license 103 + let license_url t = t.license_url 104 + let preferred_citation t = t.preferred_citation 105 + let references t = t.references 106 + let repository t = t.repository 107 + let repository_artifact t = t.repository_artifact 108 + let repository_code t = t.repository_code 109 + let type_ t = t.type_ 110 + let url t = t.url 111 + let version t = t.version 112 + 113 + let pp ppf t = 114 + Format.fprintf ppf "@[<v>"; 115 + Format.fprintf ppf "cff-version: %s@," t.cff_version; 116 + Format.fprintf ppf "title: %s@," t.title; 117 + Format.fprintf ppf "message: %s@," t.message; 118 + Format.fprintf ppf "authors:@,"; 119 + List.iter (fun a -> Format.fprintf ppf " - %a@," Cff_author.pp a) t.authors; 120 + Option.iter (fun v -> Format.fprintf ppf "version: %s@," v) t.version; 121 + Option.iter (fun v -> Format.fprintf ppf "doi: %s@," v) t.doi; 122 + Option.iter (fun v -> Format.fprintf ppf "date-released: %a@," Cff_date.pp v) t.date_released; 123 + Option.iter (fun v -> Format.fprintf ppf "license: %a@," Cff_license.pp v) t.license; 124 + Option.iter (fun v -> Format.fprintf ppf "url: %s@," v) t.url; 125 + Option.iter (fun v -> Format.fprintf ppf "repository: %s@," v) t.repository; 126 + Option.iter (fun v -> Format.fprintf ppf "repository-code: %s@," v) t.repository_code; 127 + Option.iter (fun v -> Format.fprintf ppf "abstract: %s@," v) t.abstract; 128 + Option.iter (fun v -> Format.fprintf ppf "commit: %s@," v) t.commit; 129 + Option.iter (fun v -> Format.fprintf ppf "type: %a@," Cff_enums.Cff_type.pp v) t.type_; 130 + Option.iter (fun kws -> 131 + Format.fprintf ppf "keywords:@,"; 132 + List.iter (fun k -> Format.fprintf ppf " - %s@," k) kws 133 + ) t.keywords; 134 + Option.iter (fun ids -> 135 + Format.fprintf ppf "identifiers:@,"; 136 + List.iter (fun id -> Format.fprintf ppf " - %a@," Cff_identifier.pp id) ids 137 + ) t.identifiers; 138 + Option.iter (fun contacts -> 139 + Format.fprintf ppf "contact:@,"; 140 + List.iter (fun c -> Format.fprintf ppf " - %a@," Cff_author.pp c) contacts 141 + ) t.contact; 142 + Option.iter (fun refs -> 143 + Format.fprintf ppf "references:@,"; 144 + List.iter (fun r -> Format.fprintf ppf " - %a@," Cff_reference.pp r) refs 145 + ) t.references; 146 + Option.iter (fun pc -> 147 + Format.fprintf ppf "preferred-citation:@, %a@," Cff_reference.pp pc 148 + ) t.preferred_citation; 149 + Format.fprintf ppf "@]" 150 + 151 + let list_jsont elt = Jsont.(array elt |> map ~dec:Stdlib.Array.to_list ~enc:Stdlib.Array.of_list) 152 + 153 + let jsont = 154 + let open Jsont in 155 + let authors_jsont = list_jsont Cff_author.jsont in 156 + let identifiers_jsont = list_jsont Cff_identifier.jsont in 157 + let references_jsont = list_jsont Cff_reference.jsont in 158 + let keywords_jsont = list_jsont string in 159 + Object.map ~kind:"CFF" 160 + (fun cff_version message title authors abstract commit contact 161 + date_released doi identifiers keywords license license_url 162 + preferred_citation references repository repository_artifact 163 + repository_code type_ url version -> 164 + { cff_version; message; title; authors; 165 + abstract; commit; contact; date_released; doi; 166 + identifiers; keywords; license; license_url; 167 + preferred_citation; references; repository; 168 + repository_artifact; repository_code; type_; url; version }) 169 + |> Object.mem "cff-version" string ~enc:(fun t -> t.cff_version) 170 + |> Object.mem "message" string ~enc:(fun t -> t.message) 171 + |> Object.mem "title" string ~enc:(fun t -> t.title) 172 + |> Object.mem "authors" authors_jsont ~enc:(fun t -> t.authors) 173 + |> Object.opt_mem "abstract" string ~enc:(fun t -> t.abstract) 174 + |> Object.opt_mem "commit" string ~enc:(fun t -> t.commit) 175 + |> Object.opt_mem "contact" authors_jsont ~enc:(fun t -> t.contact) 176 + |> Object.opt_mem "date-released" Cff_date.jsont ~enc:(fun t -> t.date_released) 177 + |> Object.opt_mem "doi" string ~enc:(fun t -> t.doi) 178 + |> Object.opt_mem "identifiers" identifiers_jsont ~enc:(fun t -> t.identifiers) 179 + |> Object.opt_mem "keywords" keywords_jsont ~enc:(fun t -> t.keywords) 180 + |> Object.opt_mem "license" Cff_license.jsont_lenient ~enc:(fun t -> t.license) 181 + |> Object.opt_mem "license-url" string ~enc:(fun t -> t.license_url) 182 + |> Object.opt_mem "preferred-citation" Cff_reference.jsont ~enc:(fun t -> t.preferred_citation) 183 + |> Object.opt_mem "references" references_jsont ~enc:(fun t -> t.references) 184 + |> Object.opt_mem "repository" string ~enc:(fun t -> t.repository) 185 + |> Object.opt_mem "repository-artifact" string ~enc:(fun t -> t.repository_artifact) 186 + |> Object.opt_mem "repository-code" string ~enc:(fun t -> t.repository_code) 187 + |> Object.opt_mem "type" Cff_enums.Cff_type.jsont ~enc:(fun t -> t.type_) 188 + |> Object.opt_mem "url" string ~enc:(fun t -> t.url) 189 + |> Object.opt_mem "version" string ~enc:(fun t -> t.version) 190 + |> Object.finish
+214 -4
lib/cff.mli
··· 30 30 {[ 31 31 let author = Cff.Author.Person 32 32 (Cff.Person.make ~family_names:"Smith" ~given_names:"Jane" ()) in 33 - let cff = Cff.make_simple 33 + let cff = Cff.make 34 34 ~title:"My Research Software" 35 35 ~authors:[author] 36 36 ~version:"1.0.0" ··· 188 188 189 189 (** {1 Root CFF Type} 190 190 191 - The main [t] type represents a complete [CITATION.cff] file. It includes 192 - the {!module:Cff_root} interface with all required and optional fields. *) 191 + The main [t] type represents a complete [CITATION.cff] file with all 192 + required and optional fields from the CFF 1.2.0 specification. 193 + 194 + {2 Required Fields} 195 + 196 + Every valid CFF file must include: 197 + - {!cff_version}: Schema version (defaults to ["1.2.0"]) 198 + - {!message}: Instructions for citing the work (has sensible default) 199 + - {!title}: Name of the software or dataset 200 + - {!authors}: List of persons and/or entities 201 + 202 + {2 Common Optional Fields} 203 + 204 + - {!version}: Software version string 205 + - {!doi}: Digital Object Identifier 206 + - {!date_released}: Publication/release date 207 + - {!license}: SPDX license identifier(s) 208 + - {!keywords}: Descriptive keywords 209 + - {!abstract}: Description of the work 210 + 211 + {2 Citation Redirection} 212 + 213 + The {!preferred_citation} field allows redirecting citations to 214 + a related work (e.g., a journal article describing the software). 215 + The {!references} field lists works that the software cites or 216 + depends upon. *) 217 + 218 + (** The abstract type representing a complete CFF document. *) 219 + type t 220 + 221 + (** {1 Construction} *) 222 + 223 + val default_cff_version : string 224 + (** The default CFF version used when not specified: ["1.2.0"]. *) 225 + 226 + val default_message : string 227 + (** The default citation message: 228 + ["If you use this software, please cite it using the metadata from this file."] *) 229 + 230 + val make : 231 + ?cff_version:string -> 232 + ?message:string -> 233 + title:string -> 234 + authors:Cff_author.t list -> 235 + ?abstract:string -> 236 + ?commit:string -> 237 + ?contact:Cff_author.t list -> 238 + ?date_released:Cff_date.t -> 239 + ?doi:string -> 240 + ?identifiers:Cff_identifier.t list -> 241 + ?keywords:string list -> 242 + ?license:Cff_license.t -> 243 + ?license_url:string -> 244 + ?preferred_citation:Cff_reference.t -> 245 + ?references:Cff_reference.t list -> 246 + ?repository:string -> 247 + ?repository_artifact:string -> 248 + ?repository_code:string -> 249 + ?type_:Cff_enums.Cff_type.t -> 250 + ?url:string -> 251 + ?version:string -> 252 + unit -> t 253 + (** [make ~title ~authors ...] constructs a CFF value. 254 + 255 + @param cff_version The CFF schema version (default: {!default_cff_version}) 256 + @param message Instructions for users on how to cite (default: {!default_message}) 257 + @param title The name of the software or dataset 258 + @param authors List of persons and/or entities who created the work *) 259 + 260 + (** {1 Required Fields} *) 261 + 262 + val cff_version : t -> string 263 + (** The CFF schema version that this file adheres to. 264 + 265 + For CFF 1.2.0 files, this should be ["1.2.0"]. The version determines 266 + which keys are valid and how they should be interpreted. *) 267 + 268 + val message : t -> string 269 + (** A message to readers explaining how to cite the work. 270 + 271 + Common examples: 272 + - ["If you use this software, please cite it using the metadata from this file."] 273 + - ["Please cite this software using the metadata from 'preferred-citation'."] 274 + 275 + The message should guide users toward the preferred citation method. *) 276 + 277 + val title : t -> string 278 + (** The name of the software or dataset. 193 279 194 - include module type of Cff_root 280 + This is the title that should appear in citations. For software, it's 281 + typically the project name; for datasets, the dataset title. *) 282 + 283 + val authors : t -> Cff_author.t list 284 + (** The creators of the software or dataset. 285 + 286 + Authors can be persons (individuals) or entities (organizations). 287 + At least one author is required for a valid CFF file. The order 288 + typically reflects contribution significance. *) 289 + 290 + (** {1 Optional Fields} *) 291 + 292 + val abstract : t -> string option 293 + (** A description of the software or dataset. 294 + 295 + Provides context about what the work does, its purpose, and scope. *) 296 + 297 + val commit : t -> string option 298 + (** The commit hash or revision number of the software version. 299 + 300 + Useful for precise version identification beyond semantic versioning. 301 + Example: ["1ff847d81f29c45a3a1a5ce73d38e45c2f319bba"] *) 302 + 303 + val contact : t -> Cff_author.t list option 304 + (** Contact persons or entities for the software or dataset. 305 + 306 + May differ from authors; useful when the primary contact is a 307 + project maintainer rather than the original author. *) 308 + 309 + val date_released : t -> Cff_date.t option 310 + (** The date when the software or dataset was released. 311 + 312 + Format is [(year, month, day)], corresponding to ISO 8601 [YYYY-MM-DD]. *) 313 + 314 + val doi : t -> string option 315 + (** The Digital Object Identifier for the software or dataset. 316 + 317 + DOIs provide persistent, citable identifiers. This is a shorthand 318 + for a single DOI; use {!identifiers} for multiple DOIs or other 319 + identifier types. Example: ["10.5281/zenodo.1234567"] *) 320 + 321 + val identifiers : t -> Cff_identifier.t list option 322 + (** Additional identifiers beyond the primary DOI. 323 + 324 + Each identifier has a type (DOI, URL, SWH, other), value, and 325 + optional description. Useful for versioned DOIs, Software Heritage 326 + identifiers, or repository URLs. *) 327 + 328 + val keywords : t -> string list option 329 + (** Descriptive keywords for the work. 330 + 331 + Help with discoverability and categorization. Example: 332 + [["machine learning"; "image processing"; "python"]] *) 333 + 334 + val license : t -> Cff_license.t option 335 + (** The SPDX license identifier(s) for the work. 336 + 337 + Uses {{:https://spdx.org/licenses/}SPDX identifiers}. Multiple 338 + licenses imply an OR relationship (user may choose any). 339 + Example: ["MIT"], ["Apache-2.0"], or [["GPL-3.0-only"; "MIT"]]. *) 340 + 341 + val license_url : t -> string option 342 + (** URL to the license text for non-standard licenses. 343 + 344 + Only needed for licenses not in the SPDX list. Standard SPDX 345 + licenses have well-known URLs. *) 346 + 347 + val preferred_citation : t -> Cff_reference.t option 348 + (** A reference to cite instead of the software itself. 349 + 350 + Used for "credit redirection" when authors prefer citation of 351 + a related publication (e.g., a methods paper) over the software. 352 + Note: Software citation principles recommend citing software 353 + directly; use this field judiciously. *) 354 + 355 + val references : t -> Cff_reference.t list option 356 + (** Works that this software cites or depends upon. 357 + 358 + Functions like a bibliography, listing dependencies, foundational 359 + works, or related publications. Each reference includes full 360 + bibliographic metadata. *) 361 + 362 + val repository : t -> string option 363 + (** URL to the repository where the software is developed. 364 + 365 + Typically a version control system URL. For source code repositories, 366 + prefer {!repository_code}. *) 367 + 368 + val repository_artifact : t -> string option 369 + (** URL to the built/compiled artifact repository. 370 + 371 + For binary distributions, package registries (npm, PyPI, CRAN), 372 + or container registries. *) 373 + 374 + val repository_code : t -> string option 375 + (** URL to the source code repository. 376 + 377 + Typically a GitHub, GitLab, or similar URL where the source 378 + code is publicly accessible. *) 379 + 380 + val type_ : t -> Cff_enums.Cff_type.t option 381 + (** The type of work: [`Software] (default) or [`Dataset]. 382 + 383 + Most CFF files describe software; use [`Dataset] for data packages. *) 384 + 385 + val url : t -> string option 386 + (** The URL of the software or dataset homepage. 387 + 388 + A general landing page, documentation site, or project website. *) 389 + 390 + val version : t -> string option 391 + (** The version string of the software or dataset. 392 + 393 + Can be any version format: semantic versioning (["1.2.3"]), 394 + date-based (["2024.01"]), or other schemes. *) 395 + 396 + (** {1 Formatting and Codec} *) 397 + 398 + val pp : Format.formatter -> t -> unit 399 + (** Pretty-print a CFF value in a human-readable YAML-like format. *) 400 + 401 + val jsont : t Jsont.t 402 + (** JSON/YAML codec for serialization and deserialization. 403 + 404 + Used internally by the YAML codec functions. *)
-175
lib/cff_root.ml
··· 1 - (*--------------------------------------------------------------------------- 2 - Copyright (c) 2025 The ocaml-cff programmers. All rights reserved. 3 - SPDX-License-Identifier: ISC 4 - ---------------------------------------------------------------------------*) 5 - 6 - (** Root CFF type. *) 7 - 8 - type t = { 9 - cff_version : string; 10 - message : string; 11 - title : string; 12 - authors : Cff_author.t list; 13 - abstract : string option; 14 - commit : string option; 15 - contact : Cff_author.t list option; 16 - date_released : Cff_date.t option; 17 - doi : string option; 18 - identifiers : Cff_identifier.t list option; 19 - keywords : string list option; 20 - license : Cff_license.t option; 21 - license_url : string option; 22 - preferred_citation : Cff_reference.t option; 23 - references : Cff_reference.t list option; 24 - repository : string option; 25 - repository_artifact : string option; 26 - repository_code : string option; 27 - type_ : Cff_enums.Cff_type.t option; 28 - url : string option; 29 - version : string option; 30 - } 31 - 32 - let make 33 - ~cff_version 34 - ~message 35 - ~title 36 - ~authors 37 - ?abstract 38 - ?commit 39 - ?contact 40 - ?date_released 41 - ?doi 42 - ?identifiers 43 - ?keywords 44 - ?license 45 - ?license_url 46 - ?preferred_citation 47 - ?references 48 - ?repository 49 - ?repository_artifact 50 - ?repository_code 51 - ?type_ 52 - ?url 53 - ?version 54 - () = 55 - { cff_version; message; title; authors; 56 - abstract; commit; contact; date_released; doi; 57 - identifiers; keywords; license; license_url; 58 - preferred_citation; references; repository; 59 - repository_artifact; repository_code; type_; url; version } 60 - 61 - (* Required field accessors *) 62 - let cff_version t = t.cff_version 63 - let message t = t.message 64 - let title t = t.title 65 - let authors t = t.authors 66 - 67 - (* Optional field accessors *) 68 - let abstract t = t.abstract 69 - let commit t = t.commit 70 - let contact t = t.contact 71 - let date_released t = t.date_released 72 - let doi t = t.doi 73 - let identifiers t = t.identifiers 74 - let keywords t = t.keywords 75 - let license t = t.license 76 - let license_url t = t.license_url 77 - let preferred_citation t = t.preferred_citation 78 - let references t = t.references 79 - let repository t = t.repository 80 - let repository_artifact t = t.repository_artifact 81 - let repository_code t = t.repository_code 82 - let type_ t = t.type_ 83 - let url t = t.url 84 - let version t = t.version 85 - 86 - let make_simple ~title ~authors ?version ?doi ?license () = 87 - let message = "If you use this software, please cite it using the metadata from this file." in 88 - make 89 - ~cff_version:"1.2.0" 90 - ~message 91 - ~title 92 - ~authors 93 - ?version 94 - ?doi 95 - ?license 96 - () 97 - 98 - let pp ppf t = 99 - Format.fprintf ppf "@[<v>"; 100 - Format.fprintf ppf "cff-version: %s@," t.cff_version; 101 - Format.fprintf ppf "title: %s@," t.title; 102 - Format.fprintf ppf "message: %s@," t.message; 103 - Format.fprintf ppf "authors:@,"; 104 - List.iter (fun a -> Format.fprintf ppf " - %a@," Cff_author.pp a) t.authors; 105 - Option.iter (fun v -> Format.fprintf ppf "version: %s@," v) t.version; 106 - Option.iter (fun v -> Format.fprintf ppf "doi: %s@," v) t.doi; 107 - Option.iter (fun v -> Format.fprintf ppf "date-released: %a@," Cff_date.pp v) t.date_released; 108 - Option.iter (fun v -> Format.fprintf ppf "license: %a@," Cff_license.pp v) t.license; 109 - Option.iter (fun v -> Format.fprintf ppf "url: %s@," v) t.url; 110 - Option.iter (fun v -> Format.fprintf ppf "repository: %s@," v) t.repository; 111 - Option.iter (fun v -> Format.fprintf ppf "repository-code: %s@," v) t.repository_code; 112 - Option.iter (fun v -> Format.fprintf ppf "abstract: %s@," v) t.abstract; 113 - Option.iter (fun v -> Format.fprintf ppf "commit: %s@," v) t.commit; 114 - Option.iter (fun v -> Format.fprintf ppf "type: %a@," Cff_enums.Cff_type.pp v) t.type_; 115 - Option.iter (fun kws -> 116 - Format.fprintf ppf "keywords:@,"; 117 - List.iter (fun k -> Format.fprintf ppf " - %s@," k) kws 118 - ) t.keywords; 119 - Option.iter (fun ids -> 120 - Format.fprintf ppf "identifiers:@,"; 121 - List.iter (fun id -> Format.fprintf ppf " - %a@," Cff_identifier.pp id) ids 122 - ) t.identifiers; 123 - Option.iter (fun contacts -> 124 - Format.fprintf ppf "contact:@,"; 125 - List.iter (fun c -> Format.fprintf ppf " - %a@," Cff_author.pp c) contacts 126 - ) t.contact; 127 - Option.iter (fun refs -> 128 - Format.fprintf ppf "references:@,"; 129 - List.iter (fun r -> Format.fprintf ppf " - %a@," Cff_reference.pp r) refs 130 - ) t.references; 131 - Option.iter (fun pc -> 132 - Format.fprintf ppf "preferred-citation:@, %a@," Cff_reference.pp pc 133 - ) t.preferred_citation; 134 - Format.fprintf ppf "@]" 135 - 136 - let list_jsont elt = Jsont.(array elt |> map ~dec:Stdlib.Array.to_list ~enc:Stdlib.Array.of_list) 137 - 138 - let jsont = 139 - let open Jsont in 140 - let authors_jsont = list_jsont Cff_author.jsont in 141 - let identifiers_jsont = list_jsont Cff_identifier.jsont in 142 - let references_jsont = list_jsont Cff_reference.jsont in 143 - let keywords_jsont = list_jsont string in 144 - Object.map ~kind:"CFF" 145 - (fun cff_version message title authors abstract commit contact 146 - date_released doi identifiers keywords license license_url 147 - preferred_citation references repository repository_artifact 148 - repository_code type_ url version -> 149 - { cff_version; message; title; authors; 150 - abstract; commit; contact; date_released; doi; 151 - identifiers; keywords; license; license_url; 152 - preferred_citation; references; repository; 153 - repository_artifact; repository_code; type_; url; version }) 154 - |> Object.mem "cff-version" string ~enc:(fun t -> t.cff_version) 155 - |> Object.mem "message" string ~enc:(fun t -> t.message) 156 - |> Object.mem "title" string ~enc:(fun t -> t.title) 157 - |> Object.mem "authors" authors_jsont ~enc:(fun t -> t.authors) 158 - |> Object.opt_mem "abstract" string ~enc:(fun t -> t.abstract) 159 - |> Object.opt_mem "commit" string ~enc:(fun t -> t.commit) 160 - |> Object.opt_mem "contact" authors_jsont ~enc:(fun t -> t.contact) 161 - |> Object.opt_mem "date-released" Cff_date.jsont ~enc:(fun t -> t.date_released) 162 - |> Object.opt_mem "doi" string ~enc:(fun t -> t.doi) 163 - |> Object.opt_mem "identifiers" identifiers_jsont ~enc:(fun t -> t.identifiers) 164 - |> Object.opt_mem "keywords" keywords_jsont ~enc:(fun t -> t.keywords) 165 - |> Object.opt_mem "license" Cff_license.jsont_lenient ~enc:(fun t -> t.license) 166 - |> Object.opt_mem "license-url" string ~enc:(fun t -> t.license_url) 167 - |> Object.opt_mem "preferred-citation" Cff_reference.jsont ~enc:(fun t -> t.preferred_citation) 168 - |> Object.opt_mem "references" references_jsont ~enc:(fun t -> t.references) 169 - |> Object.opt_mem "repository" string ~enc:(fun t -> t.repository) 170 - |> Object.opt_mem "repository-artifact" string ~enc:(fun t -> t.repository_artifact) 171 - |> Object.opt_mem "repository-code" string ~enc:(fun t -> t.repository_code) 172 - |> Object.opt_mem "type" Cff_enums.Cff_type.jsont ~enc:(fun t -> t.type_) 173 - |> Object.opt_mem "url" string ~enc:(fun t -> t.url) 174 - |> Object.opt_mem "version" string ~enc:(fun t -> t.version) 175 - |> Object.finish
-249
lib/cff_root.mli
··· 1 - (*--------------------------------------------------------------------------- 2 - Copyright (c) 2025 The ocaml-cff programmers. All rights reserved. 3 - SPDX-License-Identifier: ISC 4 - ---------------------------------------------------------------------------*) 5 - 6 - (** Root CFF type representing a complete [CITATION.cff] file. 7 - 8 - A [CITATION.cff] file is the standard way to provide citation metadata 9 - for research software and datasets. This module defines the root type 10 - containing all top-level fields from the CFF 1.2.0 specification. 11 - 12 - {2 Required Fields} 13 - 14 - Every valid CFF file must include: 15 - - {!cff_version}: Schema version (["1.2.0"]) 16 - - {!message}: Instructions for citing the work 17 - - {!title}: Name of the software or dataset 18 - - {!authors}: List of persons and/or entities 19 - 20 - {2 Common Optional Fields} 21 - 22 - - {!version}: Software version string 23 - - {!doi}: Digital Object Identifier 24 - - {!date_released}: Publication/release date 25 - - {!license}: SPDX license identifier(s) 26 - - {!keywords}: Descriptive keywords 27 - - {!abstract}: Description of the work 28 - 29 - {2 Citation Redirection} 30 - 31 - The {!preferred_citation} field allows redirecting citations to 32 - a related work (e.g., a journal article describing the software). 33 - The {!references} field lists works that the software cites or 34 - depends upon. 35 - 36 - {2 Example} 37 - 38 - {[ 39 - let cff = Cff_root.make 40 - ~cff_version:"1.2.0" 41 - ~message:"If you use this software, please cite it as below." 42 - ~title:"My Research Software" 43 - ~authors:[Cff_author.Person (Cff_author.Person.make 44 - ~family_names:"Smith" 45 - ~given_names:"Jane" 46 - ())] 47 - ~version:"1.0.0" 48 - ~doi:"10.5281/zenodo.1234567" 49 - ~date_released:(2024, 1, 15) 50 - ~license:(Cff_license.single "MIT") 51 - () 52 - ]} *) 53 - 54 - (** The abstract type representing a complete CFF document. *) 55 - type t 56 - 57 - (** {1 Construction} *) 58 - 59 - val make : 60 - cff_version:string -> 61 - message:string -> 62 - title:string -> 63 - authors:Cff_author.t list -> 64 - ?abstract:string -> 65 - ?commit:string -> 66 - ?contact:Cff_author.t list -> 67 - ?date_released:Cff_date.t -> 68 - ?doi:string -> 69 - ?identifiers:Cff_identifier.t list -> 70 - ?keywords:string list -> 71 - ?license:Cff_license.t -> 72 - ?license_url:string -> 73 - ?preferred_citation:Cff_reference.t -> 74 - ?references:Cff_reference.t list -> 75 - ?repository:string -> 76 - ?repository_artifact:string -> 77 - ?repository_code:string -> 78 - ?type_:Cff_enums.Cff_type.t -> 79 - ?url:string -> 80 - ?version:string -> 81 - unit -> t 82 - (** [make ~cff_version ~message ~title ~authors ...] constructs a CFF value. 83 - 84 - @param cff_version The CFF schema version, typically ["1.2.0"] 85 - @param message Instructions for users on how to cite the work 86 - @param title The name of the software or dataset 87 - @param authors List of persons and/or entities who created the work *) 88 - 89 - (** {1 Required Fields} *) 90 - 91 - val cff_version : t -> string 92 - (** The CFF schema version that this file adheres to. 93 - 94 - For CFF 1.2.0 files, this should be ["1.2.0"]. The version determines 95 - which keys are valid and how they should be interpreted. *) 96 - 97 - val message : t -> string 98 - (** A message to readers explaining how to cite the work. 99 - 100 - Common examples: 101 - - ["If you use this software, please cite it using the metadata from this file."] 102 - - ["Please cite this software using the metadata from 'preferred-citation'."] 103 - 104 - The message should guide users toward the preferred citation method. *) 105 - 106 - val title : t -> string 107 - (** The name of the software or dataset. 108 - 109 - This is the title that should appear in citations. For software, it's 110 - typically the project name; for datasets, the dataset title. *) 111 - 112 - val authors : t -> Cff_author.t list 113 - (** The creators of the software or dataset. 114 - 115 - Authors can be persons (individuals) or entities (organizations). 116 - At least one author is required for a valid CFF file. The order 117 - typically reflects contribution significance. *) 118 - 119 - (** {1 Optional Fields} *) 120 - 121 - val abstract : t -> string option 122 - (** A description of the software or dataset. 123 - 124 - Provides context about what the work does, its purpose, and scope. *) 125 - 126 - val commit : t -> string option 127 - (** The commit hash or revision number of the software version. 128 - 129 - Useful for precise version identification beyond semantic versioning. 130 - Example: ["1ff847d81f29c45a3a1a5ce73d38e45c2f319bba"] *) 131 - 132 - val contact : t -> Cff_author.t list option 133 - (** Contact persons or entities for the software or dataset. 134 - 135 - May differ from authors; useful when the primary contact is a 136 - project maintainer rather than the original author. *) 137 - 138 - val date_released : t -> Cff_date.t option 139 - (** The date when the software or dataset was released. 140 - 141 - Format is [(year, month, day)], corresponding to ISO 8601 [YYYY-MM-DD]. *) 142 - 143 - val doi : t -> string option 144 - (** The Digital Object Identifier for the software or dataset. 145 - 146 - DOIs provide persistent, citable identifiers. This is a shorthand 147 - for a single DOI; use {!identifiers} for multiple DOIs or other 148 - identifier types. Example: ["10.5281/zenodo.1234567"] *) 149 - 150 - val identifiers : t -> Cff_identifier.t list option 151 - (** Additional identifiers beyond the primary DOI. 152 - 153 - Each identifier has a type (DOI, URL, SWH, other), value, and 154 - optional description. Useful for versioned DOIs, Software Heritage 155 - identifiers, or repository URLs. *) 156 - 157 - val keywords : t -> string list option 158 - (** Descriptive keywords for the work. 159 - 160 - Help with discoverability and categorization. Example: 161 - [["machine learning"; "image processing"; "python"]] *) 162 - 163 - val license : t -> Cff_license.t option 164 - (** The SPDX license identifier(s) for the work. 165 - 166 - Uses {{:https://spdx.org/licenses/}SPDX identifiers}. Multiple 167 - licenses imply an OR relationship (user may choose any). 168 - Example: ["MIT"], ["Apache-2.0"], or [["GPL-3.0-only"; "MIT"]]. *) 169 - 170 - val license_url : t -> string option 171 - (** URL to the license text for non-standard licenses. 172 - 173 - Only needed for licenses not in the SPDX list. Standard SPDX 174 - licenses have well-known URLs. *) 175 - 176 - val preferred_citation : t -> Cff_reference.t option 177 - (** A reference to cite instead of the software itself. 178 - 179 - Used for "credit redirection" when authors prefer citation of 180 - a related publication (e.g., a methods paper) over the software. 181 - Note: Software citation principles recommend citing software 182 - directly; use this field judiciously. *) 183 - 184 - val references : t -> Cff_reference.t list option 185 - (** Works that this software cites or depends upon. 186 - 187 - Functions like a bibliography, listing dependencies, foundational 188 - works, or related publications. Each reference includes full 189 - bibliographic metadata. *) 190 - 191 - val repository : t -> string option 192 - (** URL to the repository where the software is developed. 193 - 194 - Typically a version control system URL. For source code repositories, 195 - prefer {!repository_code}. *) 196 - 197 - val repository_artifact : t -> string option 198 - (** URL to the built/compiled artifact repository. 199 - 200 - For binary distributions, package registries (npm, PyPI, CRAN), 201 - or container registries. *) 202 - 203 - val repository_code : t -> string option 204 - (** URL to the source code repository. 205 - 206 - Typically a GitHub, GitLab, or similar URL where the source 207 - code is publicly accessible. *) 208 - 209 - val type_ : t -> Cff_enums.Cff_type.t option 210 - (** The type of work: [`Software] (default) or [`Dataset]. 211 - 212 - Most CFF files describe software; use [`Dataset] for data packages. *) 213 - 214 - val url : t -> string option 215 - (** The URL of the software or dataset homepage. 216 - 217 - A general landing page, documentation site, or project website. *) 218 - 219 - val version : t -> string option 220 - (** The version string of the software or dataset. 221 - 222 - Can be any version format: semantic versioning (["1.2.3"]), 223 - date-based (["2024.01"]), or other schemes. *) 224 - 225 - (** {1 Convenience Constructors} *) 226 - 227 - val make_simple : 228 - title:string -> 229 - authors:Cff_author.t list -> 230 - ?version:string -> 231 - ?doi:string -> 232 - ?license:Cff_license.t -> 233 - unit -> t 234 - (** Create a minimal CFF with sensible defaults. 235 - 236 - Uses [cff_version = "1.2.0"] and the standard message: 237 - ["If you use this software, please cite it using the metadata from this file."] 238 - 239 - This is the quickest way to create a valid CFF for simple projects. *) 240 - 241 - (** {1 Formatting and Codec} *) 242 - 243 - val pp : Format.formatter -> t -> unit 244 - (** Pretty-print a CFF value in a human-readable YAML-like format. *) 245 - 246 - val jsont : t Jsont.t 247 - (** JSON/YAML codec for serialization and deserialization. 248 - 249 - Used internally by the YAML codec functions. *)
+1 -1
test/test_cff.ml
··· 53 53 let test_create_programmatic () = 54 54 let author = Cff.Author.Person 55 55 (Cff.Person.make ~family_names:"Smith" ~given_names:"Jane" ()) in 56 - let cff = Cff.make_simple 56 + let cff = Cff.make 57 57 ~title:"My Software" 58 58 ~authors:[author] 59 59 ~version:"1.0.0"