1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
// This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. // // Copyright © 2018 Corporation for Digital Scholarship use super::attr::GetAttribute; use super::error::*; use super::version::Features; #[derive(Debug, Eq, Copy, Clone, PartialEq, EnumProperty)] pub enum AnyVariable { Ordinary(Variable), Name(NameVariable), Date(DateVariable), Number(NumberVariable), } impl GetAttribute for AnyVariable { fn get_attr(s: &str, features: &Features) -> Result<Self, UnknownAttributeValue> { use self::AnyVariable::*; if let Ok(v) = Variable::get_attr(s, features) { return Ok(Ordinary(v)); } else if let Ok(v) = NameVariable::get_attr(s, features) { return Ok(Name(v)); } else if let Ok(v) = DateVariable::get_attr(s, features) { return Ok(Date(v)); } else if let Ok(v) = NumberVariable::get_attr(s, features) { return Ok(Number(v)); } Err(UnknownAttributeValue::new(s)) } } /// Contrary to the CSL-M spec's declaration that number variables in a regular `<text variable>` /// "should fail validation", that is perfectly valid, because "number variables are a subset of the /// standard variables": /// [Spec](https://docs.citationstyles.org/en/stable/specification.html#number-variables) #[derive(Debug, Eq, Copy, Clone, PartialEq)] pub enum StandardVariable { Ordinary(Variable), Number(NumberVariable), } impl GetAttribute for StandardVariable { fn get_attr(s: &str, features: &Features) -> Result<Self, UnknownAttributeValue> { use self::StandardVariable::*; if let Ok(v) = Variable::get_attr(s, features) { return Ok(Ordinary(v)); } else if let Ok(v) = NumberVariable::get_attr(s, features) { return Ok(Number(v)); } Err(UnknownAttributeValue::new(s)) } } #[derive(AsRefStr, EnumProperty, EnumString, Debug, Copy, Clone, PartialEq, Eq, Hash)] #[strum(serialize_all = "kebab_case")] pub enum Variable { /// abstract of the item (e.g. the abstract of a journal article) Abstract, /// reader’s notes about the item content Annote, /// archive storing the item Archive, /// storage location within an archive (e.g. a box and folder number) /// technically the spec says use an underscore, but that's probably a typo. #[strum(serialize = "archive_location", serialize = "archive-location")] ArchiveLocation, /// geographic location of the archive, ArchivePlace, /// issuing or judicial authority (e.g. “USPTO” for a patent, “Fairfax Circuit Court” for a legal case) /// CSL-M only #[strum(props(csl = "1", cslM = "0"))] Authority, /// active={true} call number (to locate the item in a library) CallNumber, /// label identifying the item in in-text citations of label styles (e.g. “Ferr78”). May be assigned by the CSL processor based on item metadata. CitationLabel, /// title of the collection holding the item (e.g. the series title for a book) CollectionTitle, /// title of the container holding the item (e.g. the book title for a book chapter, the journal title for a journal article) ContainerTitle, /// short/abbreviated form of “container-title” (also accessible through the “short” form of the “container-title” variable) ContainerTitleShort, /// physical (e.g. size) or temporal (e.g. running time) dimensions of the item Dimensions, /// Digital Object Identifier (e.g. “10.1128/AEM.02591-07”) #[strum(serialize = "DOI")] DOI, /// name of the related event (e.g. the conference name when citing a conference paper) Event, /// geographic location of the related event (e.g. “Amsterdam, the Netherlands”) EventPlace, /// class, type or genre of the item (e.g. “adventure” for an adventure movie, “PhD dissertation” for a PhD thesis) Genre, /// International Standard Book Number #[strum(serialize = "ISBN")] ISBN, /// International Standard Serial Number #[strum(serialize = "ISSN")] ISSN, /// geographic scope of relevance (e.g. “US” for a US patent) Jurisdiction, /// keyword(s) or tag(s) attached to the item Keyword, /// medium description (e.g. “CD”, “DVD”, etc.) Medium, /// (short) inline note giving additional item details (e.g. a concise summary or commentary) Note, /// original publisher, for items that have been republished by a different publisher OriginalPublisher, /// geographic location of the original publisher (e.g. “London, UK”) OriginalPublisherPlace, /// title of the original version (e.g. “Война и мир”, the untranslated Russian title of “War and Peace”) OriginalTitle, /// PubMed Central reference number #[strum(serialize = "PMCID")] PMCID, /// PubMed reference number #[strum(serialize = "PMID")] PMID, /// publisher Publisher, /// geographic location of the publisher PublisherPlace, /// resources related to the procedural history of a legal case References, /// title of the item reviewed by the current item ReviewedTitle, /// scale of e.g. a map Scale, /// container section holding the item (e.g. “politics” for a newspaper article). /// TODO: CSL-M appears to interpret this as a number variable? Section, /// from whence the item originates (e.g. a library catalog or database) Source, /// (publication) status of the item (e.g. “forthcoming”) Status, /// primary title of the item Title, /// short/abbreviated form of “title” (also accessible through the “short” form of the “title” variable) TitleShort, /// URL (e.g. “https://aem.asm.org/cgi/content/full/74/9/2766”) #[strum(serialize = "URL")] URL, /// version of the item (e.g. “2.0.9” for a software program) Version, /// disambiguating year suffix in author-date styles (e.g. “a” in “Doe, 1999a”) YearSuffix, /// CSL-M only // Intercept Hereinafter at CiteContext, as it isn't known at Reference-time. // Global-per-document config should be its own thing separate from references. // TODO: delete any noRef="true" and replace with serde directives not to read from // CSL-JSON. #[strum(props(csl = "0", cslM = "1", noRef = "true"))] Hereinafter, /// CSL-M only #[strum(props(csl = "0", cslM = "1"))] Dummy, /// CSL-M only #[strum(props(csl = "0", cslM = "1"))] LocatorExtra, /// CSL-M only #[strum(props(csl = "0", cslM = "1"))] VolumeTitle, /// CSL-M only /// /// Not documented in the CSL-M spec. #[strum(props(csl = "0", cslM = "1"))] Committee, /// CSL-M only /// /// Not documented in the CSL-M spec. See [Indigo Book][ib] section 'R26. Short Form /// Citation for Court Documents' for its intended use case, and the Juris-M [US cheat /// sheet][uscs] /// /// [uscs]: https://juris-m.github.io/cheat-sheets/us.pdf /// /// [ib]: https://law.resource.org/pub/us/code/blue/IndigoBook.html #[strum(props(csl = "0", cslM = "1"))] DocumentName, /// CSL-M only /// /// Not documented in the CSL-M spec. /// /// TODO: I think variable="gazette-flag" may have been superseded by type="gazette", /// but clearly you can still tick the "Gazette Ref" checkbox in Juris-M on a statute. /// Ask Frank. See also https://juris-m.github.io/cheat-sheets/us.pdf #[strum(props(csl = "0", cslM = "1"))] GazetteFlag, // TODO: should not be accessible in condition blocks Language, } impl Variable { pub fn should_replace_hyphens(self) -> bool { false } pub fn hyperlink(self, value: &str) -> Option<&str> { match self { Variable::URL => Some(value), Variable::DOI => Some(value), _ => None, } } } #[derive(AsRefStr, EnumProperty, EnumString, Debug, Copy, Clone, PartialEq, Eq, Hash)] #[strum(serialize_all = "kebab_case")] pub enum NumberVariable { ChapterNumber, CollectionNumber, Edition, Issue, Number, NumberOfPages, NumberOfVolumes, Volume, /// Locator, Page and PageFirst, FRRN, and CiteNumber: These are technically meant to be standard variables in CSL 1.0.1, but the spec /// requires us to treat them as numerics for `<label plural="contextual">` anyway. /// /// a cite-specific pinpointer within the item (e.g. a page number within a book, or a volume in a multi-volume work). Must be accompanied in the input data by a label indicating the locator type (see the Locators term list), which determines which term is rendered by cs:label when the “locator” variable is selected. Locator, /// range of pages the item (e.g. a journal article) covers in a container (e.g. a journal issue) Page, /// first page of the range of pages the item (e.g. a journal article) covers in a container (e.g. a journal issue) PageFirst, /// number of a preceding note containing the first reference to the item. Assigned by the CSL processor. The variable holds no value for non-note-based styles, or when the item hasn’t been cited in any preceding notes. FirstReferenceNoteNumber, /// index (starting at 1) of the cited reference in the bibliography (generated by the CSL processor) CitationNumber, /// CSL-M only #[strum(props(csl = "0", cslM = "1"))] PublicationNumber, /// CSL-M only #[strum(props(csl = "0", cslM = "1"))] Supplement, /// CSL-M only #[strum(props(csl = "0", cslM = "1"))] Authority, } impl NumberVariable { pub fn should_replace_hyphens(self) -> bool { self == NumberVariable::Locator } } #[derive(AsRefStr, EnumProperty, EnumString, Debug, Copy, Clone, PartialEq, Eq, Hash)] #[strum(serialize_all = "kebab_case")] pub enum NameVariable { /// author Author, /// editor of the collection holding the item (e.g. the series editor for a book) CollectionEditor, /// composer (e.g. of a musical score) Composer, /// author of the container holding the item (e.g. the book author for a book chapter) ContainerAuthor, /// director (e.g. of a film) Director, /// editor Editor, /// managing editor (“Directeur de la Publication” in French) EditorialDirector, /// illustrator (e.g. of a children’s book) Illustrator, /// interviewer (e.g. of an interview) Interviewer, /// ? OriginalAuthor, /// recipient (e.g. of a letter) Recipient, /// author of the item reviewed by the current item ReviewedAuthor, /// translator Translator, /// CSL-M only #[strum(props(csl = "0", cslM = "1"))] Authority, /// CSL-M only /// /// The dummy name variable is always empty. Use it to force all name variables called through /// a cs:names node to render through cs:substitute, and so suppress whichever is chosen for /// rendering to be suppressed through the remainder of the current cite. #[strum(props(csl = "0", cslM = "1"))] Dummy, } #[derive(AsRefStr, EnumProperty, EnumString, Debug, Copy, Clone, PartialEq, Eq, Hash)] #[strum(serialize_all = "kebab_case")] pub enum DateVariable { /// date the item has been accessed Accessed, /// ? Container, /// date the related event took place EventDate, /// date the item was issued/published Issued, /// (issue) date of the original version OriginalDate, /// date the item (e.g. a manuscript) has been submitted for publication Submitted, /// CSL-M only #[strum(props(csl = "0", cslM = "1"))] LocatorDate, /// CSL-M only #[strum(props(csl = "0", cslM = "1"))] PublicationDate, /// CSL-M only #[strum(props(csl = "0", cslM = "1"))] AvailableDate, }