citeworks_csl/
items.rs

1//! Types and utilities for bibliography items.
2
3use std::collections::BTreeMap;
4
5use serde::{Deserialize, Serialize};
6
7use crate::{dates::Date, names::Name, ordinaries::OrdinaryValue};
8
9/// An item carries the details of a single unique bibliographic resource.
10///
11/// The set of fields that an item may have is determined by the item type; in
12/// this library this is not checked: known fields have their field type defined
13/// and checked, but unrecognised fields are not errors when deserialised and
14/// go in the generic `fields` map.
15#[derive(Debug, Default, Clone, Hash, Eq, PartialEq, Serialize, Deserialize)]
16#[serde(rename_all = "kebab-case")]
17pub struct Item {
18	/// Unique ID of this item within the CSL document.
19	pub id: String,
20
21	/// Type of the resource.
22	#[serde(rename = "type")]
23	pub item_type: ItemType,
24
25	/// Author(s).
26	#[serde(default, skip_serializing_if = "Vec::is_empty")]
27	pub author: Vec<Name>,
28
29	/// Contributor(s) to the item.
30	#[serde(default, skip_serializing_if = "Vec::is_empty")]
31	pub contributor: Vec<Name>,
32
33	/// Date the item was issued on.
34	#[serde(default, skip_serializing_if = "Option::is_none")]
35	pub issued: Option<Date>,
36
37	/// Date the item was last updated.
38	#[serde(default, skip_serializing_if = "Option::is_none")]
39	pub updated: Option<Date>,
40
41	/// Date the item was published on.
42	#[serde(default, skip_serializing_if = "Option::is_none")]
43	pub published: Option<Date>,
44
45	/// Date the item was accessed (for citations).
46	#[serde(default, skip_serializing_if = "Option::is_none")]
47	pub accessed: Option<Date>,
48
49	/// Category (scientific field or type of study)
50	#[serde(default, skip_serializing_if = "Option::is_none")]
51	pub category: Option<OrdinaryValue>,
52
53	/// ISSN.
54	#[serde(default, skip_serializing_if = "Option::is_none", rename = "ISSN")]
55	pub issn: Option<OrdinaryValue>,
56
57	/// EISSN.
58	#[serde(default, skip_serializing_if = "Option::is_none", rename = "EISSN")]
59	pub eissn: Option<OrdinaryValue>,
60
61	/// ISSNL.
62	#[serde(default, skip_serializing_if = "Option::is_none", rename = "ISSNL")]
63	pub issnl: Option<OrdinaryValue>,
64
65	/// DOI.
66	#[serde(default, skip_serializing_if = "Option::is_none", rename = "DOI")]
67	pub doi: Option<OrdinaryValue>,
68
69	/// URL.
70	#[serde(default, skip_serializing_if = "Option::is_none", rename = "URL")]
71	pub url: Option<OrdinaryValue>,
72
73	/// Title.
74	#[serde(default, skip_serializing_if = "Option::is_none")]
75	pub title: Option<OrdinaryValue>,
76
77	/// Short title.
78	#[serde(default, skip_serializing_if = "Option::is_none")]
79	pub title_short: Option<OrdinaryValue>,
80
81	/// Summary.
82	#[serde(default, skip_serializing_if = "Option::is_none")]
83	pub summary: Option<OrdinaryValue>,
84
85	/// Abstract.
86	#[serde(default, skip_serializing_if = "Option::is_none", rename = "abstract")]
87	pub abstract_text: Option<OrdinaryValue>,
88
89	/// Name of the issuing publication.
90	#[serde(default, skip_serializing_if = "Option::is_none")]
91	pub container_title: Option<OrdinaryValue>,
92
93	/// Abbreviated name of the issuing publication.
94	///
95	/// This has non-standard casing: `journalAbbreviation`.
96	#[serde(
97		default,
98		skip_serializing_if = "Option::is_none",
99		rename = "journalAbbreviation"
100	)]
101	pub journal_abbrevation: Option<OrdinaryValue>,
102
103	/// Volume number of the issuing publication.
104	///
105	/// This can be a numerical value but is often a string of a number.
106	#[serde(default, skip_serializing_if = "Option::is_none")]
107	pub volume: Option<OrdinaryValue>,
108
109	/// Issue number of the issuing publication.
110	///
111	/// This can be a numerical value but is often a string of a number.
112	#[serde(default, skip_serializing_if = "Option::is_none")]
113	pub issue: Option<OrdinaryValue>,
114
115	/// Page number or page range in the issuing publication.
116	///
117	/// This can be a numerical value but is often a string of a number, or of
118	/// the range in `N-M` format.
119	#[serde(default, skip_serializing_if = "Option::is_none")]
120	pub page: Option<OrdinaryValue>,
121
122	/// Language code.
123	#[serde(default, skip_serializing_if = "Option::is_none")]
124	pub language: Option<OrdinaryValue>,
125
126	/// Plain source name.
127	#[serde(default, skip_serializing_if = "Option::is_none")]
128	pub source: Option<OrdinaryValue>,
129
130	/// Copyright statement.
131	#[serde(default, skip_serializing_if = "Option::is_none")]
132	pub rights: Option<OrdinaryValue>,
133
134	/// License statement.
135	///
136	/// Sometimes used as a synonym of `rights` rather than actual licensing.
137	#[serde(default, skip_serializing_if = "Option::is_none")]
138	pub license: Option<OrdinaryValue>,
139
140	/// Note for extra details that are important to include in the citation but
141	/// don't have a standard field.
142	///
143	/// May be structured or semi-structured data, but as there is no convention
144	/// processors shouldn't make assumptions unless they can assert meaning.
145	#[serde(default, skip_serializing_if = "Option::is_none")]
146	pub note: Option<OrdinaryValue>,
147
148	/// Any field that is not directly supported by name.
149	#[serde(flatten)]
150	pub fields: BTreeMap<String, ItemValue>,
151}
152
153/// Any of the possible value types of an item's fields.
154#[derive(Debug, Clone, Hash, Eq, PartialEq, Serialize, Deserialize)]
155#[serde(untagged)]
156pub enum ItemValue {
157	/// Ordinary fields containing string or numeric values.
158	///
159	/// In ordinary fields, the processor recognizes a limited set of [HTML-like
160	/// tags][html-tags] for visual formatting.
161	///
162	/// One common ordinary field is `title`, which identifies the title of the
163	/// citation item.
164	///
165	/// [html-tags]: https://citeproc-js.readthedocs.io/en/latest/csl-json/markup.html#html-like-formatting-tags
166	Ordinary(OrdinaryValue),
167
168	/// Date fields containing dates or ranges of dates.
169	///
170	/// A date field is a complex field that expresses a date or a range of
171	/// dates, for example `issued`, which identifies the date an item was
172	/// issued or published.
173	Date(Date),
174
175	/// Names fields containing lists of names.
176	///
177	/// A names field is a complex field that lists persons as authors,
178	/// contributors, or creators, etc. Each field is an array of objects, with
179	/// each object containing information about one person.
180	Names(Vec<Name>),
181}
182
183/// The type of the bibliographic resource.
184#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Serialize, Deserialize)]
185#[serde(rename_all = "kebab-case")]
186#[allow(missing_docs)]
187pub enum ItemType {
188	// CSL
189	Article,
190	ArticleJournal,
191	ArticleMagazine,
192	ArticleNewspaper,
193	Bill,
194	Book,
195	Broadcast,
196	Chapter,
197	Classic,
198	Collection,
199	Dataset,
200	Document,
201	Entry,
202	EntryDictionary,
203	EntryEncyclopedia,
204	Figure,
205	Graphic,
206	Hearing,
207	Interview,
208	LegalCase,
209	Legislation,
210	Manuscript,
211	Map,
212	MotionPicture,
213	MusicalScore,
214	Pamphlet,
215	PaperConference,
216	Patent,
217	Performance,
218	Periodical,
219	PersonalCommunication,
220	Post,
221	PostWeblog,
222	Regulation,
223	Report,
224	Review,
225	ReviewBook,
226	Software,
227	Song,
228	Speech,
229	Standard,
230	Thesis,
231	Treaty,
232	Webpage,
233
234	// CSL-M additional types
235	Gazette,
236	Video,
237	LegalCommentary,
238}
239
240impl Default for ItemType {
241	fn default() -> Self {
242		Self::Article
243	}
244}