(*--------------------------------------------------------------------------- Copyright (c) 2026 The ocaml-cff programmers. All rights reserved. SPDX-License-Identifier: ISC ---------------------------------------------------------------------------*) (** Bibliographic reference type for CFF. References represent citable works in the [references] and [preferred-citation] fields of a CFF file. They can describe any type of scholarly output: journal articles, books, conference papers, software, datasets, theses, patents, and many more. {1 Structure} CFF references have 60+ possible fields. This module organizes them into logical sub-records for easier manipulation: - {!Core} - Required fields: type, title, authors - {!Publication} - Journal articles: journal, volume, issue, pages - {!Collection} - Book chapters, proceedings: collection title, DOI - {!Dates} - When the work was published, accessed, etc. - {!Identifiers} - DOI, URL, ISBN, ISSN, repository links - {!Entities} - Editors, publisher, institution, conference - {!Metadata} - Keywords, license, languages, copyright - {!Technical} - Software-specific: commit, version, format {1 Reference Types} The [type] field determines what kind of work is being referenced. CFF 1.2.0 supports 40+ types including: - Academic: [`Article], [`Book], [`Conference_paper], [`Thesis] - Software: [`Software], [`Software_code], [`Software_container] - Data: [`Data], [`Database], [`Dataset] - Legal: [`Patent], [`Legal_case], [`Statute] - Media: [`Video], [`Sound_recording], [`Film_broadcast] {1 Example} {[ (* A journal article reference *) let article = Cff_reference.make_simple ~type_:`Article ~title:"The Software Citation Principles" ~authors:[ Cff_author.Person (Cff_author.Person.make ~family_names:"Smith" ~given_names:"Arfon M." ()); ] ~doi:"10.7717/peerj-cs.86" ~year:2016 ~journal:"PeerJ Computer Science" () (* A software reference with more details *) let core = Cff_reference.Core.make ~type_:`Software ~title:"NumPy" ~authors:[...] () in let dates = Cff_reference.Dates.make ~year:2020 () in let ids = Cff_reference.Identifiers.make ~doi:"10.1038/s41586-020-2649-2" ~url:"https://numpy.org" () in let software = Cff_reference.make ~core ~dates ~identifiers:ids () ]} {1 Sub-records} *) (** Core identity fields (required for all references). Every reference must have a type, title, and at least one author. The type determines what additional fields are relevant. *) module Core : sig type t (** Create a core record. @param type_ The reference type (article, book, software, etc.) @param title The title of the work @param authors List of persons and/or entities *) val make : type_:Cff_enums.Reference_type.t -> title:string -> authors:Cff_author.t list -> ?abstract:string -> ?abbreviation:string -> unit -> t (** The reference type. Determines which other fields are applicable. *) val type_ : t -> Cff_enums.Reference_type.t (** The title of the referenced work. *) val title : t -> string (** The authors/creators of the work. *) val authors : t -> Cff_author.t list (** A description or abstract of the work. *) val abstract : t -> string option (** Abbreviated form of the title (e.g., for journal names). *) val abbreviation : t -> string option val pp : Format.formatter -> t -> unit end (** Publication metadata for journal articles and periodicals. Fields for works published in journals, magazines, or other serial publications. Page numbers can be specified as a range ([pages]) or as separate [start] and [end_] values. *) module Publication : sig type t (** Empty publication record with all fields as [None]. *) val empty : t val make : ?journal:string -> ?volume:string -> ?issue:string -> ?pages:string -> ?start:string -> ?end_:string -> ?edition:string -> ?section:string -> ?status:Cff_enums.Status.t -> unit -> t (** The name of the journal or magazine. *) val journal : t -> string option (** The volume number of the journal. *) val volume : t -> string option (** The issue number within the volume. *) val issue : t -> string option (** Page range (e.g., ["123-145"]). Alternative to [start]/[end_]. *) val pages : t -> string option (** Starting page number. *) val start : t -> string option (** Ending page number. *) val end_ : t -> string option (** The edition of the work (e.g., ["2nd edition"]). *) val edition : t -> string option (** The section of a work (e.g., newspaper section). *) val section : t -> string option (** Publication status: preprint, in-press, submitted, etc. *) val status : t -> Cff_enums.Status.t option (** [true] if all fields are [None]. *) val is_empty : t -> bool end (** Collection metadata for works in edited volumes. Used for book chapters, conference proceedings, and other works that appear within a larger collection. *) module Collection : sig type t val empty : t val make : ?collection_title:string -> ?collection_type:string -> ?collection_doi:string -> ?volume_title:string -> ?number_volumes:string -> unit -> t (** Title of the collection (proceedings, book series, etc.). *) val collection_title : t -> string option (** Type of collection (e.g., ["proceedings"], ["book series"]). *) val collection_type : t -> string option (** DOI of the collection itself (not the individual work). *) val collection_doi : t -> string option (** Title of the specific volume within a multi-volume collection. *) val volume_title : t -> string option (** Total number of volumes in the collection. *) val number_volumes : t -> string option val is_empty : t -> bool end (** Date-related fields. CFF distinguishes between several date types: - {b date-released}: When the software/dataset was released - {b date-published}: When the work was formally published - {b date-accessed}: When an online resource was last accessed - {b date-downloaded}: When a resource was downloaded For older works or when only the year is known, use [year] instead of a full date. *) module Dates : sig type t val empty : t val make : ?date_accessed:Cff_date.t -> ?date_downloaded:Cff_date.t -> ?date_published:Cff_date.t -> ?date_released:Cff_date.t -> ?year:int -> ?year_original:int -> ?month:int -> ?issue_date:string -> unit -> t (** Date when an online resource was accessed for citation. *) val date_accessed : t -> Cff_date.t option (** Date when a resource was downloaded. *) val date_downloaded : t -> Cff_date.t option (** Formal publication date. *) val date_published : t -> Cff_date.t option (** Release date (typically for software). *) val date_released : t -> Cff_date.t option (** Publication year when full date is unknown. *) val year : t -> int option (** Year of original publication (for reprints, translations). *) val year_original : t -> int option (** Publication month (1-12) when only month/year is known. *) val month : t -> int option (** Issue date as a string (for periodicals with specific dates). *) val issue_date : t -> string option val is_empty : t -> bool end (** Identifiers and repository links. Various identifier schemes for locating and citing works: - DOI: Digital Object Identifier (preferred for academic works) - URL: Web address - ISBN: International Standard Book Number - ISSN: International Standard Serial Number (journals) - PMCID: PubMed Central ID - NIHMSID: NIH Manuscript Submission ID *) module Identifiers : sig type t val empty : t val make : ?doi:string -> ?url:string -> ?repository:string -> ?repository_code:string -> ?repository_artifact:string -> ?isbn:string -> ?issn:string -> ?pmcid:string -> ?nihmsid:string -> ?identifiers:Cff_identifier.t list -> unit -> t (** Digital Object Identifier (e.g., ["10.1234/example"]). *) val doi : t -> string option (** URL where the work can be accessed. *) val url : t -> string option (** General repository URL. *) val repository : t -> string option (** Source code repository (GitHub, GitLab, etc.). *) val repository_code : t -> string option (** Built artifact repository (npm, PyPI, Docker Hub, etc.). *) val repository_artifact : t -> string option (** International Standard Book Number. *) val isbn : t -> string option (** International Standard Serial Number (for journals). *) val issn : t -> string option (** PubMed Central identifier. *) val pmcid : t -> string option (** NIH Manuscript Submission System identifier. *) val nihmsid : t -> string option (** Additional typed identifiers (DOI, URL, SWH, other). *) val identifiers : t -> Cff_identifier.t list option val is_empty : t -> bool end (** Related entities: editors, publishers, institutions. Persons and organizations involved in the work beyond the authors: - Editors of collections or journals - Publishers and their locations - Academic institutions (for theses, reports) - Conferences (for proceedings, presentations) *) module Entities : sig type t val empty : t val make : ?editors:Cff_author.t list -> ?editors_series:Cff_author.t list -> ?translators:Cff_author.t list -> ?recipients:Cff_author.t list -> ?senders:Cff_author.t list -> ?contact:Cff_author.t list -> ?publisher:Cff_author.Entity.t -> ?institution:Cff_author.Entity.t -> ?conference:Cff_author.Entity.t -> ?database_provider:Cff_author.Entity.t -> ?location:Cff_author.Entity.t -> unit -> t (** Editors of the work (for edited volumes). *) val editors : t -> Cff_author.t list option (** Series editors (for book series). *) val editors_series : t -> Cff_author.t list option (** Translators of the work. *) val translators : t -> Cff_author.t list option (** Recipients (for personal communications). *) val recipients : t -> Cff_author.t list option (** Senders (for personal communications). *) val senders : t -> Cff_author.t list option (** Contact persons for the work. *) val contact : t -> Cff_author.t list option (** Publishing organization. *) val publisher : t -> Cff_author.Entity.t option (** Academic/research institution (for theses, reports). *) val institution : t -> Cff_author.Entity.t option (** Conference where the work was presented. *) val conference : t -> Cff_author.Entity.t option (** Provider of a database (for data references). *) val database_provider : t -> Cff_author.Entity.t option (** Location entity (city, venue for conferences). *) val location : t -> Cff_author.Entity.t option val is_empty : t -> bool end (** Descriptive metadata: keywords, license, notes. Additional information about the work for discovery and rights. *) module Metadata : sig type t val empty : t val make : ?keywords:string list -> ?languages:string list -> ?license:Cff_license.t -> ?copyright:string -> ?scope:string -> ?notes:string -> unit -> t (** Descriptive keywords for the work. *) val keywords : t -> string list option (** Languages the work is available in (ISO 639 codes). *) val languages : t -> string list option (** SPDX license identifier(s), or unknown license with optional URL. *) val license : t -> Cff_license.t option (** Copyright statement. *) val copyright : t -> string option (** Scope of the reference (what aspect it covers). *) val scope : t -> string option (** Additional notes or comments. *) val notes : t -> string option val is_empty : t -> bool end (** Technical and domain-specific fields. Fields for software, data, and specialized reference types: - Software: commit hash, version, filename - Theses: thesis type, department - Data: data type, database, format - Patents: patent states - Dictionaries/encyclopedias: term, entry *) module Technical : sig type t val empty : t val make : ?commit:string -> ?version:string -> ?filename:string -> ?format:string -> ?medium:string -> ?data_type:string -> ?database:string -> ?number:string -> ?patent_states:string list -> ?thesis_type:string -> ?term:string -> ?entry:string -> ?department:string -> ?loc_start:string -> ?loc_end:string -> unit -> t (** Git commit hash or VCS revision. *) val commit : t -> string option (** Version string of the software/data. *) val version : t -> string option (** Name of the file being referenced. *) val filename : t -> string option (** Format of the work (e.g., ["PDF"], ["HTML"]). *) val format : t -> string option (** Physical medium (e.g., ["CD-ROM"], ["print"]). *) val medium : t -> string option (** Type of data (for datasets). *) val data_type : t -> string option (** Name of the database. *) val database : t -> string option (** Report/patent/standard number. *) val number : t -> string option (** Countries where a patent is held. *) val patent_states : t -> string list option (** Type of thesis (["PhD"], ["Master's"], etc.). *) val thesis_type : t -> string option (** Dictionary/encyclopedia term being referenced. *) val term : t -> string option (** Encyclopedia entry name. *) val entry : t -> string option (** Academic department (for theses). *) val department : t -> string option (** Starting line/location in source code. *) val loc_start : t -> string option (** Ending line/location in source code. *) val loc_end : t -> string option val is_empty : t -> bool end (** {1 Reference Type} *) (** The complete reference type combining all sub-records. *) type t (** Construct a reference from sub-records. Only [core] is required; other sub-records default to empty. *) val make : core:Core.t -> ?publication:Publication.t -> ?collection:Collection.t -> ?dates:Dates.t -> ?identifiers:Identifiers.t -> ?entities:Entities.t -> ?metadata:Metadata.t -> ?technical:Technical.t -> unit -> t (** Convenience constructor for simple references. Creates a reference with just the most common fields. Suitable for quick article or software references. *) val make_simple : type_:Cff_enums.Reference_type.t -> title:string -> authors:Cff_author.t list -> ?doi:string -> ?year:int -> ?journal:string -> unit -> t (** {2 Sub-record Accessors} *) (** The core identity fields. *) val core : t -> Core.t (** Publication metadata (journal, volume, pages). *) val publication : t -> Publication.t (** Collection metadata (proceedings, book series). *) val collection : t -> Collection.t (** Date-related fields. *) val dates : t -> Dates.t (** Identifiers and links. *) val identifiers : t -> Identifiers.t (** Related entities (editors, publisher). *) val entities : t -> Entities.t (** Descriptive metadata (keywords, license). *) val metadata : t -> Metadata.t (** Technical fields (commit, version, format). *) val technical : t -> Technical.t (** {2 Direct Accessors for Common Fields} Convenience accessors that delegate to sub-records. *) (** Shortcut for [Core.type_ (core t)]. *) val type_ : t -> Cff_enums.Reference_type.t (** Shortcut for [Core.title (core t)]. *) val title : t -> string (** Shortcut for [Core.authors (core t)]. *) val authors : t -> Cff_author.t list (** Shortcut for [Identifiers.doi (identifiers t)]. *) val doi : t -> string option (** Shortcut for [Dates.year (dates t)]. *) val year : t -> int option (** {1 Formatting and Codec} *) (** Pretty-print a reference in a human-readable format. *) val pp : Format.formatter -> t -> unit (** JSON/YAML codec for serialization. *) val jsont : t Jsont.t