diff --git a/.github/workflows/check-full.yaml b/.github/workflows/check-full.yaml index f0008bef..a1077e05 100644 --- a/.github/workflows/check-full.yaml +++ b/.github/workflows/check-full.yaml @@ -27,16 +27,14 @@ jobs: config: - {os: windows-latest, r: 'devel'} - {os: windows-latest, r: 'release'} - # - {os: windows-latest, r: 'oldrel'} + - {os: windows-latest, r: 'oldrel'} - {os: macOS-latest, r: 'devel'} - {os: macOS-latest, r: 'release'} - #- {os: macOS-latest, r: 'oldrel'} + - {os: macOS-latest, r: 'oldrel'} - {os: ubuntu-latest, r: 'release'} - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} - #- {os: ubuntu-latest, r: 'oldrel'} - #- {os: ubuntu-latest, r: 'oldrel-2'} - #- {os: ubuntu-latest, r: '3.6'} - + - {os: ubuntu-latest, r: 'oldrel'} + - {os: ubuntu-latest, r: 'oldrel-2'} env: GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} diff --git a/.lintr b/.lintr index d4708be9..add4d27e 100644 --- a/.lintr +++ b/.lintr @@ -1,3 +1,8 @@ linters: linters_with_defaults() # see vignette("lintr") encoding: "UTF-8" -exclusions: list("data-raw") +exclusions: list( + "data-raw", + "tests/testthat/test_ci/test-full_cff.R", + "vignettes/cffr.Rmd", + "vignettes/bibtex_cff.Rmd" + ) diff --git a/CITATION.cff b/CITATION.cff index ae2c7213..f6be3074 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -10,9 +10,9 @@ license: GPL-3.0-or-later title: 'cffr: Generate Citation File Format (''cff'') Metadata for R Packages' version: 0.5.0.9000 doi: 10.21105/joss.03900 -abstract: The Citation File Format version 1.2.0 is a - human and machine readable file format which provides citation metadata for software. - This package provides core utilities to generate and validate this metadata. +abstract: The Citation File Format version 1.2.0 + is a human and machine readable file format which provides citation metadata for + software. This package provides core utilities to generate and validate this metadata. authors: - family-names: Hernangómez given-names: Diego @@ -96,7 +96,7 @@ references: name: R Foundation for Statistical Computing address: Vienna, Austria year: '2024' - version: '>= 3.6.0' + version: '>= 4.0.0' - type: software title: cli abstract: 'cli: Helpers for Developing Command Line Interfaces' diff --git a/DESCRIPTION b/DESCRIPTION index b3eae1d3..fd4613e1 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -17,7 +17,7 @@ License: GPL (>= 3) URL: https://docs.ropensci.org/cffr/, https://github.com/ropensci/cffr BugReports: https://github.com/ropensci/cffr/issues Depends: - R (>= 3.6.0) + R (>= 4.0.0) Imports: cli (>= 2.0.0), desc (>= 1.3.0), diff --git a/NAMESPACE b/NAMESPACE index 16d8f1c6..259686bd 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,8 +1,23 @@ # Generated by roxygen2: do not edit by hand +S3method("[",cff_pers_list) +S3method("[",cff_ref_list) +S3method(as.data.frame,cff) +S3method(as.person,cff) +S3method(as_cff,Bibtex) +S3method(as_cff,bibentry) +S3method(as_cff,default) +S3method(as_cff,list) +S3method(as_cff,person) S3method(c,cff) +S3method(head,cff) S3method(print,cff) +S3method(tail,cff) +S3method(toBibtex,cff) export(as.cff) +export(as_bibentry) +export(as_cff) +export(as_cff_person) export(cff) export(cff_create) export(cff_extract_to_bibtex) @@ -10,19 +25,26 @@ export(cff_from_bibtex) export(cff_gha_update) export(cff_git_hook_install) export(cff_git_hook_remove) +export(cff_modify) export(cff_parse_citation) export(cff_parse_person) export(cff_parse_person_bibtex) export(cff_read) +export(cff_read_bib) +export(cff_read_bib_text) +export(cff_read_cff_citation) +export(cff_read_citation) +export(cff_read_description) export(cff_schema_definitions_entity) export(cff_schema_definitions_person) export(cff_schema_definitions_refs) export(cff_schema_keys) export(cff_schema_keys_license) -export(cff_to_bibentry) export(cff_to_bibtex) export(cff_validate) export(cff_write) +export(cff_write_bib) +export(cff_write_citation) export(encoded_utf_to_latex) export(write_bib) export(write_citation) @@ -33,9 +55,11 @@ importFrom(utils,bibentry) importFrom(utils,capture.output) importFrom(utils,citation) importFrom(utils,download.file) +importFrom(utils,head) importFrom(utils,installed.packages) importFrom(utils,modifyList) importFrom(utils,packageDescription) importFrom(utils,person) importFrom(utils,read.csv) +importFrom(utils,tail) importFrom(utils,toBibtex) diff --git a/NEWS.md b/NEWS.md index fe67541a..1b4080bc 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,16 +1,78 @@ # cffr (development version) -## Major changes in the API - +This is a major release with some notable changes. The change mainly **affects +to non-core functions**, hence the natural workflow (`cff_create()` → +`cff_write()` → `cff_validate()`) shouldn't be affected. + +## Major changes + +### API + +The API has been completely reviewed to provide more clarity on functions naming +and to facilitate internal maintenance. This change **only** **affects to +non-core functions**. Now each function does less things but does it better. The +old API [has been +deprecated](https://lifecycle.r-lib.org/articles/stages.html#deprecated) and it +would warn when used, providing advice on the replacement function. + +#### Deprecation + +- `cff_to_bibtex()` and `cff_extract_to_bibtex()`: replaced by + `as_bibentry()`. +- `cff_from_bibtex()`: replaced by `cff_read_bib()` (for `*.bib` files) and + `cff_read_bib_text()` (for character strings). +- `write_bib()` and `write_citation()` : replaced by `cff_write_bib()` and + `cff_write_citation()` respectively. +- `cff_parse_person()` and `cff_parse_person_bibtex()`: replaced by + `as_cff_person()`. - The conversion from `cff` to `bibentry` is performed now by a new function - `cff_to_bibentry()`. Previous names of this function were `cff_to_bibtex()` - and `cff_extract_to_bibtex()` that are now superseded. - -## Changes on bibtex crosswalk - -- **\@inbook** and **\@book** gains a new value on [CFF]{.underline} when - **series** is provided: [collection-type: book-series.]{.underline} -- Review and update `vignette("bibtex_cff", package = "cffr")`. + `as_bibentry()`. Previous names of this function were `cff_to_bibtex()` and + `cff_extract_to_bibtex()` that are now deprecated. +- `cff_parse_citation()`: replaced by `as_cff()`, see **New capabilities**. +- Argument `path` in `cff()` is also deprecated, use `cff_read()`. + +### New capabilities + +- New `as_cff()` S3 generic method (replacing `as.cff()`): This method coerces + **R** objects to `cff-class` format. Current methods provided are: + - `as_cff.Bibtex()`. + - `as_cff.bibentry()`, replacing cff_parse_citation(). + - `as_cff.person()`, similar to `as_cff_person()` but only for `person` + objects. We recommend using `as_cff_person()` since it can parse also + string representing authors in BibTeX markup (`"{von Neumen}, James"`), + that can't be captured properly via methods. +- Now reading from external files is performed exclusively by `cff_read()` + (that is designed to fit all supported file types on a single entry point) + and the new specific readers (that are used under the hood by `cff_read()`), + namely: + - `cff_read_cff_citation()`, + - `cff_read_description()`, + - `cff_read_citation()` + - `cff_read_bib()`. +- New `cff_modify()` function for updating and modifying `cff` objects easily. + +## Other changes + +- Minimum **R** version required now is **4.0.0**. +- Now `class()` of `cff` objects are `c("cff", "list")` instead of single + value (`"cff"`). +- New S3 **base** and **utils** methods added: + - `as.data.frame.cff().` + - `as.person.cff()`, that provides results **only** for CFF keys defined + as + [person](https://github.com/citation-file-format/citation-file-format/blob/main/schema-guide.md#definitionsperson) + or + [entity](https://github.com/citation-file-format/citation-file-format/blob/main/schema-guide.md#definitionsentity) + (e.g. `authors`, `contacts`, `editors`, `publisher,` etc.). + - `head.cff()`, `tail.cff()`. + - `toBibtex.cff()`. +- Update of BibTeX crosswalk (see `vignette("bibtex_cff", package = "cffr")`) + and consequently changes in the mapping performed by `as_bibtex()` + `cff_parse_citation()`: + - **\@inbook** and **\@book** gains a new value on [CFF]{.underline} when + **series** is provided: [collection-type: book-series.]{.underline} + - Can handle BibLaTeX **\@inbook**, that differs significantly from BibTeX + **\@inbook**. # cffr 0.5.0 @@ -27,7 +89,7 @@ ## Enhancements - Additional authors of a **R** package can be now included based on the role - on the DESCRIPTION file, via the parameter `authors_roles` (#49). + on the `DESCRIPTION` file, via the parameter `authors_roles` (#49). - New message interface based on [**cli**](https://cli.r-lib.org/) capabilities. @@ -55,7 +117,7 @@ # cffr 0.3.0 -- `preferred-citation` is only produced when a CITATION (**R**) file has been +- `preferred-citation` is only produced when a `CITATION` **R** file has been provided with the package (#37). - Improve email handling on authors. - Add `cff_read()` function. This functionality was already implemented on @@ -72,7 +134,6 @@ # cffr 0.2.1 - GitHub Action now runs only on `master` or `main`branch. - - Better handling of references # cffr 0.2.0 @@ -80,31 +141,22 @@ - Now **cffr** extracts also information of the package dependencies and adds the main citation of the dependencies to the `references` field, using `citation(auto = TRUE)`. - - New `dependencies` parameter on `cff_create()` and `cff_write()`. - - Other improvements on `cff_parse_citation():` - - `cff_parse_citation()` extracts more information of authors, based on - the fields provided on the DESCRIPTION file. - + the fields provided on the `DESCRIPTION` file. - `cff_parse_citation()` does a better job extracting information from `bibentry()` /BibTeX and mapping it to `preferred-citation/references` fields of CFF. - - Add new functions for working with git pre-commit hooks [![Experimental](https://lifecycle.r-lib.org/articles/figures/lifecycle-experimental.svg)](https://lifecycle.r-lib.org/articles/stages.html#experimental): - - `cff_git_hook_install()` - `cff_git_hook_remove()` - - New BibTeX functions: - - `cff_extract_to_bibtex()` - `cff_to_bibtex()` - `cff_parse_person_bibtex()` - `write_bib()` - - Add a new dependency: `lifecycle`. # cffr 0.1.1 @@ -121,16 +173,16 @@ # cffr 0.0.2 -- `cffr` is part now of rOpenSci. +- **cffr** is part now of rOpenSci. - Update on docs and README. - Add fuzzy match on `keys` parameter. - New dataset: `cran_to_spdx`. - Add DOI - Citation of installed packages extracted using `citation().` -- Auto-generating `preferred-citation` key from DESCRIPTION. +- Auto-generating `preferred-citation` key from `DESCRIPTION`. - Rename `cff_schema_definitions_reference()` to `cff_schema_definitions_refs()`. -- "repository" key is supported. +- `repository` key is supported. - Added vignette: `vignette("crosswalk", package = "cffr")`. - Add support to Bioconductor packages. - New function: `cff_gha_update()`. diff --git a/R/cff_to_bibentry.R b/R/as_bibentry.R similarity index 71% rename from R/cff_to_bibentry.R rename to R/as_bibentry.R index c44fe704..3274ad20 100644 --- a/R/cff_to_bibentry.R +++ b/R/as_bibentry.R @@ -1,16 +1,25 @@ -#' Create BibTeX entries from several sources +#' Create `bibentry` objects from several sources #' +#' @rdname as_bibentry +#' @name as_bibentry +#' @order 1 + #' @description #' -#' This function creates [bibentry()] objects -#' from different metadata sources (`cff` objects, `DESCRIPTION` files, etc.). +#' This function creates `bibentry` objects (see [utils::bibentry()]) from +#' different metadata sources (`cff` objects, `DESCRIPTION` files, etc.). Note +#' that a **R** `bibentry` object is the representation of a BibTeX entry, +#' see **Examples** +#' #' The function tries to map the information of the source `x` into a `cff` #' object and performs a mapping of the metadata to BibTeX, according to #' `vignette("bibtex_cff", "cffr")`. #' -#' Note that a **R** [bibentry()] object is the representation of a BibTeX -#' entry, see **Examples**. +#' The inverse transformation (`bibentry` object to `cff` reference) can +#' be done with the corresponding [as_cff()] method. #' +#' @seealso +#' [utils::bibentry()] #' #' @references #' - Patashnik, Oren. "BIBTEXTING" February 1988. @@ -20,7 +29,7 @@ #' *Ruby CFF Library (Version 0.9.0)* (Computer software). #' \doi{10.5281/zenodo.1184077}. #' -#' - Hernangómez D (2022). "BibTeX and CFF, a potential crosswalk." +#' - Hernangomez D (2022). "BibTeX and CFF, a potential crosswalk." #' *The cffr package, Vignettes*. \doi{10.21105/joss.03900}, #' . #' @@ -39,14 +48,14 @@ #' - `all`: A combination of the previous two options. This would extract #' both the preferred citation info and the references. #' -#' @family BibTeX helpers +#' @family bibtex +#' @family coercing #' -#' @return A `bibentry` object or a list of `bibentry` objects. This could -#' be parsed to BibTeX using [toBibtex()] +#' @return +#' `as_bibentry()` returns s `bibentry` object (or a list of `bibentry` +#' objects). #' #' @export -#' @name cff_to_bibentry -#' @rdname cff_to_bibentry #' #' @examples #' \donttest{ @@ -56,7 +65,7 @@ #' cff_object #' #' # bibentry object -#' bib <- cff_to_bibentry(cff_object) +#' bib <- as_bibentry(cff_object) #' #' class(bib) #' @@ -66,16 +75,20 @@ #' #' toBibtex(bib) #' +#' # Thanks to the S3 Method we can also do +#' +#' toBibtex(cff_object) +#' #' # From a CITATION.cff file with options #' #' path <- system.file("examples/CITATION_complete.cff", package = "cffr") -#' cff_file <- cff_to_bibentry(path, what = "all") +#' cff_file <- as_bibentry(path, what = "all") #' #' toBibtex(cff_file) #' #' # For an installed package #' -#' installed_package <- cff_to_bibentry("jsonvalidate") +#' installed_package <- as_bibentry("jsonvalidate") #' #' toBibtex(installed_package) #' @@ -83,19 +96,19 @@ #' # Use a DESCRIPTION file #' #' path2 <- system.file("examples/DESCRIPTION_gitlab", package = "cffr") -#' desc_file <- cff_to_bibentry(path2) +#' desc_file <- as_bibentry(path2) #' #' toBibtex(desc_file) #' } -cff_to_bibentry <- function(x, - what = c("preferred", "references", "all")) { +as_bibentry <- function(x, + what = c("preferred", "references", "all")) { what <- match.arg(what) if (is.null(x)) { return(NULL) } if (is_cff_file(x)) { - x <- cff_read(x) + x <- cff_read_cff_citation(x) } if (is_cff(x)) { @@ -103,60 +116,55 @@ cff_to_bibentry <- function(x, } else { obj <- cff_create(x) } - if (what == "preferred") { - return(cff_bibtex_parser(obj)) - } - if (what == "references") { - if (is.null(obj$references)) { - return(NULL) - } - ref <- lapply(obj$references, cff_bibtex_parser) - return(do.call(c, ref)) - } + # Guess case + cff_type <- guess_cff_part(obj) - pref <- cff_bibtex_parser(obj) + if (cff_type == "cff_full") { + # Try to generate preferred if not present + if (!("preferred-citation" %in% names(obj))) { + prefcit <- obj + prefcit$type <- "generic" + prefcit <- prefcit[names(prefcit) %in% cff_schema_definitions_refs()] + prefcit <- new_cff(prefcit) + # And add to the object + obj$`preferred-citation` <- prefcit + } - if (!is.null(obj$references)) { - ref <- lapply(obj$references, cff_bibtex_parser) - ref <- do.call(c, ref) - return(c(pref, ref)) + # Select type to extract + obj_extract <- switch(what, + "preferred" = list(obj$`preferred-citation`), + "references" = obj$references, + c(list(obj$`preferred-citation`), obj$references) + ) + } else if (cff_type == "cff_ref") { + obj_extract <- list(obj) + } else { + obj_extract <- obj } - return(pref) -} - -#' @export -#' @rdname cff_to_bibentry -#' @usage NULL -cff_to_bibtex <- cff_to_bibentry - -cff_bibtex_parser <- function(x) { - if (is.null(x)) { + # Cleanup + obj_extract <- obj_extract[lengths(obj_extract) > 0] + if (length(obj_extract) == 0) { return(NULL) } - stopifnotcff(x) + ref <- lapply(obj_extract, make_bibentry) + ref <- do.call(c, ref) - # Read cff of CITATION.cff file - if (!is_cff(x)) { - x <- cff(x) - } + return(ref) +} - # Try to generate preferred if not present - if (!("preferred-citation" %in% names(x))) { - origtype <- clean_str(x$type) - if (is.null(origtype)) { - x$type <- "misc" - } - } else { - x <- x$`preferred-citation` +make_bibentry <- function(x) { + if (is.null(x)) { + return(NULL) } # Partially based on ruby parser - # https://github.com/citation-file-format/ruby-cff/blob/main/lib/cff/formatter/bibtex_formatter.rb + # https://github.com/citation-file-format/ruby-cff/blob/main/lib/cff/ >> + # (cont) formatter/bibtex_formatter.rb # Create a initial empty list @@ -166,94 +174,13 @@ cff_bibtex_parser <- function(x) { # edition institution journal month number pages publisher title volume year # Guess type of entry---- - tobibentry$bibtype <- switch(tolower(x$type), - "article" = "article", - "book" = "book", - "manual" = "manual", - "unpublished" = "unpublished", - "conference" = "inproceedings", - "conference-paper" = "inproceedings", - "proceedings" = "proceedings", - "magazine-article" = "article", - "newspaper-article" = "article", - "pamphlet" = "booklet", - "report" = "techreport", - "thesis" = "mastersthesis", - # We would need to guess - "misc" - ) - # Try guess thesis - ttype <- clean_str(gsub("[[:punct:]]", "", - x$`thesis-type`, - perl = TRUE - )) - - if (!is.null(ttype) && x$type == "thesis") { - if (grepl("Phd", ttype, ignore.case = TRUE)) { - tobibentry$bibtype <- "phdthesis" - } - } - - # Check if it may be an incollection - # Hint: is misc with collection-title and publisher - - if (all( - tobibentry$bibtype == "misc", !is.null(x$`collection-title`), - !is.null(x$publisher), !is.null(x$year) - )) { - tobibentry$bibtype <- "incollection" - } - + tobibentry$bibtype <- guess_bibtype(x) # address---- - # BibTeX 'address' is taken from the publisher (book, others) or the - # conference (inproceedings). - # Set logic: conference > institution > publisher - if (!is.null(x$conference)) { - addr_search <- x$conference - } else if (!is.null(x$institution)) { - addr_search <- x$institution - } else { - addr_search <- x$publisher - } - - - tobibentry$address <- clean_str(paste( - c( - addr_search$address, - addr_search$city, - addr_search$region, - addr_search$country - ), - collapse = ", " - )) - - # As a fallback, use also location - if (is.null(tobibentry$address) && !is.null(x$location)) { - tobibentry$address <- x$location$name - } - - + tobibentry$address <- guess_address(x) # author---- - aut <- x$authors - - author <- lapply(aut, function(y) { - if ("name" %in% names(y)) { - # Person protected on family - person(family = clean_str(y$name)) - } else { - person( - given = clean_str(y$`given-names`), - family = clean_str(paste( - clean_str(y$`name-particle`), - clean_str(y$`family-names`), - clean_str(y$`name-suffix`) - )) - ) - } - }) - tobibentry$author <- do.call(c, author) + tobibentry$author <- as.person(x$authors) # booktitle ---- @@ -265,7 +192,10 @@ cff_bibtex_parser <- function(x) { # Fallback to conference name - if (tobibentry$bibtype == "inproceedings" && is.null(tobibentry$booktitle)) { + if (all( + tobibentry$bibtype == "inproceedings", + is.null(tobibentry$booktitle) + )) { tobibentry$booktitle <- x$conference$name } @@ -277,40 +207,10 @@ cff_bibtex_parser <- function(x) { # editor---- # Same case than authors - editors <- x["editors"][[1]] - - if (!is.null(editors)) { - # Same - editor <- lapply(editors, function(y) { - if (!is.null(y$name)) { - # Person protected on family - person(family = clean_str(y$name)) - } else { - person( - given = clean_str(y$`given-names`), - family = clean_str(paste( - clean_str(y$`name-particle`), - clean_str(y$`family-names`), - clean_str(y$`name-suffix`) - )) - ) - } - }) - tobibentry$editor <- do.call(c, editor) - } + tobibentry$editor <- as.person(x$editors) # howpublished---- - - howpublished <- x$medium - - if (!is.null(howpublished)) { - # Capitalize first letter - letts <- unlist(strsplit(howpublished, "|")) - howpublished <- - clean_str(paste0(c(toupper(letts[1]), letts[-1]), collapse = "")) - - tobibentry$howpublished <- howpublished - } + tobibentry$howpublished <- make_howpublised(x) # institution/organization ---- @@ -321,6 +221,7 @@ cff_bibtex_parser <- function(x) { "inproceedings", "proceedings", "manual" )) { + # Just name tobibentry$organization <- x$institution$name } else { tobibentry$institution <- x$institution$name @@ -335,28 +236,6 @@ cff_bibtex_parser <- function(x) { # journal---- tobibentry$journal <- x$journal - # key First two given of author and year---- - aut_sur <- lapply(tobibentry$author$family[1:2], clean_str) - aut_sur <- tolower(paste0(unlist(aut_sur), collapse = "")) - aut_sur <- gsub("\\s*", "", aut_sur) - - # Try hard to remove accents - # First with iconv - aut_sur <- iconv(aut_sur, - from = "UTF-8", to = "ASCII//TRANSLIT", - sub = "?" - ) - - # Next to latex - aut_sur <- encoded_utf_to_latex(aut_sur) - - # Finally keep only a-z letters for key - aut_sur <- gsub("[^_a-z]", "", aut_sur) - - y <- x$year - - tobibentry$key <- paste(c(aut_sur, y), collapse = ":") - # month---- m <- x$month @@ -433,11 +312,6 @@ cff_bibtex_parser <- function(x) { tobibentry$year <- substr(x$`date-released`, 1, 4) } - # Inform - if (is.null(tobibentry$year)) { - msg <- paste0("Entry {.val {tobibentry$key}} does not have {.field year} ") - cli::cli_alert_info(msg) - } # Keywords if (!is.null(x$keywords)) { @@ -453,6 +327,10 @@ cff_bibtex_parser <- function(x) { tobibentry$bibtype <- "inbook" } + # key: First two given of author and year---- + tobibentry$key <- make_bibkey(tobibentry) + + # Handle anonymous author---- # If anonymous and not needed, then not use it @@ -481,6 +359,7 @@ cff_bibtex_parser <- function(x) { tobibentry$urldate <- x$`date-accessed` tobibentry$version <- x$version # Translators + trns <- x$translators trnsbib <- lapply(trns, function(y) { @@ -502,10 +381,6 @@ cff_bibtex_parser <- function(x) { tobibentry$translator <- paste(unlist(trnsbib), collapse = " and ") - - - - # sort ---- # based on default by # https://flamingtempura.github.io/bibtex-tidy/ @@ -519,17 +394,146 @@ cff_bibtex_parser <- function(x) { sorted <- unique[unique %in% names(tobibentry)] tobibentry <- tobibentry[sorted] - bib <- do.call(bibentry, tobibentry) + bib <- try(do.call(bibentry, tobibentry), silent = TRUE) - # Shouldn't happen but just in case - # nocov start + # If key missing if (inherits(bib, "try-error")) { message <- attributes(bib)$condition$message - cli::cli_alert_danger(paste("Can't convert to {.fn bibentry}: ", message)) - cli::cli_alert_info("Returning {.val NULL}") + cli::cli_alert_danger(paste("Can't convert to {.fn bibentry}: ")) + cli::cli_alert_info(message) + cli::cli_alert_warning("Returning {.val NULL}") return(NULL) } - # nocov end + + # Unlist easy to undo the do.call effect + bib <- bib[[1]] return(bib) } + + +guess_bibtype <- function(x) { + init_guess <- switch(tolower(x$type), + "article" = "article", + "book" = "book", + "manual" = "manual", + "unpublished" = "unpublished", + "conference" = "inproceedings", + "conference-paper" = "inproceedings", + "proceedings" = "proceedings", + "magazine-article" = "article", + "newspaper-article" = "article", + "pamphlet" = "booklet", + "report" = "techreport", + "thesis" = "mastersthesis", + # We would need to guess + "misc" + ) + + + # Try guess thesis + ttype <- clean_str(gsub("[[:punct:]]", "", + x$`thesis-type`, + perl = TRUE + )) + + if (!is.null(ttype) && x$type == "thesis") { + if (grepl("Phd", ttype, ignore.case = TRUE)) { + init_guess <- "phdthesis" + } + } + + # Check if it may be an incollection + # Hint: is misc with collection-title and publisher + + if (all( + init_guess == "misc", !is.null(x$`collection-title`), + !is.null(x$publisher), !is.null(x$year) + )) { + init_guess <- "incollection" + } + + init_guess +} + +guess_address <- function(x) { + # BibTeX 'address' is taken from the publisher (book, others) or the + # conference (inproceedings). + # Set logic: conference > institution > publisher + if (!is.null(x$conference)) { + addr_search <- x$conference + } else if (!is.null(x$institution)) { + addr_search <- x$institution + } else { + addr_search <- x$publisher + } + + + address <- clean_str(paste( + c( + addr_search$address, + addr_search$city, + addr_search$region, + addr_search$country + ), + collapse = ", " + )) + + # As a fallback, use also location + if (is.null(address) && !is.null(x$location)) { + address <- clean_str(x$location$name) + } + + address +} + + +make_bibkey <- function(tobibentry) { + # Bear in mind institutions has only given + # Use the first two authors + aut_sur <- lapply(tobibentry$author[1:2], function(z) { + unz <- unlist(z) + if ("family" %in% names(unz)) { + r <- unz["family"] + return(clean_str(r)) + } + + r <- unz["given"] + return(clean_str(r)) + }) + + + aut_sur <- tolower(paste0(unlist(aut_sur), collapse = "")) + aut_sur <- gsub("\\s*", "", aut_sur) + + # Try hard to remove accents + # First with iconv + aut_sur <- iconv(aut_sur, + from = "UTF-8", to = "ASCII//TRANSLIT", + sub = "?" + ) + + # Next to latex + aut_sur <- encoded_utf_to_latex(aut_sur) + + # Finally keep only a-z letters for key + aut_sur <- gsub("[^_a-z]", "", aut_sur) + + y <- tobibentry$year + + key <- paste(c(aut_sur, y), collapse = ":") + key +} + +make_howpublised <- function(x) { + howpublished <- x$medium + + if (!is.null(howpublished)) { + # Capitalize first letter + letts <- unlist(strsplit(howpublished, "|")) + howpublished <- + clean_str(paste0(c(toupper(letts[1]), letts[-1]), collapse = "")) + } + + clean_str(howpublished) +} diff --git a/R/as_cff.R b/R/as_cff.R new file mode 100644 index 00000000..cfef6fe9 --- /dev/null +++ b/R/as_cff.R @@ -0,0 +1,215 @@ +#' Coerce lists, `person` and `bibentry` objects to [`cff`] +#' +#' @description +#' `as_cff()` turns an existing list-like **R** object into a so-called +#' [`cff`], a list with class `cff`. +#' +#' `as_cff` is an S3 generic, with methods for: +#' - `person` objects as produced by [utils::person()]. +#' - `bibentry` objects as produced by [utils::bibentry()]. +#' - `Bibtex` object as produced by [toBibtex()]. +#' - Default: Other inputs are first coerced with [as.list()]. +#' +#' @param x A `person`, `bibentry` or other object that could be coerced to a +#' list. +#' @param ... Additional arguments to be passed on to other methods. +#' +#' @rdname as_cff +#' +#' @returns +#' +#' A `cff` object. These objects are rarely [valid][cff_validate()], but can +#' be used to complement or modify complete `cff` objects. +#' +#' @family coercing +#' @family s3method +#' +#' @details +#' For `as_cff.bibentry()` / `as_cff.Bibtex()` see +#' `vignette("bibtex_cff", "cffr")` to understand how the mapping is performed. +#' +#' [as_cff_person()] is preferred over `as_cff.person()` since it can handle +#' `character` person such as `"Davis, Jr., Sammy"`. For `person` objects both +#' functions are similar. +#' +#' @seealso +#' - [cff()]: Create a full `cff` object from scratch. +#' - [cff_modify()]: Modify a `cff` object. +#' - [cff_create()]: Create a `cff` object of a **R** package. +#' - [cff_read()]: Create a `cff` object from a external file. +#' - [as_cff_person()]: Recommended way for creating persons in CFF format. +#' +#' @export +#' +#' @examples +#' +#' # Convert a list to "cff" object +#' cffobj <- as_cff(list( +#' "cff-version" = "1.2.0", +#' title = "Manipulating files" +#' )) +#' +#' class(cffobj) +#' +#' # Nice display thanks to yaml package +#' cffobj +#' +#' # bibentry method +#' a_cit <- citation("cffr")[[1]] +#' +#' a_cit +#' +#' as_cff(a_cit) +#' +#' # Bibtex method +#' a_bib <- toBibtex(a_cit) +#' +#' a_bib +#' +#' as_cff(a_cit) +#' +as_cff <- function(x, ...) { + UseMethod("as_cff") +} + +#' @rdname as_cff +#' @export +as_cff.default <- function(x, ...) { + as_cff(as.list(x), ...) +} + + +#' @rdname as_cff +#' @export +as_cff.list <- function(x, ...) { + # Clean up empty values on top + clean_up <- vapply(x, is.null, FUN.VALUE = logical(1)) + x_clean <- x[!clean_up] + new_cff(x_clean) +} + +#' @rdname as_cff +#' @export +as_cff.person <- function(x, ...) { + as_cff_person(x) +} + + +#' @rdname as_cff +#' @export +as_cff.bibentry <- function(x, ...) { + cff_ref <- as_cff_reference(x) + clean_up <- vapply(cff_ref, is.null, FUN.VALUE = logical(1)) + if (all(clean_up)) { + return(NULL) + } + + cff_refs <- as_cff(cff_ref, ...) + + # Add clases + cff_refs_class <- lapply(cff_refs, function(x) { + class(x) <- unique(c("cff_ref", "cff", class(x))) + x + }) + + class(cff_refs_class) <- c("cff_ref_list", "cff", "list") + cff_refs_class +} + +#' @rdname as_cff +#' @export +as_cff.Bibtex <- function(x, ...) { + tmp <- tempfile(fileext = ".bib") + writeLines(x, tmp) + abib <- cff_read_bib(tmp) + cff_refs <- as_cff(abib, ...) + + # Add clases + cff_refs_class <- lapply(cff_refs, function(x) { + class(x) <- unique(c("cff_ref", "cff", class(x))) + x + }) + + class(cff_refs_class) <- c("cff_ref_list", "cff", "list") + cff_refs_class +} + +# nolint start +#' @export +#' @rdname as_cff +#' @usage NULL +as.cff <- function(x) { + as_cff(x) +} +# nolint end + +# Helper---- + +#' Recursively clean lists and assign cff classes +#' to all nested lists +#' +#' +#' @noRd +rapply_cff <- function(x) { + if (inherits(x, "cff")) { + return(x) + } + + if (is.list(x) && length(x) > 0) { + x <- drop_null(x) + x <- lapply(x, rapply_cff) + return(structure(x, class = c("cff", "list"))) + } else { + return(x) + } +} + +# https://adv-r.hadley.nz/s3.html#s3-constructor +# Constructor +new_cff <- function(x) { + if (is_cff(x)) { + class(x) <- c("cff", "list") + return(x) + } + + # Clean all strings recursively + + x <- rapply(x, function(x) { + if (is.list(x) || length(x) > 1) { + return(x) + } + return(clean_str(x)) + }, + how = "list" + ) + + # Remove NULLs + x <- drop_null(x) + + # Remove duplicated names if named + if (!is.null(names(x))) x <- x[!duplicated(names(x))] + + # Now apply cff class to nested lists + x <- lapply(x, rapply_cff) + + class(x) <- c("cff", "list") + x +} + +# Just for pretty printing on extract + +# Based in person method +# https://github.com/wch/r-source/blob/trunk/src/library/utils/R/citation.R +#' @export +`[.cff_ref_list` <- function(x, i) { + rval <- unclass(x)[i] + class(rval) <- class(x[[i]]) + return(rval) +} + +#' @export +`[.cff_pers_list` <- function(x, i) { + rval <- unclass(x)[i] + class(rval) <- class(x[[i]]) + return(rval) +} diff --git a/R/as_cff_person.R b/R/as_cff_person.R new file mode 100644 index 00000000..60a17e0e --- /dev/null +++ b/R/as_cff_person.R @@ -0,0 +1,472 @@ +#' Create a person with the corresponding [`cff`] structure +#' +#' @description +#' +#' Create a `person` or `entity` as defined by the +#' +#' ```{r, echo=FALSE, results='asis'} +#' +#' cat(paste0(" [Citation File Format schema]", +#' "(https://github.com/citation-file-format/", +#' "citation-file-format/blob/main/schema-guide.md).")) +#' +#' +#' ``` +#' +#' [as_cff_person()] can convert the following objects: +#' - Objects with class `person` as provided by [utils::person()]. +#' - A `character` string with the definition of an author or several authors, +#' using the standard BibTeX notation. See Markey (2007) for a full +#' explanation. +#' +#' [as_cff_person()] would recognize if the input should be converted using the +#' CFF reference `person` or `entity`. +#' +#' @seealso +#' Examples in `vignette("cffr", "cffr")` and [utils::person()]. +#' +#' @export +#' @rdname as_cff_person +#' @name as_cff_person +#' @order 1 +#' +#' @family coercing +#' +#' @param person It can be either: +#' - A `person` or list of `person` object created with [utils::person()]. +#' - A `character` object or vector representing a person or persons. +#' See **Examples**. +#' +#' @return +#' `as_cff_person()` returns A list of persons or entities with class +#' `cff` converted to the +#' ```{r, echo=FALSE, results='asis'} +#' +#' cat(paste0(" [Citation File Format schema]", +#' "(https://github.com/citation-file-format/", +#' "citation-file-format/blob/main/schema-guide.md).")) +#' +#' +#' ``` +#' +#' @details +#' +#' `as_cff_person()` uses a custom algorithm that tries to break a name as +#' explained in Section 11 of "Tame the BeaST" (Markey, 2007) (see also +#' Decoret, 2007): +#' +#' - `First von Last`. +#' - `von Last, First`. +#' - `von Last, Jr, First`. +#' +#' Mapping is performed as follows: +#' - `First` is mapped to the CFF field `given-names`. +#' - `von` is mapped to the CFF field `name-particle`. +#' - `Last` is mapped to the CFF field `family-names`. +#' - `Jr` is mapped to the CFF field `name-suffix`. +#' +#' In the case of entities, the whole `character` would be mapped to `name`. +#' It is a good practice to "protect" entity's names with `{}`: +#' +#' ```{r child = "man/chunks/person.Rmd"} +#' ``` +#' `as_cff_person()` would try to add as many information as possible. +#' On `character` string coming from [`format(person())`][utils::person()] the +#' email and the ORCID would be gathered as well. +#' +#' @references +#' - Patashnik, Oren. "BIBTEXTING" February 1988. +#' . +#' +#' - Markey, Nicolas. "Tame the BeaST" +#' *The B to X of BibTeX, Version 1.4* (October 2007). +#' . +#' - Decoret X (2007). "A summary of BibTex." +#' ```{r, echo=FALSE, results='asis'} +#' +#' cat(paste0("")) +#' +#' ``` +#' +#' See **Examples** for more information. +#' +#' +#' @examples +#' # Create a person object +#' a_person <- person( +#' given = "First", family = "Author", +#' role = c("aut", "cre"), +#' email = "first.last@example.com", comment = c( +#' ORCID = "0000-0001-8457-4658", +#' affiliation = "An affiliation" +#' ) +#' ) +#' +#' a_person +#' +#' cff_person <- as_cff_person(a_person) +#' +#' cff_person +#' +#' # Back to person object with S3 Method +#' as.person(cff_person) +#' +#' # Parse a string +#' a_str <- paste0( +#' "Julio Iglesias ", +#' "()" +#' ) +#' as_cff_person(a_str) +#' +#' # Several persons +#' persons <- c(person("Clark", "Kent"), person("Lois", "Lane")) +#' +#' as_cff_person(persons) +#' +#' # Or you can use BibTeX style if you prefer +#' +#' x <- "Frank Sinatra and Dean Martin and Davis, Jr., Sammy and Joey Bishop" +#' +#' as_cff_person(x) +#' +#' as_cff_person("Herbert von Karajan") +as_cff_person <- function(person) { + if (any(is.null(person), is.na(person), length(person) == 0)) { + return(NULL) + } + + hint <- guess_hint(person) + + verbopt <- getOption("cffr_message_verbosity", "none") + if (verbopt == "debug") { + cli::cli_alert_info( + "In {.fn as_cff_person} using internal for {.val {hint}}." + ) + } + + if (hint == "txt") { + # Need to split the character + person_split <- split_txt_persons(person) + the_obj <- lapply(person_split, create_person_from_txt) + } else { + the_obj <- lapply(person, create_person_from_r) + } + + if (!length(the_obj) > 0) { + return(NULL) + } + the_obj <- new_cff(the_obj) + + # Add classes + cff_pers_class <- lapply(the_obj, function(x) { + class(x) <- unique(c("cff_pers", "cff", class(x))) + x + }) + + class(cff_pers_class) <- c("cff_pers_list", "cff", "list") + + cff_pers_class +} + +create_person_from_r <- function(person) { + person <- as.person(person) + + # Special case for Bioconductor + + if (is_substring(person$given, "Bioconductor")) { + person <- person( + given = paste( + clean_str(person$given), + clean_str(person$family) + ), + email = person$email, + role = person$role, + comment = person$comment + ) + } + + # Special case for R Core Team + if (all( + is_substring(clean_str(person$given), "R Core"), + is_substring(person$family, "Team") + )) { + person <- person( + given = paste( + clean_str(person$given), + clean_str(person$family) + ), + email = person$email, + role = person$role, + comment = person$comment + ) + } + + # Guess if entity of person. + is_entity <- is.null(person$family) || is.null(person$given) + + # Create a text version of the person, would be treated as bibtex + + if (is_entity) { + as_bib_text <- paste(c(person$family, person$given), collapse = " ") + # And protect it + as_bib_text <- paste0("{", as_bib_text, "}") + } else { + # Use von Family, Junior, Given + # Protect given + giv <- paste0(person$given, collapse = " ") + giv <- paste0("{", giv, "}") + as_bib_text <- paste0(c(person$family, giv), collapse = ", ") + } + + parsed_person <- create_person_from_txt(as_bib_text) + parsed_comments <- extract_person_comments(person) + + # Add comments + parsed_person <- c(parsed_person, parsed_comments) + + # Validate fields + parsed_person <- validate_cff_person_fields(parsed_person) + parsed_person +} + +create_person_from_txt <- function(as_bib_text) { + # Can extract comments as R + # Locate comment with R format.person default pattern + # 'first last [role] (comment) + # but we protect this if inside brackets + comments_pattern <- "<|>|\\(|\\)|\\[|\\]" + + protected <- gsub(paste0("(", comments_pattern, ")(?![^\\}]*(\\{|$))"), + "0", as_bib_text, + perl = TRUE + ) + + start_comment <- min(unlist(regexpr(comments_pattern, protected))) + + if (start_comment > 0) { + # has comments + person_only <- trimws(substr(as_bib_text, 1, start_comment - 1)) + comment_only <- trimws(substr( + as_bib_text, start_comment, + nchar(as_bib_text) + )) + + # Fake a person object to extract comments + fake_person <- paste0("{Fake} ", comment_only) + parsed_comments <- extract_person_comments(fake_person) + } else { + # Does not + person_only <- as_bib_text + parsed_comments <- list() + } + + # Special case for Bioconductor + if (is_substring(tolower(person_only), "bioconductor")) { + person_only <- paste0("{", person_only, "}") + } + # Special case for R Core Team + if (is_substring(tolower(person_only), "r core")) { + person_only <- paste0("{", person_only, "}") + } + + + # Now extract structure for person_only string + # It may be one of: + # A. Given von Family + # B. von Family, Given + # C. von Family, Junior, Given + + # Protect commas on brackets to avoid error counting + protected <- gsub(",(?![^\\}]*(\\{|$))", "@comma@", + person_only, + perl = TRUE + ) + + commas <- as.character(lengths(regmatches( + protected, + gregexpr(",", protected) + ))) + + # Assign the corresponding fun + bibtex_name_str <- switch(commas, + # Case A + "0" = bibtex_pers_first_von_last(person_only), + # Case B + "1" = bibtex_pers_von_last_first(person_only), + # Case C + "2" = bibtex_pers_von_last_first_jr(person_only), + # Empty + list(family = paste(person_only, collapse = " ")) + ) + + # Clean + bibtex_name_str <- lapply(bibtex_name_str, function(z) { + if (is.null(z)) { + return(NULL) + } + if (any((is.na(z) | z == ""))) { + return(NULL) + } + + cleaned <- gsub("\\{|\\}", "", z) + clean_str(cleaned) + }) + + # Final parsed person + if (is.null(bibtex_name_str$given)) { + ent <- c(bibtex_name_str$von, bibtex_name_str$family, bibtex_name_str$jr) + ent <- clean_str(paste(ent, collapse = " ")) + parsed_person <- list(name = ent) + } else { + parsed_person <- list( + "family-names" = bibtex_name_str$family, + "given-names" = bibtex_name_str$given, + "name-particle" = bibtex_name_str$von, + "name-suffix" = bibtex_name_str$jr + ) + } + + parsed_person <- parsed_person[!lengths(parsed_person) == 0] + + # Add comments + parsed_person <- c(parsed_person, parsed_comments) + + # Validate fields + parsed_person <- validate_cff_person_fields(parsed_person) + parsed_person +} + +guess_hint <- function(person) { + if (inherits(person, "person")) { + return("person") + } + + # Rest of cases "txt" + return("txt") +} + + +split_txt_persons <- function(person) { + person <- trimws(person) + person <- paste0(person, collapse = " and ") + + # Remove role on [] as it comes from print.person by default + # We don't use it here + person <- gsub("\\[[^()]*\\]", "", person) + + # Protect 'and' on brackets {} + # Lower + protected <- gsub("(and)(?![^\\}]*(\\{|$))", "@nd@", + person, + perl = TRUE + ) + + # upper + protected <- gsub("AND(?![^\\}]*(\\{|$))", "@ND@", + protected, + perl = TRUE + ) + + # Do the same for 'and' in comments "()" as provided by print.person + # Lower + protected <- gsub("(and)(?![^\\)]*(\\(|$))", "@nd@", + protected, + perl = TRUE + ) + + # upper + protected <- gsub("AND(?![^\\)]*(\\(|$))", "@ND@", + protected, + perl = TRUE + ) + + # Do the same for 'and' in "<>". These are email, should never happen + # Lower + protected <- gsub("(and)(?![^>]*(<|$))", "@nd@", + protected, + perl = TRUE + ) + + # upper + protected <- gsub("AND(?![^>]*(<|$))", "@ND@", + protected, + perl = TRUE + ) + + auths <- unlist(strsplit(protected, " and | AND ")) + + # Unprotec + auths_un <- gsub("@nd@", "and", auths) + auths_un <- gsub("@ND@", "AND", auths_un) + + auths_un +} + +extract_person_comments <- function(person) { + # Ensure person type + person <- as.person(person) + + # Extract from comments + parsed_comments <- as.list(person$comment) + names(parsed_comments) <- tolower(names(parsed_comments)) + nms_com <- names(parsed_comments) + comment_as_text <- tolower(clean_str(parsed_comments)) + + # Special case when coerced from text, only can extract orcid and web + if (all( + any(is.na(nms_com), length(nms_com) == 0), + length(comment_as_text > 0) + ) + ) { + split_comments <- unlist(strsplit(comment_as_text, ",| |<|>")) + + # Guess that seems to be a web + url_comment <- split_comments[is_url(split_comments)] + + # guess orcid + orcid <- url_comment[grepl("orcid.org/", url_comment)] + + # Get the first non-orcid url + web <- url_comment[!grepl("orcid.org/", url_comment)][1] + + # Reset comment list + parsed_comments <- list() + + parsed_comments$orcid <- clean_str(orcid) + parsed_comments$website <- clean_str(web) + } + + # Add url to orcid if not present + # Parse leading invalid urls + + if (!is.null(parsed_comments$orcid)) { + orcid <- gsub("^orcid.org/", "", parsed_comments$orcid) + orcid <- gsub("^https://orcid.org/", "", orcid) + orcid <- gsub("^http://orcid.org/", "", orcid) + + parsed_comments$orcid <- paste0("https://orcid.org/", orcid) + } + + # Add website + web <- parsed_comments$website + + if (!is.null(web)) { + parsed_comments$website <- clean_str(web[is_url(web)]) + } + + # Add also email + # Check if several mails (MomTrunc 6.0) + look_emails <- c(unlist(person$email), parsed_comments$email) + valid_emails <- unlist(lapply(look_emails, is_email)) + email <- look_emails[valid_emails][1] + + # Final list + fin_list <- c( + list(email = NULL), + parsed_comments["email" != names(parsed_comments)] + ) + fin_list$email <- clean_str(email) + + fin_list +} diff --git a/R/cff_parse_citation.R b/R/as_cff_reference.R similarity index 79% rename from R/cff_parse_citation.R rename to R/as_cff_reference.R index c7fccc55..e13b0729 100644 --- a/R/cff_parse_citation.R +++ b/R/as_cff_reference.R @@ -1,90 +1,17 @@ -#' Parse a `bibentry` to `cff` +#' Internal functions for `as_cff.bibentry` method #' -#' Parse a `bibentry` object to a valid format for a `CITATION.cff` file. -#' -#' @seealso [cff_create()], `vignette("bibtex_cff", "cffr")`, [bibentry()] -#' -#' @export -#' -#' @family Parsers -#' -#' @param bib A `bibentry` object, either created with [bibentry()] -#' (preferred) or [citEntry()]. -#' -#' @return A [`cff`] object ready to be used on [cff_create()]. -#' -#' @details -#' This is a helper function designed to help on adding or -#' replacing the auto-generated authors of the package. See **Examples**. -#' -#' This function tries to adapt a `bibentry` object (generated with [bibentry()] -#' or [citEntry()]) to the CFF standard. -#' -#' ## Entry types considered -#' -#' - **Article**, **Book**, **Booklet**, **InBook**, **InCollection**, -#' **InProceedings**, **Manual**, **MastersThesis**, **Misc**, **PhDThesis**, -#' **Proceedings**, **TechReport**, **Unpublished**. See [bibentry()] -#' for more information. -#' -#' Note that **Conference** is not implemented in -#' [bibentry()], however is equivalent to **InProceedings** (Patashnik (1988)). -#' -#' ## Fields considered -#' -#' - **address**, **author**, **booktitle**, **chapter**, **edition**, -#' **editor**, **howpublished**, **institution**, **journal**, **key**, -#' **month**, **note**, **number**, **organization**, **pages**, -#' **publisher**, **school**, **series**, **title**, **type**, **year**. -#' -#' **annote** and **crossref** fields are ignored. -#' -#' -#' @references -#' - Patashnik, Oren. "BIBTEXTING" February 1988. -#' . -#' -#' - Haines, R., & The Ruby Citation File Format Developers. (2021). -#' *Ruby CFF Library (Version 0.9.0)* (Computer software). -#' \doi{10.5281/zenodo.1184077}. -#' -#' @examples -#' \donttest{ -#' bib <- citation("base") -#' bib -#' -#' -#' # To cff -#' bib_to_cff <- cff_parse_citation(bib) -#' bib_to_cff -#' -#' # Create the object -#' new_cff <- cff() -#' -#' full <- cff_create(new_cff, keys = list("preferred-citation" = bib_to_cff)) -#' -#' full -#' # Validate -#' cff_validate(full) -#' -#' # Several citations -#' -#' cff_parse_citation(citation("rmarkdown")) -#' } -cff_parse_citation <- function(bib) { - if (!inherits(bib, "bibentry")) { - return(NULL) - } +#' @noRd +as_cff_reference <- function(x) { + # Need always to be unnamed bibentry + bib <- unname(x) - ## Unname - bib <- unname(bib) - if (length(bib) > 1) { - bib <- lapply(bib, cff_parse_citation) - class(bib) <- "cff" - return(bib) - } + # Return always a list + the_list <- lapply(bib, make_cff_reference) + the_list +} +make_cff_reference <- function(bib) { # Parse BibTeX entry ---- parse_cit <- parse_bibtex_entry(bib) @@ -100,6 +27,8 @@ cff_parse_citation <- function(bib) { # Parse BibTeX fields ---- parsed_fields <- parse_bibtex_fields(parse_cit) + # VGAM: title is a vector + parsed_fields$title <- clean_str(parsed_fields$title) ## Handle collection types ---- parsed_fields <- add_bibtex_coltype(parsed_fields) @@ -121,9 +50,7 @@ cff_parse_citation <- function(bib) { } ## authors ---- - parse_all_authors <- drop_null( - lapply(parsed_fields$authors, cff_parse_person) - ) + parse_all_authors <- as_cff_person(parsed_fields$authors) parsed_fields$authors <- unique(parse_all_authors) ## other persons---- @@ -186,9 +113,8 @@ cff_parse_citation <- function(bib) { parse_cit <- parse_cit[names(parse_cit) %in% validnames] parse_cit <- drop_null(parse_cit) - parse_cit_result <- as.cff(parse_cit) - return(parse_cit_result) + return(parse_cit) } #' Extract and map BibTeX entry @@ -313,7 +239,7 @@ parse_bibtex_fields <- function(parse_cit) { loc <- parse_cit$location - if (!is.null(loc)) parse_cit$location <- person(family = loc) + if (!is.null(loc)) parse_cit$location <- loc diff --git a/R/assertions.R b/R/assertions.R index d703d6f5..245dc9e1 100644 --- a/R/assertions.R +++ b/R/assertions.R @@ -6,10 +6,11 @@ is_email <- function(email) { return(FALSE) } - # See https://www.nicebread.de/validating-email-adresses-in-r/ - x <- grepl("\\<[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}\\>", - as.character(email), - ignore.case = TRUE + email <- trimws(as.character(email)) + + # See CFF validation schema + x <- grepl("^[\\S]+@[\\S]+\\.[\\S]{2,}$", email, + ignore.case = TRUE, perl = TRUE ) x } @@ -22,7 +23,7 @@ is_url <- function(url) { return(FALSE) } - x <- grepl("^http://|^https://|^ftp://|sftp://", url) + x <- grepl("^(https|http|ftp|sftp)://.+", url) x } @@ -43,15 +44,11 @@ is_substring <- function(x, sub) { } } -#' Check if a object is cff +#' Check if a object is `cff` #' @param x object to be evaluated #' @noRd is_cff <- function(x) { - if (inherits(x, "cff")) { - return(TRUE) - } else { - return(FALSE) - } + inherits(x, "cff") } #' Check if a object is cff file @@ -70,7 +67,7 @@ is_cff_file <- function(x) { return(TRUE) } -#' Check if a object is cff +#' Check if an url is from GitHub #' @param x object to be evaluated #' @noRd is_github <- function(x) { @@ -82,7 +79,7 @@ is_github <- function(x) { return(res) } -#' Error if it is not a cff file +#' Error if it is not a `cff` file or object #' @param x file to be evaluated #' @noRd stopifnotcff <- function(x) { @@ -113,3 +110,10 @@ stopifnotexists <- function(x) { } return(invisible(NULL)) } + +#' Check if `x` has names +#' @param x object to be evaluated +#' @noRd +is_named <- function(x) { + !is.null(names(x)) +} diff --git a/R/cff-class.R b/R/cff-class.R deleted file mode 100644 index 87b0d599..00000000 --- a/R/cff-class.R +++ /dev/null @@ -1,12 +0,0 @@ -#' The `cff` class -#' -#' @name cff-class -#' -#' @description -#' TODO -#' -#' @keywords internal -#' -#' -#' -NULL diff --git a/R/cff-methods.R b/R/cff-methods.R new file mode 100644 index 00000000..d2c80e05 --- /dev/null +++ b/R/cff-methods.R @@ -0,0 +1,143 @@ +#' Print Values +#' +#' @noRd +#' @export +print.cff <- function(x, ...) { + cat(yaml::as.yaml(x)) +} + +#' Combine Values into a Vector or List +#' +#' @source +#' Based on `?c.person` \CRANpkg{utils}. +#' +#' +#' +#' @noRd +#' @export +c.cff <- function(..., recursive = FALSE) { + args <- list(...) + args <- lapply(args, unclass) + rval <- do.call("c", args) + class(rval) <- "cff" + rval +} + + +# nolint start +#' Coerce to a Data Frame +#' +#' @noRd +#' @export +as.data.frame.cff <- function(x, row.names = NULL, optional = FALSE, ...) { + # List of references + if (inherits(x, "cff_ref_list")) { + x_n <- list("references" = x) + the_df <- cff_to_df(x_n) + } else if (is.null(names(x))) { + the_df <- cff_list_to_df(x) + } else { + the_df <- cff_to_df(x) + } + + the_df <- as.data.frame(the_df, + row.names = row.names, optional = optional, + ... + ) + + return(the_df) +} + +# nolint end + +#' @rdname as_cff_person +#' @name as.person.cff +#' @order 3 +#' +#' @description +#' +#' The inverse transformation (`cff` person to [`person`][utils::as.person()]) +#' object can be done through the [as.person.cff()] method. Note that this is +#' expected to be used with a `cff` person, not with a complete `cff` object. +#' +#' +#' @family s3method +#' @export +#' @seealso [utils::person()] +#' +#' @param x `cff` object representing a person or entity. +#' +#' @return +#' +#' `as.person.cff()` returns a `person` object. +as.person.cff <- function(x) { + # If single enclose on a list + is_single <- any(grepl("^name$|^given-names|^family-names", names(x))) + + if (is_single) x <- list(x) + + + pers <- lapply(x, make_r_person) + + # If not all extracted, malformed, return null + if (!all(lengths(pers) > 0)) { + return(person()) + } + do.call(c, pers) +} + +#' Head +#' +#' @noRd +#' @export +head.cff <- function(x, n = 6L, ...) { + as_cff(NextMethod()) +} + +#' Tail +#' +#' @noRd +#' @export +tail.cff <- function(x, n = 6L, ...) { + as_cff(NextMethod()) +} + + +#' @rdname as_bibentry +#' @name toBibtex.cff +#' @order 2 +#' +#' @description +#' Additionally, it is also provided a method for [toBibtex()], that can +#' convert [`cff`] objects to `Bibtex` objects as provided by +#' [utils::toBibtex()]. These objects are character vectors with BibTeX markup. +#' +#' @family s3method +#' @export +#' @seealso [utils::toBibtex()] +#' +#' @param object `cff` object. +#' @param ... Arguments passed to [utils::toBibtex()]. +#' +#' @return +#' +#' `toBibtex.cff()` returns a `Bibtex` object that can be printed as BibTeX +#' markup. +toBibtex.cff <- function(object, ..., + what = c("preferred", "references", "all")) { + # If a single reference... + if ("cff-version" %in% names(object)) { + # If full cff + biblist_cff <- as_bibentry(x = object, what = what) + } else { + # Need to enlist if single + if ("type" %in% names(object)) { + object <- list(object) + class(object) <- c("cff", "list") + } + + bib_list <- lapply(object, make_bibentry) + biblist_cff <- do.call(c, bib_list) + } + toBibtex(biblist_cff, ...) +} diff --git a/R/cff.R b/R/cff.R new file mode 100644 index 00000000..3d619158 --- /dev/null +++ b/R/cff.R @@ -0,0 +1,105 @@ +#' Read and manipulate `cff` objects +#' +#' A class and utility methods for reading, creating and holding CFF +#' information. See [`cff-class`] to learn more about `cff` objects. +#' +#' @rdname cff +#' @name cff +#' @return +#' +#' A `cff` object. Under the hood, a `cff` object is a regular `list` object +#' with a special [print()] method. +#' +#' @family core +#' +#' @param path `r lifecycle::badge("deprecated")` `path` is no longer supported, +#' use [cff_read_cff_citation()] instead. +#' @param ... Named arguments to be used for creating a `cff` object. See +#' **Details**. +#' +#' @details +#' +#' If no additional `...` parameters are supplied (the default behavior), +#' a minimal valid `cff` object is created. `cff` would convert `_` in the name +#' of the argument to `-` (e.g, `cff_version = "1.2.0'` would be converted to +#' `cff-version = "1.2.0'`) +#' +#' Valid parameters are those specified on [cff_schema_keys()]: +#' +#' +#' ```{r, echo=FALSE} +#' +#' +#' valid_keys <- cff_schema_keys() +#' +#' knitr::kable(valid_keys, col.names = "**valid cff keys**") +#' +#' +#' ``` +#' @export +#' @examples +#' # Blank cff +#' cff() +#' +#' # Use custom params +#' test <- cff( +#' title = "Manipulating files", +#' keywords = c("A", "new", "list", "of", "keywords"), +#' authors = as_cff_person("New author") +#' ) +#' test +#' \donttest{ +#' # Would fail +#' cff_validate(test) +#' } +#' +#' # Modify with cff_create +#' new <- cff_create(test, keys = list( +#' "cff_version" = "1.2.0", +#' message = "A blank file" +#' )) +#' new +#' +#' # Would pass +#' cff_validate(new) +#' +#' @export +cff <- function(path, ...) { + if (!missing(path)) { + if (is_cff_file(path)) { + lifecycle::deprecate_soft( + "1.0.0", "cff(path)", "cff_read_cff_citation()" + ) + return(cff_read_cff_citation(path)) + } else { + lifecycle::deprecate_soft( + "1.0.0", "cff(path)", + details = "Argument ignored." + ) + } + } + + cffobj <- list(...) + if (length(cffobj) == 0) { + # If nothing is provided use a minimal cff + path <- system.file("examples/CITATION_skeleton.cff", + package = "cffr" + ) + + return(cff_read_cff_citation(path)) + } + + # Check names + + cffobj <- validate_extra_keys(cffobj) + cffobj <- fuzzy_keys(cffobj) + + if (any(duplicated(names(cffobj)))) { + cli::cli_alert_warning("Removing duplicated keys.") + cffobj <- cffobj[!duplicated(names(cffobj))] + } + + cffobj <- as_cff(cffobj) + + return(cffobj) +} diff --git a/R/cff_create.R b/R/cff_create.R index ddb05320..b8792efb 100644 --- a/R/cff_create.R +++ b/R/cff_create.R @@ -1,32 +1,36 @@ -#' Create `cff` object +#' Create a [`cff`] object #' #' @description -#' Create a [`cff`] object from a given source for further manipulation. -#' Similar to [cff_write()], but returns a object rather than writing -#' directly to a file. See **Examples**. #' -#' @return A [`cff`] list object. +#' Create a [`cff`] object from a given source for further +#' manipulation. This object can be written to a `*.cff ` file with +#' [cff_write()], see **Examples**. #' -#' @family Core functions +#' Most of the heavy lifting of \CRANpkg{cffr} is done via this function. +#' +#' @return A [`cff`] object. +#' +#' @family core #' #' @export #' #' @param x The source that would be used for generating #' the [`cff`] object. It could be: -#' * A missing value. That would retrieve the DESCRIPTION -#' file on your in-development package. +#' * A missing value. That would retrieve the `DESCRIPTION` file on your +#' in-development **R** package. #' * An existing [`cff`] object, #' * The name of an installed package (`"jsonlite"`), or -#' * Path to a DESCRIPTION file (`"*/DESCRIPTION*"`). +#' * Path to a `DESCRIPTION` file (`"./DESCRIPTION"`). #' -#' @param keys List of additional keys to add to the [`cff`] object. See +#' @param keys +#' List of additional keys to add to the [`cff`] object. See #' **Details**. #' @param cff_version The Citation File Format schema version that the #' `CITATION.cff` file adheres to for providing the citation metadata. #' @param gh_keywords Logical `TRUE/FALSE`. If the package is hosted on #' GitHub, would you like to add the repo topics as keywords? #' @param dependencies Logical `TRUE/FALSE`. Would you like to add the -#' of your package to the `reference` key? +#' of your package to the `references` CFF key? #' @param authors_roles Roles to be considered as authors of the package when #' generating the `CITATION.cff` file. See **Details**. #' @@ -39,8 +43,9 @@ #' #' #' ``` +#' See also [cff_write()] for creating a CFF file. `vignette("cffr", "cffr")` +#' shows an introduction on how manipulate `cff` objects. #' -#' `vignette("cffr", "cffr")` #' @details #' #' It is possible to add additional keys not detected by [cff_create()] using @@ -59,11 +64,11 @@ #' ``` #' for additional details. #' -#' If `x` is a path to a DESCRIPTION file or `inst/CITATION`, is not present on -#' your package, \CRANpkg{cffr} would auto-generate a `preferred-citation` key -#' using the information provided on that file. +#' If `x` is a path to a `DESCRIPTION` file or `inst/CITATION`, is not present +#' on your package, \CRANpkg{cffr} would auto-generate a `preferred-citation` +#' key using the information provided on that file. #' -#' By default, only persons whose role in the DESCRIPTION file of the package +#' By default, only persons whose role in the `DESCRIPTION` file of the package #' is author (`"aut"`) or maintainer (`"cre"`) are considered to be authors #' of the package. The default setting can be controlled via the `authors_roles` #' parameter. See **Details** on [utils::person()] to get additional insights @@ -85,7 +90,7 @@ #' message = "This overwrites fields", #' abstract = "New abstract", #' keywords = c("A", "new", "list", "of", "keywords"), -#' authors = list(cff_parse_person("New author")) +#' authors = as_cff_person("New author") #' ) #' #' cff_create(demo_file, keys = newkeys) @@ -97,22 +102,17 @@ #' #' new_contact <- append( #' old$contact, -#' list( -#' cff_parse_person(person( -#' given = "I am", -#' family = "New Contact" -#' )) -#' ) +#' as_cff_person(person( +#' given = "I am", +#' family = "New Contact" +#' )) #' ) #' #' #' cff_create(demo_file, keys = list("contact" = new_contact)) #' } -cff_create <- function(x, - keys = list(), - cff_version = "1.2.0", - gh_keywords = TRUE, - dependencies = TRUE, +cff_create <- function(x, keys = list(), cff_version = "1.2.0", + gh_keywords = TRUE, dependencies = TRUE, authors_roles = c("aut", "cre")) { # On missing use package root if (missing(x)) x <- getwd() @@ -122,6 +122,42 @@ cff_create <- function(x, cli::cli_abort(msg) } + # Detect sources and build cff + result_parsed <- detect_sources( + x, cff_version, gh_keywords, + dependencies, authors_roles + ) + + desc_path <- result_parsed[["desc_path"]] + instpack <- result_parsed[["instpack"]] + cffobjend <- result_parsed[["cffobjend"]] + + + + # Add software dependencies + if (dependencies) { + deps <- parse_dependencies(desc_path, instpack) + + cffobjend$references <- unique(c(cffobjend$references, deps)) + } + + # Additional keys, using internals of cff_modify + cffobjend <- modify_cff(cffobjend, keys, "keys") + + # Order + cffobjend <- cffobjend[cff_schema_keys()] + + # Enhance authors info + if (!is.null(cffobjend$`preferred-citation`)) { + cffobjend$`preferred-citation`$authors <- enhance_pref_authors(cffobjend) + } + cffobjend <- as_cff(cffobjend) + cffobjend +} + +detect_sources <- function(x, cff_version = "1.2.0", + gh_keywords = TRUE, dependencies = TRUE, + authors_roles = c("aut", "cre")) { instpack <- as.character(installed.packages()[, "Package"]) # Set initially citobj to NULL @@ -148,16 +184,13 @@ cff_create <- function(x, # If it doesn't exists look on the root # this is for call to installed packages with system.file() if (!file.exists(cit_path)) { - cit_path <- gsub( - "DESCRIPTION$", - "CITATION", x - ) + cit_path <- gsub("DESCRIPTION$", "CITATION", x) } if (file.exists(cit_path)) { - citobj <- parse_r_citation(desc_path, cit_path) - citobj <- lapply(citobj, cff_parse_citation) + citobj <- cff_safe_read_citation(desc_path, cit_path) if (length(citobj) == 0) citobj <- NULL citobj <- drop_null(citobj) + citobj <- unname(citobj) } } else { msg <- paste0( @@ -172,8 +205,9 @@ cff_create <- function(x, cli::cli_abort("No {.file DESCRIPTION} file found with {.arg x}") } - cffobj <- cff_description(desc_path, cff_version, - gh_keywords = gh_keywords, authors_roles = authors_roles + cffobj <- cff_read_description(desc_path, cff_version, + gh_keywords = gh_keywords, + authors_roles = authors_roles ) } @@ -183,233 +217,11 @@ cff_create <- function(x, cffobjend <- merge_desc_cit(cffobj, citobj) - # Add software dependencies - if (dependencies) { - deps <- parse_dependencies(desc_path, instpack) - - cffobjend$references <- unique(c( - cffobjend$references, - deps - )) - } - - # Additional keys - if (!is.null(keys)) { - keys <- fuzzy_keys(keys) - cffobjendmod <- cffobjend[setdiff(names(cffobjend), names(keys))] - cffobjend <- modifyList(cffobjendmod, keys, keep.null = FALSE) - cffobjend <- as.cff(cffobjend) - } - - - # Order - cffobjend <- cffobjend[cff_schema_keys()] - - # Enhance authors info - - if (!is.null(cffobjend$`preferred-citation`)) { - cffobjend$`preferred-citation`$authors <- enhance_pref_authors(cffobjend) - } - cffobjend <- as.cff(cffobjend) - cffobjend -} - - -#' Merge the information of a parsed description with a parsed citation -#' @noRd -merge_desc_cit <- function(cffobj, citobj) { - # If no citobj then return null - - if (is.null(citobj)) { - return(cffobj) - } - - # Add doi from citation if missing - if (is.null(cffobj$doi)) { - cffobj$doi <- clean_str(citobj[[1]]$doi) - } - cffobjend <- c(cffobj, - "preferred-citation" = citobj[1], - references = list(citobj[-1]) - ) - - - - # Merge identifiers - oldids <- cffobjend$identifiers - cffobjend$identifiers <- c( - citobj[[1]]$identifiers, - oldids - ) - - # Reorder - cffobjfinal <- c( - cffobjend[!names(cffobjend) %in% c("identifiers", "references")], - cffobjend["identifiers"], - cffobjend["references"] - ) - - cffobjfinal <- drop_null(cffobjfinal) - - return(cffobjfinal) -} - -#' Enhance authors info from preferred-citation using metadata from DESCRIPTION -#' @noRd -enhance_pref_authors <- function(cffobjend) { - # Create index of authors extracted from DESCRIPTION (First cff level) - auth_desc <- cffobjend$authors - key_aut_desc <- lapply(auth_desc, function(x) { - l <- list(x["family-names"], x["given-names"], x["name"]) - l <- unlist(drop_null(l)) - tolower(paste0(l, collapse = "")) - }) - names(auth_desc) <- unlist(key_aut_desc) - - # Create index of authors from preferred-citation - auth_pref <- cffobjend$`preferred-citation`$authors - key_aut_cit <- lapply(auth_pref, function(x) { - l <- list(x["family-names"], x["given-names"], x["name"]) - l <- unlist(drop_null(l)) - tolower(paste0(l, collapse = "")) - }) - names(auth_pref) <- unlist(key_aut_cit) - - # Add missing keys to authors - enhancedauth <- lapply(names(auth_pref), function(x) { - newdata <- auth_desc[x] - olddata <- auth_pref[x] - - # New fields only - oldkeys <- names(olddata[[1]]) - newkeys <- names(newdata[[1]]) - fieldstoadd <- newdata[[1]][!newkeys %in% oldkeys] - - newinfo <- c(olddata[[1]], fieldstoadd) - - newinfo - }) - - enhancedauth -} + # Return collected info - -parse_dependencies <- function(desc_path, - instpack = as.character( - installed.packages()[, "Package"] - )) { - # nocov start - if (!is.character(desc_path)) { - return(NULL) - } - if (!file.exists(desc_path)) { - return(NULL) - } - # nocov end - - getdeps <- desc::desc(desc_path) - - deps <- getdeps$get_deps() - - # Adapt version - - deps$version_clean <- gsub("*", "", deps$version, fixed = TRUE) - - # Save copy for later - origdeps <- deps - - # Dedupe rows - deps <- unique(deps[, c("package", "version_clean")]) - - - # Get dependency type and add to scope - scope <- vapply(deps$package, - FUN.VALUE = character(1), - function(x) { - y <- origdeps[origdeps$package == x, "type"] - - y[1] - } + list( + desc_path = desc_path, + instpack = instpack, + cffobjend = cffobjend ) - deps$scope <- scope - - av_deps <- deps[deps$package %in% c("R", instpack), ] - - # Get references from DESCRIPTION of dependencies - cff_deps <- lapply(seq_len(nrow(av_deps)), function(y) { - n <- av_deps[y, ] - - if (n$package == "R") { - mod <- cff_parse_citation(citation()[1]) - mod$year <- format(Sys.Date(), "%Y") - } else { - mod <- try(cff_parse_citation(citation(n$package, auto = TRUE)[1]), - silent = TRUE - ) - - if (inherits(mod, "try-error")) { - return(NULL) - } - - # Simplified version of the cff obj - # Avoid cluttering the output - mod$abstract <- mod$title - mod$title <- n$package - } - - mod$type <- "software" - mod$version <- ifelse(is.na(n$version_clean), - NULL, - paste(n$version_clean) - ) - # Get url and repo from package DESCRIPTION - # urls from citation() vary due to auto = TRUE - dfile <- system.file("DESCRIPTION", package = n$package) - - if (file.exists(dfile)) { - pkg <- desc::desc(dfile) - mod$url <- parse_desc_urls(pkg)$url - mod$repository <- parse_desc_repository(pkg) - } - - mod <- drop_null(mod) - - # Get year - date_rel <- mod[["date-released"]] - - if (is.null(date_rel)) { - year <- format(Sys.Date(), "%Y") - } else { - year <- format(as.Date(date_rel), "%Y") - } - - mod$year <- year - mod$notes <- clean_str(n$scope) - - # Re-arrange - mod <- c( - mod[c( - "type", - "title", "abstract", - "notes", - "url", "repository" - )], - mod[!names(mod) %in% c( - "type", - "title", "abstract", - "notes", - "url", "repository" - )] - ) - - mod <- as.cff(mod) - }) - - cff_deps <- drop_null(cff_deps) - - cff_deps <- unique(cff_deps) - - class(cff_deps) <- "cff" - - return(cff_deps) } diff --git a/R/cff_description.R b/R/cff_description.R deleted file mode 100644 index b2676718..00000000 --- a/R/cff_description.R +++ /dev/null @@ -1,46 +0,0 @@ -#' @noRd -cff_description <- function(desc_path = "DESCRIPTION", - cff_version = "1.2.0", - gh_keywords = TRUE, - authors_roles = c("aut", "cre")) { - pkg <- desc::desc(desc_path) - pkg$coerce_authors_at_r() - - msg <- paste0( - 'To cite package "', - pkg$get("Package"), - '" in publications use:' - ) - - - list_fields <- list( - "cff-version" = cff_version, - message = msg, - type = "software", - title = parse_desc_title(pkg), - version = parse_desc_version(pkg), - authors = parse_desc_authors(pkg, authors_roles = authors_roles), - abstract = parse_desc_abstract(pkg), - repository = parse_desc_repository(pkg), - "repository-code" = parse_desc_urls(pkg)$repo, - url = parse_desc_urls(pkg)$url, - identifiers = parse_desc_urls(pkg)$identifiers, - "date-released" = parse_desc_date_released(pkg), - contact = parse_desc_contacts(pkg), - keywords = parse_desc_keywords(pkg), - license = unlist(parse_desc_license(pkg)) - ) - - if (gh_keywords) { - ghtopics <- parse_ghtopics(list_fields) - list_fields$keywords <- unique( - c( - list_fields$keywords, - ghtopics - ) - ) - } - - list_fields <- as.cff(list_fields) - list_fields -} diff --git a/R/cff_from_bibtex.R b/R/cff_from_bibtex.R deleted file mode 100644 index 302617aa..00000000 --- a/R/cff_from_bibtex.R +++ /dev/null @@ -1,91 +0,0 @@ -#' Create a cff object from BibTeX entries -#' -#' @description -#' -#' Extract the information of a BibTeX file or BibTeX entry and creates the -#' corresponding [`cff`] object with [cff_parse_citation()]. -#' -#' @param x The source that would be used for generating the `cff` object. A -#' `character` object indicating either: -#' - The path to a BibTeX file. -#' - A vector of characters with the full BibTeX string. See **Examples** -#' @param encoding Encoding to be assumed for `x`. See [readLines()]. -#' @param ... Other arguments passed to [bibtex::read.bib()]. -#' -#' @family BibTeX helpers -#' -#' @return A [`cff`] object ready to be used on [cff_create()]. -#' -#' @export -#' -#' @details -#' -#' This function requires the package \CRANpkg{bibtex} (>= 0.5.0), that is -#' listed as `Suggested` by \CRANpkg{cffr}. -#' -#' @seealso -#' -#' `vignette("bibtex_cff", package = "cffr")` to learn about the mapping of -#' information between BibTeX and CITATION.cff. -#' -#' @examples -#' if (requireNamespace("bibtex", quietly = TRUE)) { -#' x <- c( -#' "@book{einstein1921, -#' title = {Relativity: The Special and the General Theory}, -#' author = {Einstein, Albert}, -#' year = 1920, -#' publisher = {Henry Holt and Company}, -#' address = {London, United Kingdom}, -#' isbn = 9781587340925 -#' }", -#' "@misc{misc-full, -#' title = {Handing out random pamphlets in airports}, -#' author = {Joe-Bob Missilany}, -#' year = 1984, -#' month = oct, -#' note = {This is a full MISC entry}, -#' howpublished = {Handed out at O'Hare} -#' }" -#' ) -#' -#' cff_from_bibtex(x) -#' -#' # From a file -#' -#' x2 <- system.file("examples/example.bib", package = "cffr") -#' cff_from_bibtex(x2) -#' } -cff_from_bibtex <- function(x, encoding = "UTF-8", ...) { - # nocov start - if (!requireNamespace("bibtex", quietly = TRUE)) { - msg <- paste0( - "{.pkg bibtex} package required for using this function: ", - '{.run install.packages("bibtex")}' - ) - cli::cli_abort(msg) - } - # nocov end - if (!is.character(x)) { - msg <- paste0( - "{.arg x} should be a {.cls character} object. ", - "You provided an object of class(es) {.cls {class(x)}}" - ) - cli::cli_abort(msg) - } - - if (length(x) == 1 && file.exists(x)) { - # Read bib file - file <- x - } else { - # Write x to a tempfile - file <- tempfile(fileext = ".bib") - writeLines(x, file) - } - # Read from tempfile - read_bib <- bibtex::read.bib(file = file, encoding = encoding, ...) - - - tocff <- cff_parse_citation(read_bib) - return(tocff) -} diff --git a/R/cff_gha_update.R b/R/cff_gha_update.R index 5a066074..5d53b0bc 100644 --- a/R/cff_gha_update.R +++ b/R/cff_gha_update.R @@ -1,23 +1,30 @@ -#' Install a cffr GitHub Action +#' Install a \CRANpkg{cffr} GitHub Action #' #' @description #' -#' This function would install a GitHub Action on your repo. The action +#' This function would install a +#' [GitHub Action](https://github.com/features/actions) on your repo. The action #' will update your `CITATION.cff` when any of these events occur: #' - You publish a new release of the package. -#' - Your DESCRIPTION or inst/CITATION are modified. +#' - Your `DESCRIPTION` or `inst/CITATION` are modified. #' - The action can be run also manually. #' -#' @param path Project directory -#' @param overwrite If already present, do you want to overwrite your action? +#' @param path Project directory. +#' @param overwrite Logical. If already present, do you want to overwrite your +#' action? #' #' @return Invisible, this function is called by its side effects. #' #' @details #' #' Triggers on your action can be modified, see -#' [Events that trigger -#' workflows](https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows). +#' ```{r, echo=FALSE, results='asis'} +#' +#' cat(paste0(" [Events that trigger workflows]", +#' "(https://docs.github.com/en/actions/learn-github-actions/", +#' "events-that-trigger-workflows).")) +#' +#' ``` #' #' @examples #' \dontrun{ @@ -25,7 +32,7 @@ #' } #' @export #' -#' @family Git helpers +#' @family git cff_gha_update <- function(path = ".", overwrite = FALSE) { destdir <- file.path(path, ".github", "workflows") @@ -39,9 +46,8 @@ cff_gha_update <- function(path = ".", newfile <- file.path(destdir, "update-citation-cff.yaml") if (!file.exists(newfile) || isTRUE(overwrite)) { - cli::cli_alert_success( - "Installing {.file {newfile}}" - ) + cli::cli_alert_success("Installing {.file {newfile}}") + file.copy(system.file("yaml/update-citation-cff.yaml", package = "cffr"), newfile, overwrite = TRUE diff --git a/R/cff_git_hook.R b/R/cff_git_hook.R index 0c54797b..55e1bbd9 100644 --- a/R/cff_git_hook.R +++ b/R/cff_git_hook.R @@ -3,13 +3,19 @@ #' @description #' #' Install a -#' [pre-commit -#' hook](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks#_committing_workflow_hooks) +#' +#' ```{r, echo=FALSE, results='asis'} +#' +#' cat(paste0(" [pre-commit hook]", +#' "(https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks", +#' "#_committing_workflow_hooks) ")) +#' +#' ``` #' that remembers you to update your `CITATION.cff` file. #' #' @name cff_git_hook #' -#' @family Git helpers +#' @family git #' #' @export #' @@ -25,9 +31,9 @@ #' A pre-commit hook is a script that identifies simple issues before #' submission to code review. This pre-commit hook would warn you if any of the #' following conditions are met: -#' - You included in a commit your DESCRIPTION or inst/CITATION file, you +#' - You included in a commit your `DESCRIPTION` or `inst/CITATION` file, you #' are not including your `CITATION.cff` and the `CITATION.cff` file is -#' "older" than any of your DESCRIPTION or inst/CITATION file, or +#' "older" than any of your `DESCRIPTION` or `inst/CITATION` file. #' - You have updated your `CITATION.cff` but you are not including it on #' your commit. #' @@ -37,14 +43,15 @@ #' `CITATION.cff`. However, the mechanism of detection is not perfect and would #' be triggered also even if you have tried to update your `CITATION.cff` file. #' -#' This is typically the case when you have updated your DESCRIPTION or -#' inst/CITATION files but those changes doesn't make a change on your +#' This is typically the case when you have updated your `DESCRIPTION` or +#' `inst/CITATION` files but those changes doesn't make a change on your #' `CITATION.cff` file (i.e. you are including new dependencies). #' #' In those cases, you can override the check running `git commit --no-verify` -#' on the Terminal tab. If you are using -#' RStudio you can run also this command from a R script by selecting that -#' line and sending it to the Terminal using: +#' on the terminal. +#' +#' If you are using **RStudio** you can run also this command from a **R** +#' script by selecting that line and sending it to the terminal using: #' #' - `Ctrl+Alt+Enter` (Windows & Linux), or #' - `Cmd+Option+Return` (Mac). @@ -63,10 +70,7 @@ cff_git_hook_install <- function() { bash_file <- system.file("bash/citation-cff-pre-commit.sh", package = "cffr") if (requireNamespace("usethis", quietly = TRUE)) { - usethis::use_git_hook( - "pre-commit", - readLines(con = bash_file) - ) + usethis::use_git_hook("pre-commit", readLines(con = bash_file)) } else { cli::cli_alert_danger( paste0( diff --git a/R/cff_modify.R b/R/cff_modify.R new file mode 100644 index 00000000..757940df --- /dev/null +++ b/R/cff_modify.R @@ -0,0 +1,105 @@ +#' Modify a [`cff`] object +#' +#' Add new keys or modify existing ones on a [`cff`] object. +#' +#' @param x A [`cff`] object. +#' @param ... Named arguments to be used for modifying `x`. See also [cff()]. +#' +#' @details +#' +#' If any key provided in `...` is present in `x`, the result would have the +#' key provided in `...`. +#' +#' @returns +#' +#' A [`cff`] object. +#' +#' @family core +#' @export +#' @seealso +#' This function is wrapper of [utils::modifyList()]. +#' +#' See [cff()] for creating [`cff`] objects from scratch. +#' +#' +#' +#' @export +#' @family core +#' @examples +#' x <- cff() +#' x +#' +#' cff_validate(x) +#' +#' +#' x_mod <- cff_modify(x, +#' contact = as_cff_person("A contact"), +#' message = "This overwrites fields", +#' title = "New Title", +#' abstract = "New abstract", +#' doi = "10.21105/joss.03900" +#' ) +#' cff_validate(x_mod) +#' +cff_modify <- function(x, ...) { + if (!inherits(x, "cff")) { + cli::cli_abort( + "{.arg x} should be a {.cls cff} object, not {.cls {class(x)}}." + ) + } + new_keys <- list(...) + if (length(new_keys) == 0) { + cli::cli_alert_info("Args {.arg ...} empty. Returning {.arg x}.") + return(x) + } + + modify_cff(x, new_keys, "...") +} + +modify_cff <- function(x, keys, argname = "...") { + # Don't throw message here, these cases are coming from cff_create + if (all(argname == "keys", length(keys) == 0)) { + return(x) + } + + new_keys <- validate_extra_keys(keys, argname) + new_keys <- fuzzy_keys(new_keys) + if (any(duplicated(names(new_keys)))) { + cli::cli_alert_warning("Removing duplicated keys.") + new_keys <- new_keys[!duplicated(names(new_keys))] + } + + init_ord <- names(x) + + xmod <- x[setdiff(names(x), names(new_keys))] + xend <- modifyList(xmod, new_keys, keep.null = FALSE) + + # Name order + sorted_nm <- unique(c(init_ord, names(xend))) + as_cff(xend[sorted_nm]) +} + + +# Check names +validate_extra_keys <- function(cffobj, argname = "...") { + has_names <- names(cffobj) + if (is.null(has_names)) { + cli::cli_abort( + "Elements in {.arg {argname}} should be named." + ) + } + + if (any(has_names == "")) { + # nolint start + # For printing only + index <- as.character(which(has_names %in% "")) + # nolint end + + cli::cli_alert_warning( + "Found {length(index)} not-named argument{?s} in position{?s} {index}." + ) + cli::cli_alert_info("Removing unnamed arguments") + cffobj <- cffobj[has_names != ""] + } + cffobj +} diff --git a/R/cff_parse_person.R b/R/cff_parse_person.R deleted file mode 100644 index a19d87e2..00000000 --- a/R/cff_parse_person.R +++ /dev/null @@ -1,238 +0,0 @@ -#' Parse a person to `cff` -#' -#' @description -#' Parse a person or string to a valid format for a `CITATION.cff` file. This -#' is a helper function designed to help on adding or replacing the -#' auto-generated authors of the package. -#' -#' @seealso [cff_create()], `vignette("cffr", "cffr")`, [utils::person()] -#' -#' @export -#' -#' @family Parsers -#' -#' @param person A `person` object created with [person()] or a -#' character string. See **Details**. -#' -#' @return A [`cff`] object ready to be used on [cff_create()]. -#' -#' @details -#' The `person` parameter of the function could be: -#' -#' * For `cff_parse_person()`: A `person` object or a character coercible to -#' `person`. See [person()] for details. -#' * For `cff_parse_person_bibtex()`: A string with the definition of an author -#' or several authors, using the standard BibTeX notation. See Markey (2007) -#' for a full explanation. -#' -#' See **Examples** for more information. -#' -#' @references -#' - Patashnik, Oren. "BIBTEXTING" February 1988. -#' . -#' -#' - Markey, Nicolas. "Tame the BeaST." -#' *The B to X of BibTeX, Version 1.4* (October 2007). -#' . -#' -#' @examples -#' # Parse a person object -#' -#' cff_parse_person(person( -#' given = "First", -#' family = "Author", -#' role = c("aut", "cre"), -#' email = "first.last@example.com", -#' comment = c( -#' ORCID = "0000-0001-8457-4658", -#' affiliation = "An affiliation" -#' ) -#' )) -#' -#' # Parse a string -#' -#' cff_parse_person("Julio Iglesias ") -#' -#' # Several persons -#' persons <- c(person("Clark", "Kent"), person("Lois", "Lane")) -#' -#' cff_parse_person(persons) -cff_parse_person <- function(person) { - person <- as.person(person) - - if (length(person) == 0) { - return(NULL) - } - - if (length(person) > 1) { - person <- lapply(person, cff_parse_person) - class(person) <- "cff" - return(person) - } - - # Special case for Bioconductor - - if (is_substring(person$given, "Bioconductor")) { - person <- person( - given = paste( - clean_str(person$given), - clean_str(person$family) - ), - email = person$email, - role = person$role, - comment = person$comment - ) - } - - # Special case for R Core Team - if (all( - is_substring(clean_str(person$given), "R Core"), - is_substring(person$family, "Team") - )) { - person <- person( - given = paste( - clean_str(person$given), - clean_str(person$family) - ), - email = person$email, - role = person$role, - comment = person$comment - ) - } - - # Guess if entity of person. - is_entity <- is.null(person$family) || is.null(person$given) - - # Create my list - parsed_person <- list() - - if (is_entity) { - parsed_person$name <- clean_str(c(person$family, person$given)) - } else { - parsed_person$"family-names" <- clean_str(person$family) - parsed_person$"given-names" <- clean_str(person$given) - } - - # Check if several mails (MomTrunc 6.0) - valid_emails <- unlist(lapply(person$email, is_email)) - email <- person$email[valid_emails][1] - parsed_person$email <- clean_str(email) - - # Extract from comments - parsed_comments <- as.list(person$comment) - names(parsed_comments) <- tolower(names(parsed_comments)) - - # Extract for comments only what is not already there - parsed_comments <- parsed_comments[setdiff( - names(parsed_comments), - names(parsed_person) - )] - - - # Add url to orcid if not present - # Parse leading invalid urls - - if (!is.null(parsed_comments$orcid)) { - orcid <- gsub("^orcid.org/", "", parsed_comments$orcid) - orcid <- gsub("^https://orcid.org/", "", orcid) - orcid <- gsub("^http://orcid.org/", "", orcid) - - parsed_comments$orcid <- paste0( - "https://orcid.org/", - orcid - ) - } - - # Add website - web <- parsed_comments$website - - if (!is.null(web)) { - parsed_comments$website <- clean_str(web[is_url(web)]) - } - - # Add comments - parsed_person <- c(parsed_person, parsed_comments) - - - - # Keep only valid tags - Would depend on entity or person - definition <- if (is_entity) { - cff_schema_definitions_entity() - } else { - cff_schema_definitions_person() - } - parsed_person <- parsed_person[names(parsed_person) %in% definition] - - parsed_person <- as.cff(parsed_person) - parsed_person -} - -#' @rdname cff_parse_person -#' -#' @export -#' -#' @examples -#' -#' # Or you can use BibTeX style if you prefer -#' -#' x <- "Frank Sinatra and Dean Martin and Davis, Jr., Sammy and Joey Bishop" -#' -#' cff_parse_person_bibtex(x) -#' -#' cff_parse_person_bibtex("Herbert von Karajan") -cff_parse_person_bibtex <- function(person) { - person <- trimws(person) - - # Protect and on brackets - # Lower - protected <- gsub("(and)(?![^\\}]*(\\{|$))", "@nd@", - person, - perl = TRUE - ) - - # upper - protected <- gsub("AND(?![^\\}]*(\\{|$))", "@ND@", - protected, - perl = TRUE - ) - - - auths <- unlist(strsplit(protected, " and | AND ")) - - # Unprotec - auths_un <- gsub("@nd@", "and", auths) - auths_un <- gsub("@ND@", "AND", auths_un) - - - bibtex_auths <- lapply(auths_un, as_person_bibtex) - - - end <- lapply(bibtex_auths, function(x) { - if (is.null(x$given)) { - ent <- c(x$von, x$family, x$jr) - ent <- clean_str(paste(ent, collapse = " ")) - - l <- list(name = ent) - l <- as.cff(l) - } else { - l <- list( - "family-names" = x$family, - "given-names" = x$given, - "name-particle" = x$von, - "name-suffix" = x$jr - ) - - l <- as.cff(l) - } - }) - - # Handle single author - if (length(end) == 1) { - end <- end[[1]] - } else { - # Need the class - class(end) <- "cff" - } - - return(end) -} diff --git a/R/cff_read.R b/R/cff_read.R index d2c8433f..202c0572 100644 --- a/R/cff_read.R +++ b/R/cff_read.R @@ -1,203 +1,392 @@ -#' Read and manipulate `cff` objects +#' Read an external file as a [`cff`] object #' -#' A class and utility methods for reading, creating and holding CFF -#' information. +#' @description +#' Read files and convert them to [`cff`] objects. Files supported +#' are: +#' - `CITATION.cff` files. +#' - `DESCRIPTION` files. +#' - **R** citation files (usually located in `inst/CITATION`). +#' - BibTeX files (with extension `*.bib`). #' -#' @name cff_read -#' @aliases cff -#' @return -#' A `cff` object. Under the hood, a `cff` object is a regular [`list`] object -#' with a special [print()] method. +#' [cff_read()] would try to guess the type of file provided in `path`. However +#' we provide a series of alias for each specific type of file: +#' - [cff_read_cff_citation()], that uses [yaml::read_yaml()]. +#' - [cff_read_description()], using [desc::desc()]. +#' - [cff_read_citation()] uses [utils::readCitationFile()]. +#' - [cff_read_bib()] requires \CRANpkg{bibtex} (>= 0.5.0) and uses +#' [bibtex::read.bib()]. #' -#' @family Core functions +#' @export +#' @rdname cff_read +#' @family reading +#' @seealso #' -#' @param path The path to a `CITATION.cff` file. -#' @param ... Named arguments to be used for creating a [`cff`] object. See -#' **Details**. +#' The underlying functions used for reading external files: +#' - [yaml::read_yaml()] for `CITATION.cff` files. +#' - [desc::desc()] for `DESCRIPTION` files. +#' - [utils::readCitationFile()] for **R** citation files. +#' - [bibtex::read.bib()] for BibTeX files (extension `*.bib`). #' -#' @details +#' @param path Path to a file. +#' @param cff_version The Citation File Format schema version that the +#' `CITATION.cff` file adheres to for providing the citation metadata. +#' @param gh_keywords Logical `TRUE/FALSE`. If the package is hosted on +#' GitHub, would you like to add the repo topics as keywords? +#' @param authors_roles Roles to be considered as authors of the package when +#' generating the [`cff`] object. +#' @param encoding Encoding to be assumed for `path`. See [readLines()]. +#' @param meta A list of package metadata as obtained by +#' [utils::packageDescription()] or `NULL` (the default). See **Details**. +#' @param ... Arguments to be passed to other functions (i.e. to +#' [yaml::read_yaml()], [bibtex::read.bib()], etc.). #' -#' This object can be manipulated using [cff_create()]. +#' @return +#' A [`cff`] object. In the case of [cff_read_cff_citation()] and +#' [cff_read_description()] a full and (potentially) valid `cff` object. #' -#' **Note that** this function reads `CITATION.cff` files. If you want to -#' create `cff` objects from DESCRIPTION files use [cff_create()]. #' -#' If no additional `...` parameters are supplied (the default behavior), -#' a minimal valid `cff` object is created. Valid parameters are those -#' specified on [cff_schema_keys()]: +#' In the case of [cff_read_bib()] and [cff_read_citation()], the result is +#' the `cff` version of a [bibentry()] object (i.e. a bibliographic reference), +#' that can be used to complement another `cff` object. See +#' `vignette("bibtex_cff", "cffr")` to get further insights on how this +#' conversion is performed. #' #' +#' @references #' -#' ```{r, echo=FALSE} +#' - R Core Team (2023). _Writing R Extensions_. +#' #' +#' - Hernangomez D (2022). "BibTeX and CFF, a potential crosswalk." +#' *The cffr package, Vignettes*. \doi{10.21105/joss.03900}, +#' . #' -#' valid_keys <- cff_schema_keys() +#' @details #' -#' knitr::kable(valid_keys, col.names = "**valid cff keys**") +#' # The `meta` object #' +#' Section 1.9 CITATION files of *Writing R Extensions* (R Core Team 2023) +#' specifies how to create dynamic `CITATION` files using `meta` object, hence +#' the `meta` argument in [cff_read_citation()] may be needed for reading +#' some files correctly. #' -#' ``` -#' @export #' @examples #' -#' # Blank cff -#' cff() +#' # Create cff object from cff file #' -#' # From file -#' cff_read(system.file("examples/CITATION_basic.cff", +#' from_cff_file <- cff_read(system.file("examples/CITATION_basic.cff", #' package = "cffr" #' )) #' -#' # Use custom params -#' test <- cff( -#' title = "Manipulating files", -#' keywords = c("A", "new", "list", "of", "keywords"), -#' authors = list(cff_parse_person("New author")) -#' ) -#' test -#' \donttest{ -#' # Would fail -#' cff_validate(test) -#' -#' -#' # Modify with cff_create -#' new <- cff_create(test, keys = list( -#' "cff-version" = "1.2.0", -#' message = "A blank file" +#' head(from_cff_file, 7) +#' +#' # Create cff object from DESCRIPTION +#' from_desc <- cff_read(system.file("examples/DESCRIPTION_basic", +#' package = "cffr" #' )) -#' new #' -#' # Would pass -#' cff_validate(new) +#' from_desc +#' +#' # Create cff object from BibTex +#' +#' if (requireNamespace("bibtex", quietly = TRUE)) { +#' from_bib <- cff_read(system.file("examples/example.bib", +#' package = "cffr" +#' )) +#' +#' # First item only +#' from_bib[[1]] #' } -cff_read <- function(path) { - cffobj <- cff(path = path) +#' # Create cff object from CITATION +#' from_citation <- cff_read(system.file("CITATION", package = "cffr")) +#' +#' # First item only +#' from_citation[[1]] +#' +cff_read <- function(path, ...) { + if (length(path) > 1) { + cli::cli_abort( + "Use a single value, {.arg path} has length {.val {length(path)}}" + ) + } + + if (!file.exists(path)) { + cli::cli_abort( + paste( + "{.file {path}} does not exist. ", + "Check the {.file {dirname(path)}} directory" + ) + ) + } + filetype <- guess_type_file(path) + + if (is.null(filetype)) { + cli::cli_abort( + paste0( + "Don't recognize the file type of {.file {path}}.", + " Use a specific function (e.g. {.fn cffr:cff_read_description}" + ) + ) + } + + endobj <- switch(filetype, + "cff_citation" = cff_read_cff_citation(path, ...), + "description" = cff_read_description(path, ...), + "bib" = cff_read_bib(path, ...), + "citation" = cff_read_citation(path, ...), + NULL + ) - return(cffobj) + endobj } -#' @rdname cff_read #' @export -cff <- function(path, ...) { - if (!missing(path) && is_cff(path)) { - return(path) +#' @rdname cff_read +cff_read_cff_citation <- function(path, ...) { + if (!file.exists(path)) { + cli::cli_abort( + paste( + "{.file {path}} does not exist. ", + "Check the {.file {dirname(path)}} directory" + ) + ) } - # Capture args - cffobj <- list(...) - - if (!missing(path)) { - stopifnotexists(path) - stopifnotcff(path) - cffobj <- yaml::read_yaml(path) - } else if (length(cffobj) != 0) { - cffobj <- fuzzy_keys(cffobj) + cffobj <- yaml::read_yaml(path, ...) + new_cff(cffobj) +} - cffobj <- cffobj - } else { - # If nothing is provided use a minimal cff - path <- system.file("examples/CITATION_skeleton.cff", - package = "cffr" +#' @export +#' @rdname cff_read +cff_read_description <- function(path, cff_version = "1.2.0", + gh_keywords = TRUE, + authors_roles = c("aut", "cre"), ...) { + if (!file.exists(path)) { + cli::cli_abort( + paste( + "{.file {path}} does not exist. ", + "Check the {.file {dirname(path)}} directory" + ) ) - cffobj <- yaml::read_yaml(path) } - cffobj <- drop_null(cffobj) - cffobj <- as.cff(cffobj) + pkg <- desc::desc(path) + pkg$coerce_authors_at_r() - return(cffobj) -} + msg <- paste0( + 'To cite package "', pkg$get("Package"), + '" in publications use:' + ) + list_fields <- list( + "cff-version" = cff_version, + message = msg, + type = "software", + title = parse_desc_title(pkg), + version = parse_desc_version(pkg), + authors = parse_desc_authors(pkg, authors_roles = authors_roles), + abstract = parse_desc_abstract(pkg), + repository = parse_desc_repository(pkg), + "repository-code" = parse_desc_urls(pkg)$repo, + url = parse_desc_urls(pkg)$url, + identifiers = parse_desc_urls(pkg)$identifiers, + "date-released" = parse_desc_date_released(pkg), + contact = parse_desc_contacts(pkg), + keywords = parse_desc_keywords(pkg), + license = unlist(parse_desc_license(pkg)) + ) + if (gh_keywords) { + ghtopics <- parse_ghtopics(list_fields) + list_fields$keywords <- unique(c(list_fields$keywords, ghtopics)) + } + + new_cff(list_fields) +} -#' @rdname cff_read -#' -#' @param x a character string for the [`as.cff`] default method -#' #' @export -#' -#' @examples -#' -#' -#' # Convert a list to "cff" object -#' cffobj <- as.cff(list( -#' "cff-version" = "1.2.0", -#' title = "Manipulating files" -#' )) -#' -#' class(cffobj) -#' -#' # Nice display thanks to yaml package -#' cffobj -as.cff <- function(x) { - if (is_cff(x)) { - return(x) +#' @rdname cff_read +cff_read_citation <- function(path, meta = NULL, ...) { + if (!file.exists(path)) { + cli::cli_abort( + paste( + "{.file {path}} does not exist. ", + "Check the {.file {dirname(path)}} directory" + ) + ) + } + + if (!any(is.null(meta), inherits(meta, "packageDescription"))) { + # nolint start + # Object for cli only + ex <- packageDescription("cffr") + # nolint end + + cli::cli_alert_warning( + paste0( + "{.arg meta} should be {.val NULL} or {.obj_type_friendly {ex}}", + " not {.obj_type_friendly {meta}}. Using {.arg meta = NULL}" + ) + ) + meta <- NULL } - # Clean all strings recursively + new_meta <- clean_package_meta(meta) + the_cit <- try(utils::readCitationFile(path, meta = new_meta), silent = TRUE) - x <- rapply(x, function(x) { - if (is.list(x) || length(x) > 1) { - return(x) + # If error then new try + if (inherits(the_cit, "try-error")) { + cli::cli_alert_warning( + paste0( + "It was not possible to read {.file {path}} with the {.arg meta} ", + "provided. Trying with {.code packageDescription('base')}" + ) + ) + new_meta <- packageDescription("base") + the_cit <- try(utils::readCitationFile(path, meta = new_meta), + silent = TRUE + ) + # nocov start + if (inherits(the_cit, "try-error")) { + cli::cli_alert_danger( + "Can't read {.file path}, returning {.val NULL}" + ) + return(NULL) } - return(clean_str(x)) - }, - how = "list" - ) + # nocov end + } + tocff <- as_cff(the_cit) - # Remove NULLs - x <- drop_null(x) + tocff +} - # Remove duplicated names - x <- x[!duplicated(names(x))] +#' @export +#' @family bibtex +#' @rdname cff_read +cff_read_bib <- function(path, encoding = "UTF-8", ...) { + if (!file.exists(path)) { + cli::cli_abort( + paste( + "{.file {path}} does not exist. ", + "Check the {.file {dirname(path)}} directory" + ) + ) + } + + # nocov start + if (!requireNamespace("bibtex", quietly = TRUE)) { + msg <- paste0( + "{.pkg bibtex} package required for using this function: ", + '{.run install.packages("bibtex")}' + ) + cli::cli_abort(msg) + } + # nocov end + + # Read from tempfile + read_bib <- bibtex::read.bib(file = path, encoding = encoding, ...) - # Now apply cff class to nested lists - x <- lapply(x, rapply_cff) - class(x) <- "cff" - x + tocff <- as_cff(read_bib) + tocff } +# Internal safe ---- +#' Internal version of cff_read_citation, safe +#' @noRd +cff_safe_read_citation <- function(desc_path, cit_path) { + if (!file.exists(cit_path) || !file.exists(desc_path)) { + return(NULL) + } + # Create meta + meta <- desc_to_meta(desc_path) + meta <- clean_package_meta(meta) -# Print method -#' @export -print.cff <- function(x, ...) { - cat(yaml::as.yaml(x)) + the_cit <- try(utils::readCitationFile(cit_path, meta = meta), silent = TRUE) + # Try + if (inherits(the_cit, "try-error")) { + return(NULL) + } + + # Need to be named here + tocff <- as_cff(the_cit) + tocff } -# c method -# Based on c.person (utils package) -# https://github.com/wch/r-source/blob/trunk/src/library/utils/R/citation.R +# Helpers ---- -#' @export -c.cff <- - function(..., recursive = FALSE) { - args <- list(...) - args <- lapply(args, unclass) - rval <- do.call("c", args) - class(rval) <- "cff" - rval +guess_type_file <- function(path) { + if (grepl("\\.cff$", path, ignore.case = TRUE)) { + return("cff_citation") + } + if (grepl("\\.bib$", path, ignore.case = TRUE)) { + return("bib") + } + if (grepl("citat", path, ignore.case = TRUE)) { + return("citation") + } + if (grepl("desc", path, ignore.case = TRUE)) { + return("description") } -# Helper---- + return(NULL) +} -#' Recursively clean lists and assign cff classes -#' to all nested lists -#' -#' +#' Parse and clean data from DESCRIPTION to create metadata #' @noRd -rapply_cff <- function(x) { - if (inherits(x, "cff")) { - return(x) +clean_package_meta <- function(meta) { + if (!inherits(meta, "packageDescription")) { + # Add encoding + meta <- list() + meta$Encoding <- "UTF-8" + return(meta) } - if (is.list(x) && length(x) > 0) { - x <- drop_null(x) - x <- lapply(x, rapply_cff) - return(structure(x, class = "cff")) + # Convert to a desc object + + # First write to a dcf file + tmp <- tempfile("DESCRIPTION") + meta_unl <- unclass(meta) + write.dcf(meta_unl, tmp) + pkg <- desc::desc(tmp) + pkg$coerce_authors_at_r() + # Extract package data + meta <- pkg$get(desc::cran_valid_fields) + + # Clean missing and drop empty fields + meta <- drop_null(lapply(meta, clean_str)) + + # Check encoding + if (!is.null(meta$Encoding)) { + meta <- lapply(meta, iconv, from = meta$Encoding, to = "UTF-8") } else { - return(x) + meta$Encoding <- "UTF-8" } + unlink(tmp, force = TRUE) + meta +} + + + +# Convert a DESCRIPTION object to meta object using desc package +desc_to_meta <- function(x) { + src <- x + my_meta <- desc::desc(src) + my_meta$coerce_authors_at_r() + + + # As list + my_meta_l <- my_meta$get(desc::cran_valid_fields) + my_meta_l <- as.list(my_meta_l) + v_nas <- vapply(my_meta_l, is.na, logical(1)) + my_meta_l <- my_meta_l[!v_nas] + + meta_proto <- packageDescription("cffr") + + class(my_meta_l) <- class(meta_proto) + attr(my_meta_l, "file") <- x + + my_meta_l } diff --git a/R/cff_read_bib_text.R b/R/cff_read_bib_text.R new file mode 100644 index 00000000..e615632a --- /dev/null +++ b/R/cff_read_bib_text.R @@ -0,0 +1,86 @@ +#' Read BibTeX markup as a [`cff`] object +#' +#' @description +#' Convert a [`character`][character()] representing a BibTeX entry to a +#' [`cff`] object. +#' +#' @family bibtex +#' @family reading +#' @seealso +#' [cff_read_bib()] for reading `*.bib` files. +#' +#' @export +#' +#' @param x A vector of `character` objects with the full BibTeX string. +#' @param encoding Encoding to be assumed for `x`, see [readLines()]. +#' @param ... Arguments passed on to [cff_read_bib()]. +#' @inheritDotParams cff_read_bib -path +#' +#' @return +#' +#' ```{r child = "man/chunks/value.Rmd"} +#' ``` +#' +#' @details +#' This is a helper function that writes `x` to a `*.bib` file and reads it with +#' [cff_read_bib()]. +#' +#' This function requires \CRANpkg{bibtex} (>= 0.5.0) and uses +#' [bibtex::read.bib()]. +#' +#' @examples +#' if (requireNamespace("bibtex", quietly = TRUE)) { +#' x <- c( +#' "@book{einstein1921, +#' title = {Relativity: The Special and the General Theory}, +#' author = {Einstein, Albert}, +#' year = 1920, +#' publisher = {Henry Holt and Company}, +#' address = {London, United Kingdom}, +#' isbn = 9781587340925 +#' }", +#' "@misc{misc-full, +#' title = {Handing out random pamphlets in airports}, +#' author = {Joe-Bob Missilany}, +#' year = 1984, +#' month = oct, +#' note = {This is a full MISC entry}, +#' howpublished = {Handed out at O'Hare} +#' }" +#' ) +#' +#' +#' cff_read_bib_text(x) +#' } +cff_read_bib_text <- function(x, encoding = "UTF-8", ...) { + # Validations + if (!inherits(x, "character")) { + cli::cli_abort( + paste0( + "{.arg x} should be a {.cls character}, not a ", + "{.cls {class(x)}}." + ) + ) + } + + if (any(grepl("\\.bib$", x, ignore.case = TRUE))) { + cli::cli_alert_warning( + paste0("{.arg x} seems to be a {.val .bib} file, not a BibTeX entry.") + ) + cli::cli_alert_info("Reading {.arg x} with {.fn cffr:cff_read_bib}") + the_cff <- cff_read_bib(x, encoding = encoding, ...) + return(the_cff) + } + + if (!any(grepl("^@", x))) { + cli::cli_alert_warning( + paste0("{.arg x} doesn't look as a BibTeX entry. Check the results.") + ) + } + # Write x to a tempfile + file <- tempfile(fileext = ".bib") + writeLines(x, file) + the_cff <- cff_read_bib(file, encoding = encoding, ...) + unlink(file) + the_cff +} diff --git a/R/cff_validate.R b/R/cff_validate.R index ceaa3110..cbf73f30 100644 --- a/R/cff_validate.R +++ b/R/cff_validate.R @@ -13,7 +13,7 @@ #' ``` #' @export #' -#' @family Core functions +#' @family core #' #' @seealso #' ```{r, echo=FALSE, results='asis'} @@ -26,10 +26,10 @@ #' ``` #' #' @return A message indicating the result of the validation and an invisible -#' value `TRUE/FALSE`. On error, the results would have an attribute `"errors` -#' containing the error summary (see **Examples** and [attr()]). +#' value `TRUE/FALSE`. On error, the results would have an attribute +#' `"errors"` containing the error summary (see **Examples** and [attr()]). #' -#' @param x This is expected to be either a [`cff`] object created +#' @param x This is expected to be either a `cff` object created #' with [cff_create()] or the path to a `CITATION.cff` file to be validated. #' @inheritParams cff_write #' diff --git a/R/cff_write.R b/R/cff_write.R index 31865a61..d1dd21e2 100644 --- a/R/cff_write.R +++ b/R/cff_write.R @@ -7,21 +7,22 @@ #' #' This function writes out a `CITATION.cff` file for a given package. This #' function is basically a wrapper around [cff_create()] to both create the -#' [`cff`] object and writes it out to a YAML-formatted file in one command. +#' [`cff`] object and writes it out to a YAML-formatted file in +#' one command. #' -#' @family Core functions +#' @family writing #' #' @param x The source that would be used for generating #' the `CITATION.cff` file. It could be: -#' * A missing value. That would retrieve the DESCRIPTION -#' file on your in-development package. -#' * A [`cff`] object, +#' * A missing value. That would retrieve the `DESCRIPTION` file on your +#' in-development package. +#' * A `cff` object, #' * The name of an installed package (`"jsonlite"`), or -#' * Path to a DESCRIPTION file (`"*/DESCRIPTION*"`). +#' * Path to a DESCRIPTION file (`"./DESCRIPTION"`). #' #' @param outfile The name and path of the `CITATION.cff` to be created. #' -#' @param keys List of additional keys to add to the [`cff`] object. See +#' @param keys List of additional keys to add to the `cff` object. See #' [cff_create()] for details and examples. #' #' @param validate Logical `TRUE/FALSE`. Should the new file be validated using @@ -37,7 +38,7 @@ #' #' @inheritParams cff_create #' -#' @return A `CITATION.cff` file and an (invisible) [`cff`] object. +#' @return A `CITATION.cff` file and an (invisible) `cff` object. #' #' @seealso #' ```{r, echo=FALSE, results='asis'} @@ -48,6 +49,9 @@ #' #' #' ``` +#' This function unifies the workflow [cff_create()] + [cff_write()] + +#' [cff_validate()]. +#' #' @examples #' \donttest{ #' tmpfile <- tempfile(fileext = ".cff") @@ -62,15 +66,10 @@ #' #' When creating and writing a `CITATION.cff` for the first time, the function #' adds "CITATION.cff" to ".Rbuildignore". -cff_write <- function(x, - outfile = "CITATION.cff", - keys = list(), - cff_version = "1.2.0", - gh_keywords = TRUE, - dependencies = TRUE, - validate = TRUE, - verbose = TRUE, - authors_roles = c("aut", "cre")) { +cff_write <- function(x, outfile = "CITATION.cff", keys = list(), + cff_version = "1.2.0", gh_keywords = TRUE, + dependencies = TRUE, validate = TRUE, + verbose = TRUE, authors_roles = c("aut", "cre")) { # On missing use package root if (missing(x)) x <- getwd() diff --git a/R/cff_write_misc.R b/R/cff_write_misc.R new file mode 100644 index 00000000..ac957920 --- /dev/null +++ b/R/cff_write_misc.R @@ -0,0 +1,167 @@ +#' Export **R** objects to different file types +#' +#' @description +#' +#' Export **R** objects representing citations to specific file types: +#' - [cff_write_bib()] creates a `.bib` file. +#' - [cff_write_citation()] creates a **R** citation file as explained in +#' Section 1.9 CITATION files of *Writing R Extensions* (R Core Team 2023). +#' +#' @param x A [`bibentry`][bibentry()] or a [`cff`] object. +#' @param file Name of the file to be created. If `NULL` it would display the +#' lines to be written. +#' @param append Whether to append the entries to an existing file or not. +#' @param verbose Display informative messages +#' @param ascii Whether to write the entries using ASCII characters only or not. +#' @inheritDotParams as_bibentry +#' +#' @references +#' +#' - R Core Team (2023). _Writing R Extensions_. +#' +#' +#' @export +#' @rdname cff_write_misc +#' @family bibtex +#' @family writing +#' +#' @return +#' Writes the corresponding file specified on the `file` parameter. +#' +#' @details +#' +#' When `x` is a `cff` object it would be converted to `bibentry` using +#' [as_bibentry()]. +#' +#' For security reasons, if the file already exists the function would create +#' a backup copy on the same directory. +#' +#' @seealso +#' `vignette("bibtex_cff", "cffr")`, [knitr::write_bib()] and the +#' following packages: +#' - \CRANpkg{bibtex}. +#' - \CRANpkg{RefManageR} +#' - \CRANpkg{rbibutils} +#' +#' @examples +#' +#' bib <- bibentry("Misc", +#' title = "My title", +#' author = "Fran Pérez" +#' ) +#' +#' my_temp_bib <- tempfile(fileext = ".bib") +#' +#' cff_write_bib(bib, file = my_temp_bib) +#' +#' cat(readLines(my_temp_bib), sep = "\n") +#' +#' cff_write_bib(bib, file = my_temp_bib, ascii = TRUE, append = TRUE) +#' +#' cat(readLines(my_temp_bib), sep = "\n") +cff_write_bib <- function(x, file = tempfile(fileext = ".bib"), append = FALSE, + verbose = TRUE, ascii = FALSE, ...) { + if (inherits(x, "cff")) { + x <- as_bibentry(x, ...) + } + + if (!inherits(x, "bibentry")) { + cli::cli_abort( + paste0( + "{.arg x} should be a {.cls bibentry} object, not a ", + "{.cls {class(x)}} object." + ) + ) + } + + btex <- toBibtex(x) + + if (ascii) { + # Base encoding as per file() + btex <- encoded_utf_to_latex(btex) + class(btex) <- "Bibtex" + } else { + btex <- enc2utf8(btex) + } + + if (tools::file_ext(file) != "bib") file <- paste0(file, ".bib") + write_lines_msg(btex, file, verbose, append) + return(invisible(NULL)) +} + +#' @export +#' @rdname cff_write_misc +#' @name cff_write_citation +#' @examples +#' +#' # Create a CITATION file +#' +#' # Use a system file +#' f <- system.file("examples/preferred-citation-book.cff", package = "cffr") +#' a_cff <- cff_read(f) +#' +#' out <- file.path(tempdir(), "CITATION") +#' cff_write_citation(a_cff, file = out) +#' +#' # Check by reading, use meta object +#' meta <- packageDescription("cffr") +#' meta$Encoding <- "UTF-8" +#' +#' utils::readCitationFile(out, meta) +cff_write_citation <- function(x, file = tempfile("CITATION_"), + append = FALSE, verbose = TRUE, ...) { + if (inherits(x, "cff")) { + x <- as_bibentry(x, ...) + } + + if (!inherits(x, "bibentry")) { + cli::cli_abort( + paste0( + "{.arg x} should be a {.cls bibentry} object, not a ", + "{.cls {class(x)}} object." + ) + ) + } + + bentr <- format(x, style = "R") + bentr <- c("", bentr) + write_lines_msg(bentr, file, verbose, append) + return(invisible(NULL)) +} + + +write_lines_msg <- function(lines, file, verbose, append) { + # Check that the directory exists, if not create + dir <- dirname(path.expand(file)) + if (!dir.exists(dir)) { + if (verbose) cli::cli_alert_info("Creating directory {.path {dir}}") + dir.create(dir, recursive = TRUE) + } + + # If exists creates a backup + if (file.exists(file)) { + for (i in seq(1, 100)) { + f <- paste0(file, ".bk", i) + if (!file.exists(f)) break + } + + if (verbose) { + cli::cli_alert_info( + "Creating a backup of {.file {file}} in {.file {f}}" + ) + } + file.copy(file, f) + } + + + fh <- file(file, encoding = "UTF-8", open = ifelse(append, "a+", "w+")) + on.exit(if (isOpen(fh)) close(fh)) + if (verbose) { + cli::cli_alert_info("Writing {length(lines)} entr{?y/ies} ...") + } + + writeLines(lines, fh) + if (verbose) { + cli::cli_alert_success("Results written to {.file {file}}") + } +} diff --git a/R/cffr-package.R b/R/cffr-package.R index 9a858619..3a4d0134 100644 --- a/R/cffr-package.R +++ b/R/cffr-package.R @@ -8,5 +8,5 @@ NULL # import stuffs #' @importFrom utils download.file as.person read.csv person capture.output #' installed.packages packageDescription citation available.packages -#' modifyList toBibtex bibentry +#' modifyList toBibtex bibentry head tail NULL diff --git a/R/data.R b/R/data.R index 3fbf9ac6..34096b41 100644 --- a/R/data.R +++ b/R/data.R @@ -4,6 +4,8 @@ #' on CRAN packages and its (approximate) match on the #' [SPDX License List](https://spdx.org/licenses/). #' +#' @family datasets +#' #' @format A data frame with `r nrow(cran_to_spdx)` rows and 2 variables: #' #' * `r names(cran_to_spdx)[1]`: A valid `License` string on CRAN. diff --git a/R/deprecated.R b/R/deprecated.R index 07b26ba9..f468f415 100644 --- a/R/deprecated.R +++ b/R/deprecated.R @@ -1,15 +1,15 @@ #' Previous API: Create BibTeX entries from several sources #' #' @description -#' `r lifecycle::badge('superseded')` -#' Please use [cff_to_bibentry()] instead. +#' `r lifecycle::badge('deprecated')` Please use [as_bibentry()] instead. #' -#' @rdname previous_cff_to_bib -#' @inheritParams cff_to_bibentry +#' @rdname deprecated_cff_to_bib +#' @inheritParams as_bibentry #' @export #' @keywords internal +#' @family deprecated #' -#' @return See [cff_to_bibentry()] +#' @return See [as_bibentry()]. #' @examples #' \donttest{ #' # From a cff object @@ -18,15 +18,281 @@ #' cff_object #' #' # bibentry object -#' bib <- cff_to_bibentry(cff_object) +#' bib <- as_bibentry(cff_object) #' } cff_extract_to_bibtex <- function(x, what = c("preferred", "references", "all")) { if (requireNamespace("lifecycle", quietly = TRUE)) { lifecycle::deprecate_soft( "0.5.0", "cff_extract_to_bibtex()", - "cff_to_bibentry()" + details = "Function renamed, use `as_bibentry()` instead." ) } - cff_to_bibentry(x, what) + as_bibentry(x, what) +} + +#' @rdname deprecated_cff_to_bib +#' @export +#' @keywords internal +cff_to_bibtex <- function(x, + what = c("preferred", "references", "all")) { + if (requireNamespace("lifecycle", quietly = TRUE)) { + lifecycle::deprecate_soft( + "1.0.0", "cff_extract_to_bibtex()", + details = "Function renamed, use `as_bibentry()` instead." + ) + } + as_bibentry(x, what) +} + +#' Previous API: Create a [`cff`] object from BibTeX entries +#' +#' @description +#' +#' `r lifecycle::badge('deprecated')` Please use either [cff_read_bib()] or +#' [cff_read_bib_text()] instead. +#' +#' @rdname deprecated_cff_from_bib +#' @export +#' @keywords internal +#' @family deprecated +#' +#' @param x The source that would be used for generating the +#' [`cff`] object. Must be `character` object indicating either: +#' - The path to a BibTeX file. +#' - A vector of characters with the full BibTeX string. See **Examples**. +#' @param encoding Encoding to be assumed for `x`. See [readLines()]. +#' @param ... Other arguments passed to [bibtex::read.bib()]. +#' +#' +#' @return +#' +#' See [cff_read_bib()] from reading `*.bib` files and [cff_read_bib_text()] +#' for reading a `character` object representing a BibTeX entry. +#' +#' +#' +#' @examples +#' if (requireNamespace("bibtex", quietly = TRUE)) { +#' x <- c( +#' "@book{einstein1921, +#' title = {Relativity: The Special and the General Theory}, +#' author = {Einstein, Albert}, +#' year = 1920, +#' publisher = {Henry Holt and Company}, +#' address = {London, United Kingdom}, +#' isbn = 9781587340925 +#' }", +#' "@misc{misc-full, +#' title = {Handing out random pamphlets in airports}, +#' author = {Joe-Bob Missilany}, +#' year = 1984, +#' month = oct, +#' note = {This is a full MISC entry}, +#' howpublished = {Handed out at O'Hare} +#' }" +#' ) +#' +#' cff_read_bib_text(x) +#' +#' # From a file +#' +#' x2 <- system.file("examples/example.bib", package = "cffr") +#' cff_read_bib(x2) +#' } +cff_from_bibtex <- function(x, encoding = "UTF-8", ...) { + if (length(x) == 1 && file.exists(x)) { + if (requireNamespace("lifecycle", quietly = TRUE)) { + lifecycle::deprecate_soft( + "1.0.0", "cff_from_bibtex()", "cff_read_bib()" + ) + } + + # Read bib file + return(cff_read_bib(x, encoding = encoding, ...)) + } + + if (requireNamespace("lifecycle", quietly = TRUE)) { + lifecycle::deprecate_soft( + "1.0.0", "cff_from_bibtex()", "cff_read_bib_text()" + ) + } + cff_read_bib_text(x, encoding = encoding, ...) +} + + +#' Previous API: Write files +#' +#' @description +#' +#' `r lifecycle::badge('deprecated')` Please use [cff_write_bib()] or +#' [cff_write_citation()] instead. +#' +#' @rdname deprecated_write +#' @export +#' @keywords internal +#' @family deprecated +#' @inheritParams cff_write_bib +#' +#' @return Write a file. +#' +#' @seealso +#' - [cff_write_bib()] for writing `*.bib` files. +#' - [cff_write_citation()] for writing **R** `CITATION` files. +#' +#' @examples +#' +#' bib <- bibentry("Misc", +#' title = "My title", +#' author = "Fran Pérez" +#' ) +#' +#' my_temp_bib <- tempfile(fileext = ".bib") +#' +#' cff_write_bib(bib, file = my_temp_bib) +#' +#' cat(readLines(my_temp_bib), sep = "\n") +#' +#' cff_write_bib(bib, file = my_temp_bib, ascii = TRUE, append = TRUE) +#' +#' cat(readLines(my_temp_bib), sep = "\n") +write_bib <- function(x, + file = tempfile(), + append = FALSE, + verbose = TRUE, + ascii = FALSE) { + if (requireNamespace("lifecycle", quietly = TRUE)) { + lifecycle::deprecate_soft( + "1.0.0", "write_bib()", "cff_write_bib()" + ) + } + + cff_write_bib(x, file, append, verbose, ascii) +} + +#' @rdname deprecated_write +#' @export +write_citation <- function(x, + file = "./inst/CITATION", + append = FALSE, + verbose = TRUE, + ...) { + if (requireNamespace("lifecycle", quietly = TRUE)) { + lifecycle::deprecate_soft( + "1.0.0", "write_citation()", "cff_write_citation()" + ) + } + cff_write_citation(x, file, append, verbose, ...) +} + + +#' Previous API: Parse a `person` to [`cff`] +#' +#' @description +#' +#' `r lifecycle::badge('deprecated')` Please use [as_cff_person()] +#' +#' @rdname deprecated_cff_person +#' @export +#' @keywords internal +#' @family deprecated +#' +#' @inheritParams as_cff_person +#' @return A person in format `cff`. +#' +#' @seealso [as_cff_person()] +#' +#' @examples +#' # Create a person object +#' a_person <- person( +#' given = "First", family = "Author", +#' role = c("aut", "cre"), +#' email = "first.last@example.com", comment = c( +#' ORCID = "0000-0001-8457-4658", +#' affiliation = "An affiliation" +#' ) +#' ) +#' +#' a_person +#' +#' cff_person <- as_cff_person(a_person) +#' +#' cff_person +#' +#' # Back to person object with S3 Method +#' as.person(cff_person) +#' +#' # Parse a string +#' a_str <- paste0( +#' "Julio Iglesias ", +#' "()" +#' ) +#' as_cff_person(a_str) +#' +#' # Several persons +#' persons <- c(person("Clark", "Kent"), person("Lois", "Lane")) +#' +#' as_cff_person(persons) +#' +#' # Or you can use BibTeX style if you prefer +#' +#' x <- "Frank Sinatra and Dean Martin and Davis, Jr., Sammy and Joey Bishop" +#' +#' as_cff_person(x) +#' +#' as_cff_person("Herbert von Karajan") +cff_parse_person <- function(person) { + if (requireNamespace("lifecycle", quietly = TRUE)) { + lifecycle::deprecate_soft( + "1.0.0", "cff_parse_person()", "as_cff_person()" + ) + } + as_cff_person(person) +} + +#' @rdname deprecated_cff_person +#' @export +#' +cff_parse_person_bibtex <- function(person) { + if (requireNamespace("lifecycle", quietly = TRUE)) { + lifecycle::deprecate_soft( + "1.0.0", "cff_parse_person_bibtex()", "as_cff_person()" + ) + } + as_cff_person(person) +} + +#' Previous API: Parse a `bibentry` to `cff` +#' +#' @description +#' +#' `r lifecycle::badge('deprecated')` Please use [as_cff.bibentry()] method +#' +#' @rdname deprecated_cff_bibentry +#' @export +#' @keywords internal +#' @family deprecated +#' +#' @param bib A `bibentry` object. +#' @return A `bibentry` in format `cff`. +#' +#' @seealso [as_cff.bibentry()] +#' +#' @examples +#' +#' bib <- citation("base") +#' bib +#' +#' +#' # To cff +#' bib_to_cff <- as_cff(bib) +#' bib_to_cff +#' +cff_parse_citation <- function(bib) { + if (requireNamespace("lifecycle", quietly = TRUE)) { + lifecycle::deprecate_soft( + "1.0.0", "cff_parse_citation()", "as_cff.bibentry()" + ) + } + as_cff(bib) } diff --git a/R/docs.R b/R/docs.R new file mode 100644 index 00000000..a9db5e3c --- /dev/null +++ b/R/docs.R @@ -0,0 +1,16 @@ +#' The `cff` class +#' +#' @name cff-class +#' @keywords internal +#' +#' @family s3method +#' +#' @description +#' +#' ```{r child = "man/chunks/cffclass.Rmd"} +#' ``` +#' +#' @seealso +#' +#' `vignette("cffr", "cffr")` for a hands-on example. +NULL diff --git a/R/utils-bibtex.R b/R/encoded_utf_to_latex.R similarity index 95% rename from R/utils-bibtex.R rename to R/encoded_utf_to_latex.R index cf4f11d2..5258918c 100644 --- a/R/utils-bibtex.R +++ b/R/encoded_utf_to_latex.R @@ -7,7 +7,7 @@ #' #' @param x A string, possibly encoded in UTF-8 encoding system. #' -#' @family BibTeX helpers +#' @family bibtex #' #' @seealso [tools::encoded_text_to_latex()] #' @@ -21,7 +21,7 @@ #' @keywords internal #' @export #' -#' @examplesIf getRversion() >= "4.0.0" +#' @examples #' # Full range of supported characters on R #' library(tools) #' diff --git a/R/parse_citation.R b/R/parse_citation.R index 87d0d65b..802e8014 100644 --- a/R/parse_citation.R +++ b/R/parse_citation.R @@ -1,54 +1,3 @@ -## Parsers ---- - -#' Used for parsing CITATION R-native files -#' @noRd -parse_r_citation <- function(desc_path, cit_path) { - if (!file.exists(cit_path) || !file.exists(desc_path)) { - return(NULL) - } - # Create meta - meta <- parse_package_meta(desc_path) - - # First try - Would normally be enough - parsed <- tryCatch( - utils::readCitationFile(cit_path, meta = meta), - warning = function(cit_path, meta) { - # Avoid warnings - # nocov start - suppressWarnings( - utils::readCitationFile(cit_path, meta = meta) - ) - }, - error = function(x) { - return(NULL) - } - # nocov end - ) - - parsed -} - -#' Parse and clean data from DESCRIPTION to create metadata -#' @noRd -parse_package_meta <- function(desc_path) { - pkg <- desc::desc(desc_path) - pkg$coerce_authors_at_r() - # Extract package data - meta <- pkg$get(desc::cran_valid_fields) - - # Clean missing and drop empty fields - meta <- drop_null(lapply(meta, clean_str)) - - # Check encoding - if (!is.null(meta$Encoding)) { - meta <- lapply(meta, iconv, from = meta$Encoding, to = "UTF-8") - } else { - meta$Encoding <- "UTF-8" - } - - meta -} - ## Building blocks ---- #' BB for doi @@ -190,8 +139,11 @@ building_other_persons <- function(parsed_fields) { toentity_pers <- others[names(others) %in% toent_pers] toentity_pers <- lapply(toentity_pers, function(x) { bibtex <- paste(x, collapse = " and ") + # Unname + names(bibtex) <- NULL - end <- cff_parse_person_bibtex(bibtex) + + end <- as_cff_person(bibtex) # If has names then it should be moved to a lower level on a list if (!is.null(names(end))) end <- list(end) @@ -201,16 +153,7 @@ building_other_persons <- function(parsed_fields) { toperson <- others[names(others) %in% toauto_end] - toperson <- lapply(toperson, cff_parse_person_bibtex) - # This should be vectors, so include on lists - toperson <- lapply(toperson, function(x) { - if (!is.null(names(x))) { - x <- list(x) - } else { - x - } - }) - + toperson <- lapply(toperson, as_cff_person) # Bind and reorder diff --git a/R/utils-create.R b/R/utils-create.R new file mode 100644 index 00000000..951dbb11 --- /dev/null +++ b/R/utils-create.R @@ -0,0 +1,185 @@ +#' Merge the information of a parsed description with a parsed citation +#' @noRd +merge_desc_cit <- function(cffobj, citobj) { + # If no citobj then return null + + if (is.null(citobj)) { + return(cffobj) + } + + # Add doi from citation if missing + if (is.null(cffobj$doi)) { + cffobj$doi <- clean_str(citobj[[1]]$doi) + } + cffobjend <- c(cffobj, + "preferred-citation" = citobj[1], + references = list(citobj[-1]) + ) + + + + # Merge identifiers + oldids <- cffobjend$identifiers + cffobjend$identifiers <- c(citobj[[1]]$identifiers, oldids) + + # Reorder + cffobjfinal <- c( + cffobjend[!names(cffobjend) %in% c("identifiers", "references")], + cffobjend["identifiers"], + cffobjend["references"] + ) + + cffobjfinal <- drop_null(cffobjfinal) + + return(cffobjfinal) +} + +#' Enhance authors info from preferred-citation using metadata from DESCRIPTION +#' @noRd +enhance_pref_authors <- function(cffobjend) { + # Create index of authors extracted from DESCRIPTION (First cff level) + auth_desc <- cffobjend$authors + key_aut_desc <- lapply(auth_desc, function(x) { + l <- list(x["family-names"], x["given-names"], x["name"]) + l <- unlist(drop_null(l)) + tolower(paste0(l, collapse = "")) + }) + names(auth_desc) <- unlist(key_aut_desc) + + # Create index of authors from preferred-citation + auth_pref <- cffobjend$`preferred-citation`$authors + key_aut_cit <- lapply(auth_pref, function(x) { + l <- list(x["family-names"], x["given-names"], x["name"]) + l <- unlist(drop_null(l)) + tolower(paste0(l, collapse = "")) + }) + names(auth_pref) <- unlist(key_aut_cit) + + # Add missing keys to authors + enhancedauth <- lapply(names(auth_pref), function(x) { + newdata <- auth_desc[x] + olddata <- auth_pref[x] + + # New fields only + oldkeys <- names(olddata[[1]]) + newkeys <- names(newdata[[1]]) + fieldstoadd <- newdata[[1]][!newkeys %in% oldkeys] + + newinfo <- c(olddata[[1]], fieldstoadd) + + newinfo + }) + + enhancedauth +} + + +parse_dependencies <- function(desc_path, + instpack = as.character( + installed.packages()[, "Package"] + )) { + # nocov start + if (!is.character(desc_path)) { + return(NULL) + } + if (!file.exists(desc_path)) { + return(NULL) + } + # nocov end + + getdeps <- desc::desc(desc_path) + + deps <- getdeps$get_deps() + + # Adapt version + + deps$version_clean <- gsub("*", "", deps$version, fixed = TRUE) + + # Save copy for later + origdeps <- deps + + # Dedupe rows + deps <- unique(deps[, c("package", "version_clean")]) + + + # Get dependency type and add to scope + scope <- vapply(deps$package, function(x) { + y <- origdeps[origdeps$package == x, "type"] + + y[1] + }, FUN.VALUE = character(1)) + deps$scope <- scope + + av_deps <- deps[deps$package %in% c("R", instpack), ] + + # Get references from DESCRIPTION of dependencies + cff_deps <- lapply(seq_len(nrow(av_deps)), function(y) { + n <- av_deps[y, ] + + if (n$package == "R") { + mod <- as_cff(citation())[[1]] + mod$year <- format(Sys.Date(), "%Y") + } else { + mod <- try(as_cff(citation(n$package, auto = TRUE)[1])[[1]], + silent = TRUE + ) + + if (inherits(mod, "try-error")) { + return(NULL) + } + + # Simplified version of the cff obj + # Avoid cluttering the output + mod$abstract <- mod$title + mod$title <- n$package + } + + mod$type <- "software" + mod$version <- ifelse(is.na(n$version_clean), + NULL, + paste(n$version_clean) + ) + # Get url and repo from package DESCRIPTION + # urls from citation() vary due to auto = TRUE + dfile <- system.file("DESCRIPTION", package = n$package) + + if (file.exists(dfile)) { + pkg <- desc::desc(dfile) + mod$url <- parse_desc_urls(pkg)$url + mod$repository <- parse_desc_repository(pkg) + } + + mod <- drop_null(mod) + + # Get year + date_rel <- mod[["date-released"]] + + if (is.null(date_rel)) { + year <- format(Sys.Date(), "%Y") + } else { + year <- format(as.Date(date_rel), "%Y") + } + + mod$year <- year + mod$notes <- clean_str(n$scope) + + # Re-arrange + mod <- c( + mod[c("type", "title", "abstract", "notes", "url", "repository")], + mod[!names(mod) %in% c( + "type", "title", "abstract", "notes", + "url", "repository" + )] + ) + + mod <- as_cff(mod) + }) + + cff_deps <- drop_null(cff_deps) + + cff_deps <- unique(cff_deps) + + class(cff_deps) <- "cff" + + return(cff_deps) +} diff --git a/R/utils-methods.R b/R/utils-methods.R new file mode 100644 index 00000000..8a0a0d9e --- /dev/null +++ b/R/utils-methods.R @@ -0,0 +1,200 @@ +# Utils for authors---- +make_r_person <- function(x) { + if (is.null(names(x))) { + return(person()) + } + checknames <- grepl("^name$|given-names|family-names", names(x)) + if (!isTRUE(any(checknames))) { + return(person()) + } + # Prepare list + x <- unclass(x) + + # Family is special key + # R Core uses for entity 'given', so do I + # see in citation() + is_entity <- any(grepl("^name$", names(x))) + if (is_entity) { + given <- clean_str(x[["name"]]) + # Extra protect + family <- NULL + } else { + given <- clean_str(x[["given-names"]]) + family <- clean_str(paste( + clean_str(x[["name-particle"]]), clean_str(x[["family-names"]]), + clean_str(x[["name-suffix"]]) + )) + } + + role <- clean_str(x$role) + + # Make comments + x_comments <- x[!names(x) %in% c( + "family-names", "given-names", "name", + "name-particle", "name-suffix", "email", "role" + )] + + x_comments <- lapply(x_comments, clean_str) + x_comments <- unlist(x_comments, use.names = TRUE) + + # Prepare ORCID + x_comments <- gsub("^https://orcid.org/", "", x_comments) + x_comments <- gsub("^http://orcid.org/", "", x_comments) + nm <- gsub("orcid", "ORCID", names(x_comments), fixed = TRUE) + names(x_comments) <- nm + + pers_list <- list( + given = given, + family = family, + role = role, + email = clean_str(x$email), + comment = x_comments + ) + + + do.call(person, pers_list) +} + + +# Utils for df ---- +unnamed_to_df <- function(key, nm) { + key_l <- as.integer(lengths(key)) + m <- matrix(unlist(key), nrow = 1) + df <- as.data.frame(m) + names(df) <- paste0(nm, ".", sprintf("%02d", seq_len(key_l) - 1)) + return(df) +} + +named_to_df <- function(key, nm) { + key_un <- unlist(key) + + + m <- matrix(as.character(key_un), nrow = 1) + df <- as.data.frame(m) + names(df) <- names(key_un) + return(df) +} + +nested_named_to_df <- function(key, nm) { + key_unlist <- key[[1]] + key_len <- seq_len(length(key_unlist)) + + df_l_type3 <- lapply(key_len, function(z) { + df <- cff_to_df(key_unlist[[z]]) + + # Prepend names + names(df) <- paste0(nm, ".", sprintf("%02d", z - 1), ".", names(df)) + return(df) + }) + + df_list_to_df(df_l_type3) +} + +prefcit_to_df <- function(key, nm = "preferred_citation.") { + key_df <- cff_to_df(key[[1]]) + names(key_df) <- paste0(nm, names(key_df)) + return(key_df) +} + +reflist_to_df <- function(key, nm) { + key_unlist <- key[[1]] + key_len <- seq_len(length(key_unlist)) + + prefix_key <- paste0(nm, ".", sprintf("%02d", key_len - 1), ".") + + df_l <- lapply(key_len, function(y) { + key_l <- key_unlist[y] + nm_pref <- prefix_key[y] + + dff <- prefcit_to_df(key_l, nm_pref) + + dff + }) + + final_df <- df_list_to_df(df_l) + + final_df +} + +df_list_to_df <- function(x) { + # Clean NULL + df_l_clean <- x[!vapply(x, is.null, logical(1))] + + final_df <- do.call(cbind, df_l_clean) + return(final_df) +} +cff_to_df <- function(x) { + # CFF has different models + # type 1: unnamed arrays + unnamed_array <- c("keywords", "languages", "patent-states") + + + # type 2: named arrays + named_array <- c( + "conference", "database-provider", "institution", + "location", "publisher" + ) + + + # type 3: nested named arrays + nested_named_array <- c( + "authors", "contact", "editors", "editors-series", + "recipients", "senders", "translators", "identifiers" + ) + + nms <- names(x) + x_len <- seq_len(length(x)) + + + df_l <- lapply(x_len, function(y) { + nm <- nms[y] + + if (nm %in% unnamed_array) { + return(unnamed_to_df(x[y], nm)) + } + if (nm %in% named_array) { + return(named_to_df(x[y], nm)) + } + if (nm %in% nested_named_array) { + return(nested_named_to_df(x[y], nm)) + } + if (nm == "preferred-citation") { + return(prefcit_to_df(x[y])) + } + + if (nm == "references") { + return(reflist_to_df(x[y], nm)) + } + + the_df <- as.data.frame(x[[y]]) + names(the_df) <- gsub("-", "_", nm) + return(the_df) + }) + + final_df <- df_list_to_df(df_l) + + return(final_df) +} + +cff_list_to_df <- function(x) { + # Applicable to lists of persons or references + # Guess type + if (!"type" %in% names(x[[1]])) { + guess <- "person" + } else { + guess <- "reference" + } + + + x_len <- seq_len(length(x)) + df_l <- lapply(x_len, function(y) { + df <- as.data.frame(x[y]) + newnames <- paste0(guess, ".", sprintf("%02d", y - 1), ".", names(df)) + names(df) <- newnames + + df + }) + + df_end <- df_list_to_df(df_l) + df_end +} diff --git a/R/utils-persons.R b/R/utils-persons.R index 441f120e..d45f389b 100644 --- a/R/utils-persons.R +++ b/R/utils-persons.R @@ -260,49 +260,22 @@ bibtex_pers_first_von_last <- function(x) { return(end_list) } -as_person_bibtex <- function(x) { - # Identify the pattern - # It may be one of: - # A. Given von Family - # B. von Family, Given - # C. von Family, Junior, Given - - # Protect commas on brackets to avoid error counting - protected <- gsub(",(?![^\\}]*(\\{|$))", "@comma@", - x, - perl = TRUE - ) +validate_cff_person_fields <- function(parsed_person) { + # Entity of person - commas <- length(grep(",", unlist(strsplit(protected, "|")))) - - if (commas == 0) { - # Case A - end_list <- bibtex_pers_first_von_last(x) - } else if (commas == 1) { - # Case B - end_list <- bibtex_pers_von_last_first(x) - } else if (commas == 2) { - # Case C - end_list <- bibtex_pers_von_last_first_jr(x) - } else { - # Not considered by BibTeX. everything to family - end_list <- list(family = paste(x, collapse = " ")) - } + # Guess entity or person + is_entity <- as.character("name" %in% names(parsed_person)) - # Clean - end_list <- lapply(end_list, function(z) { - if (is.null(z)) { - return(NULL) - } - if (any((is.na(z) | z == ""))) { - return(NULL) - } - - gsub("\\{|\\}", "", z) - }) + # Keep only valid tags - Would depend on entity or person + definition <- switch(is_entity, + "TRUE" = cff_schema_definitions_entity(), + cff_schema_definitions_person() + ) - end_list <- lapply(end_list, clean_str) + parsed_person <- parsed_person[names(parsed_person) %in% definition] + # Duplicates removed + parsed_person <- parsed_person[!duplicated(names(parsed_person))] - return(end_list) + parsed_person } diff --git a/R/parse_description.R b/R/utils-read-description.R similarity index 97% rename from R/parse_description.R rename to R/utils-read-description.R index d26b4e51..798dd6ac 100644 --- a/R/parse_description.R +++ b/R/utils-read-description.R @@ -8,6 +8,9 @@ parse_desc_abstract <- function(pkg) { abstract <- clean_str(abstract) abstract <- unname(abstract) + # Convert doi to url + abstract <- gsub(". -#' -#' -#' @examples -#' # Use a system file -#' f <- system.file("examples/preferred-citation-book.cff", package = "cffr") -#' -#' # Write to tmp dir -#' out <- file.path(tempdir(), "CITATION") -#' write_citation(f, file = out) -#' -#' # Check by reading, use meta object -#' -#' meta <- packageDescription("cffr") -#' meta$Encoding <- "UTF-8" -#' -#' utils::readCitationFile(out, meta) -#' -#' -#' # Append to the same file -#' bib2 <- citation() -#' write_citation(bib2, file = out, append = TRUE) -#' -#' utils::readCitationFile(out, meta) -write_citation <- function(x, - file = "./inst/CITATION", - append = FALSE, - verbose = TRUE, - ...) { - if (!inherits(x, "bibentry")) { - x <- cff_to_bibentry(x, ...) - } - - bentr <- format(x, style = "R") - - # Check that the directory exists, if not create - dir <- dirname(path.expand(file)) - if (!dir.exists(dir)) { - if (verbose) cli::cli_alert_info("Creating directory {.path {dir}}") - dir.create(dir, recursive = TRUE) - } - - - # If exists creates a backup - if (file.exists(file)) { - for (i in seq(1, 100)) { - f <- paste0(file, ".bk", i) - if (!file.exists(f)) break - } - - if (verbose) { - cli::cli_alert_info( - "Creating a backup of {.file {file}} in {.file {f}}" - ) - } - file.copy(file, f) - } - - - fh <- file(file, encoding = "UTF-8", open = if (append) { - "a+" - } else { - "w+" - }) - on.exit(if (isOpen(fh)) close(fh)) - if (verbose) { - cli::cli_alert_info("Writing {length(bentr)} entr{?y/ies} ...") - } - # Odd bug in RStudio... add empty lines - writeLines(c("", bentr), fh) - if (verbose) { - cli::cli_alert_success("Results written to {.file {file}}") - } - invisible(x) -} diff --git a/README.md b/README.md index b87bcf35..2b438aed 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ file and the `CITATION` file (if present) of your package. Note that **cffr** works best if your package pass `R CMD check/devtools::check()`. -As per 2024-02-13 there are at least 235 repos on GitHub using **cffr**. +As per 2024-03-03 there are at least 306 repos on GitHub using **cffr**. [Check them out here](https://github.com/search?q=cffr%20path%3A**%2FCITATION.cff&type=code). @@ -545,8 +545,9 @@ test <- cff_create("rmarkdown") given-names: Radford - family-names: Bell given-names: Kendon - - family-names: de Queljoe + - family-names: Queljoe given-names: Matthew + name-particle: de - family-names: Suruceanu given-names: Ion - family-names: Denney @@ -570,6 +571,7 @@ test <- cff_create("rmarkdown") authors: - family-names: Vanderkam given-names: Dan + website: http://dygraphs.com/ - family-names: Allaire given-names: JJ - family-names: Owen @@ -750,6 +752,18 @@ test <- cff_create("rmarkdown") given-names: Davis email: davis@posit.co year: '2024' + - type: software + title: cleanrmd + abstract: 'cleanrmd: Clean Class-Less ''R Markdown'' HTML Documents' + notes: Suggests + url: https://pkg.garrickadenbuie.com/cleanrmd/ + repository: https://CRAN.R-project.org/package=cleanrmd + authors: + - family-names: Aden-Buie + given-names: Garrick + email: garrick@adenbuie.com + orcid: https://orcid.org/0000-0002-7111-0077 + year: '2024' - type: software title: withr abstract: 'withr: Run Code ''With'' Temporarily Modified Global State' diff --git a/codemeta.json b/codemeta.json index 1551c39b..8ba3d173 100644 --- a/codemeta.json +++ b/codemeta.json @@ -129,7 +129,7 @@ "@type": "SoftwareApplication", "identifier": "R", "name": "R", - "version": ">= 3.6.0" + "version": ">= 4.0.0" }, "2": { "@type": "SoftwareApplication", @@ -200,7 +200,7 @@ }, "isPartOf": "https://ropensci.org", "keywords": ["attribution", "citation", "credit", "citation-files", "cff", "metadata", "r", "r-package", "citation-file-format", "rstats", "ropensci", "cran"], - "fileSize": "911.371KB", + "fileSize": "961.96KB", "citation": [ { "@type": "ScholarlyArticle", @@ -286,7 +286,7 @@ "sameAs": "https://doi.org/10.5281/zenodo.5171937" } ], - "releaseNotes": "https://github.com/ropensci/cffr/blob/main/NEWS.md", + "releaseNotes": "https://github.com/ropensci/cffr/blob/master/NEWS.md", "readme": "https://github.com/ropensci/cffr/blob/main/README.md", "contIntegration": ["https://github.com/ropensci/cffr/actions/workflows/check-full.yaml", "https://app.codecov.io/gh/ropensci/cffr", "https://github.com/ropensci/cffr/actions/workflows/cff-validator.yml"], "developmentStatus": ["https://www.repostatus.org/#active", "https://lifecycle.r-lib.org/articles/stages.html#experimental"], diff --git a/inst/WORDLIST b/inst/WORDLIST index 62027bb1..83eac8ca 100644 --- a/inst/WORDLIST +++ b/inst/WORDLIST @@ -3,16 +3,18 @@ Arfon BIBTEXTING BeaST BibLaTeX +BibTex +Bibtex Bitbucket Bliven Boettiger -BugReports CFF CMD Cabunoc Chue CodeMeta DOI +Decoret Druskat Easi Egon @@ -20,6 +22,7 @@ FOSS Fenner GitLab Haines +Hernangomez InBook InCollection InProceedings @@ -39,7 +42,6 @@ Niemeyer ORCID Oren Pandoc -Parsers Patashnik PhDThesis Philipp @@ -51,7 +53,6 @@ Rbuildignore Reproducibility Riederer SPDX -Schemas Spaaks Suárez TechReport @@ -70,7 +71,6 @@ cli codecov codemeta codemetar -coercible crossref doi dois @@ -81,16 +81,15 @@ incollection inproceedings json jsonvalidate -mastersthesis param parsers -phdthesis plaintext pre rOpenSci repo repos rmarkdown +schemas testthat xampl zenodo diff --git a/inst/examples/preferred-citation-book-missing.cff b/inst/examples/preferred-citation-book-missing.cff index 94080e82..84c401ff 100644 --- a/inst/examples/preferred-citation-book-missing.cff +++ b/inst/examples/preferred-citation-book-missing.cff @@ -13,5 +13,5 @@ preferred-citation: given-names: Ed title: "PETSc for Partial Differential Equations: Numerical Solutions in C and Python" url: https://github.com/bueler/p4pdes - isbn: 978111976304 + isbn: '978111976304' year: 2021 diff --git a/man/as_bibentry.Rd b/man/as_bibentry.Rd new file mode 100644 index 00000000..162367b4 --- /dev/null +++ b/man/as_bibentry.Rd @@ -0,0 +1,139 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/as_bibentry.R, R/cff-methods.R +\name{as_bibentry} +\alias{as_bibentry} +\alias{toBibtex.cff} +\title{Create \code{bibentry} objects from several sources} +\usage{ +as_bibentry(x, what = c("preferred", "references", "all")) + +\method{toBibtex}{cff}(object, ..., what = c("preferred", "references", "all")) +} +\arguments{ +\item{x}{The source that would be used for generating +the \code{\link[=bibentry]{bibentry()}} object via \code{cff}. It could be: +\itemize{ +\item A missing value. That would retrieve the DESCRIPTION +file on your in-development package. +\item An existing \code{\link{cff}} object, +\item Path to a CITATION.cff file (\code{"*/CITATION.cff*"}), +\item The name of an installed package (\code{"jsonlite"}), or +\item Path to a DESCRIPTION file (\code{"*/DESCRIPTION*"}). +}} + +\item{what}{Fields to extract. The value could be: +\itemize{ +\item \code{preferred}: This would create a single entry with the main citation +info of the package. +\item \code{references}: Extract all the entries on \code{references}. +\item \code{all}: A combination of the previous two options. This would extract +both the preferred citation info and the references. +}} + +\item{object}{\code{cff} object.} + +\item{...}{Arguments passed to \code{\link[utils:toLatex]{utils::toBibtex()}}.} +} +\value{ +\code{as_bibentry()} returns s \code{bibentry} object (or a list of \code{bibentry} +objects). + +\code{toBibtex.cff()} returns a \code{Bibtex} object that can be printed as BibTeX +markup. +} +\description{ +This function creates \code{bibentry} objects (see \code{\link[utils:bibentry]{utils::bibentry()}}) from +different metadata sources (\code{cff} objects, \code{DESCRIPTION} files, etc.). Note +that a \strong{R} \code{bibentry} object is the representation of a BibTeX entry, +see \strong{Examples} + +The function tries to map the information of the source \code{x} into a \code{cff} +object and performs a mapping of the metadata to BibTeX, according to +\code{vignette("bibtex_cff", "cffr")}. + +The inverse transformation (\code{bibentry} object to \code{cff} reference) can +be done with the corresponding \code{\link[=as_cff]{as_cff()}} method. + +Additionally, it is also provided a method for \code{\link[=toBibtex]{toBibtex()}}, that can +convert \code{\link{cff}} objects to \code{Bibtex} objects as provided by +\code{\link[utils:toLatex]{utils::toBibtex()}}. These objects are character vectors with BibTeX markup. +} +\examples{ +\donttest{ +# From a cff object +cff_object <- cff() + +cff_object + +# bibentry object +bib <- as_bibentry(cff_object) + +class(bib) + +bib + +# Print as bibtex + +toBibtex(bib) + +# Thanks to the S3 Method we can also do + +toBibtex(cff_object) + +# From a CITATION.cff file with options + +path <- system.file("examples/CITATION_complete.cff", package = "cffr") +cff_file <- as_bibentry(path, what = "all") + +toBibtex(cff_file) + +# For an installed package + +installed_package <- as_bibentry("jsonvalidate") + +toBibtex(installed_package) + + +# Use a DESCRIPTION file + +path2 <- system.file("examples/DESCRIPTION_gitlab", package = "cffr") +desc_file <- as_bibentry(path2) + +toBibtex(desc_file) +} +} +\references{ +\itemize{ +\item Patashnik, Oren. "BIBTEXTING" February 1988. +\url{https://osl.ugr.es/CTAN/biblio/bibtex/base/btxdoc.pdf}. +\item Haines, R., & The Ruby Citation File Format Developers. (2021). +\emph{Ruby CFF Library (Version 0.9.0)} (Computer software). +\doi{10.5281/zenodo.1184077}. +\item Hernangomez D (2022). "BibTeX and CFF, a potential crosswalk." +\emph{The cffr package, Vignettes}. \doi{10.21105/joss.03900}, +\url{https://docs.ropensci.org/cffr/articles/bibtex_cff.html}. +} +} +\seealso{ +\code{\link[utils:bibentry]{utils::bibentry()}} + +\code{\link[utils:toLatex]{utils::toBibtex()}} + +Other functions for working with BibTeX format: +\code{\link{cff_read}()}, +\code{\link{cff_read_bib_text}()}, +\code{\link{cff_write_bib}()}, +\code{\link{encoded_utf_to_latex}()} + +Other functions for converting between \strong{R} classes: +\code{\link{as_cff}()}, +\code{\link{as_cff_person}()} + +Other S3 Methods for \code{cff}: +\code{\link{as_cff}()}, +\code{\link{as_cff_person}()}, +\code{\link{cff-class}} +} +\concept{bibtex} +\concept{coercing} +\concept{s3method} diff --git a/man/as_cff.Rd b/man/as_cff.Rd new file mode 100644 index 00000000..74bf9ee7 --- /dev/null +++ b/man/as_cff.Rd @@ -0,0 +1,102 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/as_cff.R +\name{as_cff} +\alias{as_cff} +\alias{as_cff.default} +\alias{as_cff.list} +\alias{as_cff.person} +\alias{as_cff.bibentry} +\alias{as_cff.Bibtex} +\alias{as.cff} +\title{Coerce lists, \code{person} and \code{bibentry} objects to \code{\link{cff}}} +\usage{ +as_cff(x, ...) + +\method{as_cff}{default}(x, ...) + +\method{as_cff}{list}(x, ...) + +\method{as_cff}{person}(x, ...) + +\method{as_cff}{bibentry}(x, ...) + +\method{as_cff}{Bibtex}(x, ...) +} +\arguments{ +\item{x}{A \code{person}, \code{bibentry} or other object that could be coerced to a +list.} + +\item{...}{Additional arguments to be passed on to other methods.} +} +\value{ +A \code{cff} object. These objects are rarely \link[=cff_validate]{valid}, but can +be used to complement or modify complete \code{cff} objects. +} +\description{ +\code{as_cff()} turns an existing list-like \strong{R} object into a so-called +\code{\link{cff}}, a list with class \code{cff}. + +\code{as_cff} is an S3 generic, with methods for: +\itemize{ +\item \code{person} objects as produced by \code{\link[utils:person]{utils::person()}}. +\item \code{bibentry} objects as produced by \code{\link[utils:bibentry]{utils::bibentry()}}. +\item \code{Bibtex} object as produced by \code{\link[=toBibtex]{toBibtex()}}. +\item Default: Other inputs are first coerced with \code{\link[=as.list]{as.list()}}. +} +} +\details{ +For \code{as_cff.bibentry()} / \code{as_cff.Bibtex()} see +\code{vignette("bibtex_cff", "cffr")} to understand how the mapping is performed. + +\code{\link[=as_cff_person]{as_cff_person()}} is preferred over \code{as_cff.person()} since it can handle +\code{character} person such as \code{"Davis, Jr., Sammy"}. For \code{person} objects both +functions are similar. +} +\examples{ + +# Convert a list to "cff" object +cffobj <- as_cff(list( + "cff-version" = "1.2.0", + title = "Manipulating files" +)) + +class(cffobj) + +# Nice display thanks to yaml package +cffobj + +# bibentry method +a_cit <- citation("cffr")[[1]] + +a_cit + +as_cff(a_cit) + +# Bibtex method +a_bib <- toBibtex(a_cit) + +a_bib + +as_cff(a_cit) + +} +\seealso{ +\itemize{ +\item \code{\link[=cff]{cff()}}: Create a full \code{cff} object from scratch. +\item \code{\link[=cff_modify]{cff_modify()}}: Modify a \code{cff} object. +\item \code{\link[=cff_create]{cff_create()}}: Create a \code{cff} object of a \strong{R} package. +\item \code{\link[=cff_read]{cff_read()}}: Create a \code{cff} object from a external file. +\item \code{\link[=as_cff_person]{as_cff_person()}}: Recommended way for creating persons in CFF format. +} + +Other functions for converting between \strong{R} classes: +\code{\link{as_bibentry}()}, +\code{\link{as_cff_person}()} + +Other S3 Methods for \code{cff}: +\code{\link{as_bibentry}()}, +\code{\link{as_cff_person}()}, +\code{\link{cff-class}} +} +\concept{coercing} +\concept{s3method} diff --git a/man/as_cff_person.Rd b/man/as_cff_person.Rd new file mode 100644 index 00000000..6b11aa1f --- /dev/null +++ b/man/as_cff_person.Rd @@ -0,0 +1,151 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/as_cff_person.R, R/cff-methods.R +\name{as_cff_person} +\alias{as_cff_person} +\alias{as.person.cff} +\title{Create a person with the corresponding \code{\link{cff}} structure} +\usage{ +as_cff_person(person) + +\method{as.person}{cff}(x) +} +\arguments{ +\item{person}{It can be either: +\itemize{ +\item A \code{person} or list of \code{person} object created with \code{\link[utils:person]{utils::person()}}. +\item A \code{character} object or vector representing a person or persons. +See \strong{Examples}. +}} + +\item{x}{\code{cff} object representing a person or entity.} +} +\value{ +\code{as_cff_person()} returns A list of persons or entities with class +\code{cff} converted to the \href{https://github.com/citation-file-format/citation-file-format/blob/main/schema-guide.md}{Citation File Format schema}. + +\code{as.person.cff()} returns a \code{person} object. +} +\description{ +Create a \code{person} or \code{entity} as defined by the +\href{https://github.com/citation-file-format/citation-file-format/blob/main/schema-guide.md}{Citation File Format schema}. + +\code{\link[=as_cff_person]{as_cff_person()}} can convert the following objects: +\itemize{ +\item Objects with class \code{person} as provided by \code{\link[utils:person]{utils::person()}}. +\item A \code{character} string with the definition of an author or several authors, +using the standard BibTeX notation. See Markey (2007) for a full +explanation. +} + +\code{\link[=as_cff_person]{as_cff_person()}} would recognize if the input should be converted using the +CFF reference \code{person} or \code{entity}. + +The inverse transformation (\code{cff} person to \code{\link[utils:person]{person}}) +object can be done through the \code{\link[=as.person.cff]{as.person.cff()}} method. Note that this is +expected to be used with a \code{cff} person, not with a complete \code{cff} object. +} +\details{ +\code{as_cff_person()} uses a custom algorithm that tries to break a name as +explained in Section 11 of "Tame the BeaST" (Markey, 2007) (see also +Decoret, 2007): +\itemize{ +\item \verb{First von Last}. +\item \verb{von Last, First}. +\item \verb{von Last, Jr, First}. +} + +Mapping is performed as follows: +\itemize{ +\item \code{First} is mapped to the CFF field \code{given-names}. +\item \code{von} is mapped to the CFF field \code{name-particle}. +\item \code{Last} is mapped to the CFF field \code{family-names}. +\item \code{Jr} is mapped to the CFF field \code{name-suffix}. +} + +In the case of entities, the whole \code{character} would be mapped to \code{name}. +It is a good practice to "protect" entity's names with \code{{}}: + +\if{html}{\out{
}}\preformatted{# Don't do +entity <- "Elephant and Castle" +as_cff_person(entity) +#> - name: Elephant +#> - name: Castle + +# Do +entity_protect <- "\{Elephant and Castle\}" +as_cff_person(entity_protect) +#> - name: Elephant and Castle +}\if{html}{\out{
}} + +\code{as_cff_person()} would try to add as many information as possible. +On \code{character} string coming from \code{\link[utils:person]{format(person())}} the +email and the ORCID would be gathered as well. +} +\examples{ +# Create a person object +a_person <- person( + given = "First", family = "Author", + role = c("aut", "cre"), + email = "first.last@example.com", comment = c( + ORCID = "0000-0001-8457-4658", + affiliation = "An affiliation" + ) +) + +a_person + +cff_person <- as_cff_person(a_person) + +cff_person + +# Back to person object with S3 Method +as.person(cff_person) + +# Parse a string +a_str <- paste0( + "Julio Iglesias ", + "()" +) +as_cff_person(a_str) + +# Several persons +persons <- c(person("Clark", "Kent"), person("Lois", "Lane")) + +as_cff_person(persons) + +# Or you can use BibTeX style if you prefer + +x <- "Frank Sinatra and Dean Martin and Davis, Jr., Sammy and Joey Bishop" + +as_cff_person(x) + +as_cff_person("Herbert von Karajan") +} +\references{ +\itemize{ +\item Patashnik, Oren. "BIBTEXTING" February 1988. +\url{https://osl.ugr.es/CTAN/biblio/bibtex/base/btxdoc.pdf}. +\item Markey, Nicolas. "Tame the BeaST" +\emph{The B to X of BibTeX, Version 1.4} (October 2007). +\url{https://osl.ugr.es/CTAN/info/bibtex/tamethebeast/ttb_en.pdf}. +\item Decoret X (2007). "A summary of BibTex."\url{https://maverick.inria.fr/~Xavier.Decoret/resources/xdkbibtex/bibtex_summary.html#names} +} + +See \strong{Examples} for more information. +} +\seealso{ +Examples in \code{vignette("cffr", "cffr")} and \code{\link[utils:person]{utils::person()}}. + +\code{\link[utils:person]{utils::person()}} + +Other functions for converting between \strong{R} classes: +\code{\link{as_bibentry}()}, +\code{\link{as_cff}()} + +Other S3 Methods for \code{cff}: +\code{\link{as_bibentry}()}, +\code{\link{as_cff}()}, +\code{\link{cff-class}} +} +\concept{coercing} +\concept{s3method} diff --git a/man/cff-class.Rd b/man/cff-class.Rd index 79127b37..602b2020 100644 --- a/man/cff-class.Rd +++ b/man/cff-class.Rd @@ -1,9 +1,190 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/cff-class.R +% Please edit documentation in R/docs.R \name{cff-class} \alias{cff-class} \title{The \code{cff} class} \description{ -TODO +\subsection{The \code{cff} class}{ + +\strong{cffr} implements a S3 object with \code{\link[=class]{class()}} \code{cff}, that it is used to +represent the information of a \verb{*.cff} file in \strong{R}. + +Under the hood, a \code{cff} object is simply a named \code{\link{list}} to which we added +additional methods, most notably \code{\link[=print]{print()}} and \code{\link[=as_cff]{as_cff()}}. + +\if{html}{\out{
}}\preformatted{a_named_list <- list( + first = "I", second = "am", third = "a", fourth = "list", + fifth = "with", sixth = "names", "none" = NULL +) + + +dput(a_named_list) +#> list(first = "I", second = "am", third = "a", fourth = "list", +#> fifth = "with", sixth = "names", none = NULL) + +# Default print +a_named_list +#> $first +#> [1] "I" +#> +#> $second +#> [1] "am" +#> +#> $third +#> [1] "a" +#> +#> $fourth +#> [1] "list" +#> +#> $fifth +#> [1] "with" +#> +#> $sixth +#> [1] "names" +#> +#> $none +#> NULL + +# But +a_cff_object <- as_cff(a_named_list) + +class(a_cff_object) +#> [1] "cff" "list" + +a_cff_object +#> first: I +#> second: am +#> third: a +#> fourth: list +#> fifth: with +#> sixth: names + +dput(a_cff_object) +#> structure(list(first = "I", second = "am", third = "a", fourth = "list", +#> fifth = "with", sixth = "names"), class = c("cff", "list" +#> )) +}\if{html}{\out{
}} + +\code{\link[=as_cff]{as_cff()}} not only converts a \code{list} to \code{cff} but also removes items (known +as \code{keys} in CFF terminology) that are \code{NULL} or \code{NA}. } + +\subsection{Valid \code{cff} objects}{ + +Although \code{a_cff_object} is a \code{cff} object, it is not valid, since it does not +comply with the validation rules of the CFF specification. + +\if{html}{\out{
}}\preformatted{cff_validate(a_cff_object) +#> == Validating cff ============================================================== +#> x Oops! This has the following errors: +#> * cff.authors: is required +#> * cff["cff-version"]: is required +#> * cff.message: is required +#> * cff.title: is required +}\if{html}{\out{
}} + +\code{\link[=cff_validate]{cff_validate()}} gives minimal messages of what's wrong with our \code{cff} and +(invisibly) returns the result of the validation (\code{TRUE/FALSE}). +} + +\subsection{Other methods}{ +\subsection{\code{\link[=as.data.frame]{as.data.frame()}}}{ + +\if{html}{\out{
}}\preformatted{minimal_cff <- cff() + +minimal_cff +#> authors: +#> - family-names: Doe +#> given-names: John +#> cff-version: 1.2.0 +#> message: If you use this software, please cite it using these metadata. +#> title: My Research Software + +as_df <- as.data.frame(minimal_cff) + +class(as_df) +#> [1] "data.frame" + +t(as_df) +#> [,1] +#> authors.00.family_names "Doe" +#> authors.00.given_names "John" +#> cff_version "1.2.0" +#> message "If you use this software, please cite it using these metadata." +#> title "My Research Software" +}\if{html}{\out{
}} +} + +} + +\subsection{\code{\link[=c]{c()}}}{ + +\if{html}{\out{
}}\preformatted{new_keys <- c("date-released" = "2020-01-31", abstract = "Minimal example") + +c(minimal_cff, new_keys) +#> authors: +#> - family-names: Doe +#> given-names: John +#> cff-version: 1.2.0 +#> message: If you use this software, please cite it using these metadata. +#> title: My Research Software +#> date-released: '2020-01-31' +#> abstract: Minimal example +}\if{html}{\out{
}} +} + +\subsection{\code{\link[=as.person]{as.person()}}}{ + +Special case for those CFF keys that are person-like. + +\if{html}{\out{
}}\preformatted{path <- system.file("examples/CITATION_complete.cff", package = "cffr") +the_cff <- cff_read(path) + +the_cff$authors +#> - family-names: Real Person +#> given-names: One Truly +#> name-particle: van der +#> name-suffix: IV +#> alias: Citey +#> affiliation: Excellent University, Niceplace, Arcadia +#> address: 22 Acacia Avenue +#> city: Citationburgh +#> region: Renfrewshire +#> post-code: C13 7X7 +#> country: GB +#> orcid: https://orcid.org/0000-0001-2345-6789 +#> email: project@entity.com +#> tel: +44(0)141-323 4567 +#> fax: +44(0)141-323 45678 +#> website: https://www.entity-project-team.io +#> - name: Entity Project Team Conference entity +#> address: 22 Acacia Avenue +#> city: Citationburgh +#> region: Renfrewshire +#> post-code: C13 7X7 +#> country: GB +#> orcid: https://orcid.org/0000-0001-2345-6789 +#> email: project@entity.com +#> tel: +44(0)141-323 4567 +#> fax: +44(0)141-323 45678 +#> website: https://www.entity-project-team.io +#> date-start: '2017-01-01' +#> date-end: '2017-01-31' +#> location: The team garage + +as.person(the_cff$authors) +#> [1] "One Truly van der Real Person IV (Citey, Excellent University, Niceplace, Arcadia, 22 Acacia Avenue, Citationburgh, Renfrewshire, C13 7X7, GB, , +44(0)141-323 4567, +44(0)141-323 45678, https://www.entity-project-team.io)" +#> [2] "Entity Project Team Conference entity (22 Acacia Avenue, Citationburgh, Renfrewshire, C13 7X7, GB, , +44(0)141-323 4567, +44(0)141-323 45678, https://www.entity-project-team.io, 2017-01-01, 2017-01-31, The team garage)" +}\if{html}{\out{
}} +} +} +\seealso{ +\code{vignette("cffr", "cffr")} for a hands-on example. + +Other S3 Methods for \code{cff}: +\code{\link{as_bibentry}()}, +\code{\link{as_cff}()}, +\code{\link{as_cff_person}()} +} +\concept{s3method} \keyword{internal} diff --git a/man/cff.Rd b/man/cff.Rd new file mode 100644 index 00000000..46cfd6db --- /dev/null +++ b/man/cff.Rd @@ -0,0 +1,88 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/cff.R +\name{cff} +\alias{cff} +\title{Read and manipulate \code{cff} objects} +\usage{ +cff(path, ...) +} +\arguments{ +\item{path}{\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} \code{path} is no longer supported, +use \code{\link[=cff_read_cff_citation]{cff_read_cff_citation()}} instead.} + +\item{...}{Named arguments to be used for creating a \code{cff} object. See +\strong{Details}.} +} +\value{ +A \code{cff} object. Under the hood, a \code{cff} object is a regular \code{list} object +with a special \code{\link[=print]{print()}} method. +} +\description{ +A class and utility methods for reading, creating and holding CFF +information. See \code{\linkS4class{cff}} to learn more about \code{cff} objects. +} +\details{ +If no additional \code{...} parameters are supplied (the default behavior), +a minimal valid \code{cff} object is created. \code{cff} would convert \verb{_} in the name +of the argument to \code{-} (e.g, \verb{cff_version = "1.2.0'} would be converted to +\verb{cff-version = "1.2.0'}) + +Valid parameters are those specified on \code{\link[=cff_schema_keys]{cff_schema_keys()}}:\tabular{l}{ + \strong{valid cff keys} \cr + cff-version \cr + message \cr + type \cr + license \cr + title \cr + version \cr + doi \cr + abstract \cr + authors \cr + preferred-citation \cr + repository \cr + repository-artifact \cr + repository-code \cr + url \cr + date-released \cr + contact \cr + keywords \cr + references \cr + commit \cr + identifiers \cr + license-url \cr +} +} +\examples{ +# Blank cff +cff() + +# Use custom params +test <- cff( + title = "Manipulating files", + keywords = c("A", "new", "list", "of", "keywords"), + authors = as_cff_person("New author") +) +test +\donttest{ +# Would fail +cff_validate(test) +} + +# Modify with cff_create +new <- cff_create(test, keys = list( + "cff_version" = "1.2.0", + message = "A blank file" +)) +new + +# Would pass +cff_validate(new) + +} +\seealso{ +Other core functions of \CRANpkg{cffr}: +\code{\link{cff_create}()}, +\code{\link{cff_modify}()}, +\code{\link{cff_validate}()} +} +\concept{core} diff --git a/man/cff_create.Rd b/man/cff_create.Rd index 98562aef..ab413b1e 100644 --- a/man/cff_create.Rd +++ b/man/cff_create.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/cff_create.R \name{cff_create} \alias{cff_create} -\title{Create \code{cff} object} +\title{Create a \code{\link{cff}} object} \usage{ cff_create( x, @@ -17,11 +17,11 @@ cff_create( \item{x}{The source that would be used for generating the \code{\link{cff}} object. It could be: \itemize{ -\item A missing value. That would retrieve the DESCRIPTION -file on your in-development package. +\item A missing value. That would retrieve the \code{DESCRIPTION} file on your +in-development \strong{R} package. \item An existing \code{\link{cff}} object, \item The name of an installed package (\code{"jsonlite"}), or -\item Path to a DESCRIPTION file (\code{"*/DESCRIPTION*"}). +\item Path to a \code{DESCRIPTION} file (\code{"./DESCRIPTION"}). }} \item{keys}{List of additional keys to add to the \code{\link{cff}} object. See @@ -34,18 +34,20 @@ file on your in-development package. GitHub, would you like to add the repo topics as keywords?} \item{dependencies}{Logical \code{TRUE/FALSE}. Would you like to add the -of your package to the \code{reference} key?} +of your package to the \code{references} CFF key?} \item{authors_roles}{Roles to be considered as authors of the package when generating the \code{CITATION.cff} file. See \strong{Details}.} } \value{ -A \code{\link{cff}} list object. +A \code{\link{cff}} object. } \description{ -Create a \code{\link{cff}} object from a given source for further manipulation. -Similar to \code{\link[=cff_write]{cff_write()}}, but returns a object rather than writing -directly to a file. See \strong{Examples}. +Create a \code{\link{cff}} object from a given source for further +manipulation. This object can be written to a \verb{*.cff } file with +\code{\link[=cff_write]{cff_write()}}, see \strong{Examples}. + +Most of the heavy lifting of \CRANpkg{cffr} is done via this function. } \details{ It is possible to add additional keys not detected by \code{\link[=cff_create]{cff_create()}} using @@ -56,11 +58,11 @@ Please refer to \href{https://github.com/citation-file-format/citation-file-format/blob/main/schema-guide.md}{Guide to Citation File Format schema version 1.2.0}. for additional details. -If \code{x} is a path to a DESCRIPTION file or \code{inst/CITATION}, is not present on -your package, \CRANpkg{cffr} would auto-generate a \code{preferred-citation} key -using the information provided on that file. +If \code{x} is a path to a \code{DESCRIPTION} file or \code{inst/CITATION}, is not present +on your package, \CRANpkg{cffr} would auto-generate a \code{preferred-citation} +key using the information provided on that file. -By default, only persons whose role in the DESCRIPTION file of the package +By default, only persons whose role in the \code{DESCRIPTION} file of the package is author (\code{"aut"}) or maintainer (\code{"cre"}) are considered to be authors of the package. The default setting can be controlled via the \code{authors_roles} parameter. See \strong{Details} on \code{\link[utils:person]{utils::person()}} to get additional insights @@ -81,7 +83,7 @@ newkeys <- list( message = "This overwrites fields", abstract = "New abstract", keywords = c("A", "new", "list", "of", "keywords"), - authors = list(cff_parse_person("New author")) + authors = as_cff_person("New author") ) cff_create(demo_file, keys = newkeys) @@ -93,12 +95,10 @@ old <- cff_create(demo_file) new_contact <- append( old$contact, - list( - cff_parse_person(person( - given = "I am", - family = "New Contact" - )) - ) + as_cff_person(person( + given = "I am", + family = "New Contact" + )) ) @@ -107,12 +107,12 @@ cff_create(demo_file, keys = list("contact" = new_contact)) } \seealso{ \href{https://github.com/citation-file-format/citation-file-format/blob/main/schema-guide.md}{Guide to Citation File Format schema version 1.2.0}. +See also \code{\link[=cff_write]{cff_write()}} for creating a CFF file. \code{vignette("cffr", "cffr")} +shows an introduction on how manipulate \code{cff} objects. -\code{vignette("cffr", "cffr")} - -Other Core functions: -\code{\link{cff_read}()}, -\code{\link{cff_validate}()}, -\code{\link{cff_write}()} +Other core functions of \CRANpkg{cffr}: +\code{\link{cff}()}, +\code{\link{cff_modify}()}, +\code{\link{cff_validate}()} } -\concept{Core functions} +\concept{core} diff --git a/man/cff_gha_update.Rd b/man/cff_gha_update.Rd index e522d757..c45049d9 100644 --- a/man/cff_gha_update.Rd +++ b/man/cff_gha_update.Rd @@ -2,30 +2,31 @@ % Please edit documentation in R/cff_gha_update.R \name{cff_gha_update} \alias{cff_gha_update} -\title{Install a cffr GitHub Action} +\title{Install a \CRANpkg{cffr} GitHub Action} \usage{ cff_gha_update(path = ".", overwrite = FALSE) } \arguments{ -\item{path}{Project directory} +\item{path}{Project directory.} -\item{overwrite}{If already present, do you want to overwrite your action?} +\item{overwrite}{Logical. If already present, do you want to overwrite your +action?} } \value{ Invisible, this function is called by its side effects. } \description{ -This function would install a GitHub Action on your repo. The action +This function would install a +\href{https://github.com/features/actions}{GitHub Action} on your repo. The action will update your \code{CITATION.cff} when any of these events occur: \itemize{ \item You publish a new release of the package. -\item Your DESCRIPTION or inst/CITATION are modified. +\item Your \code{DESCRIPTION} or \code{inst/CITATION} are modified. \item The action can be run also manually. } } \details{ -Triggers on your action can be modified, see -\href{https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows}{Events that trigger workflows}. +Triggers on your action can be modified, see \href{https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows}{Events that trigger workflows}. } \examples{ \dontrun{ @@ -33,7 +34,7 @@ cff_gha_update() } } \seealso{ -Other Git helpers: +Other Git/GitHub helpers: \code{\link{cff_git_hook}} } -\concept{Git helpers} +\concept{git} diff --git a/man/cff_git_hook.Rd b/man/cff_git_hook.Rd index f7926930..85a7f720 100644 --- a/man/cff_git_hook.Rd +++ b/man/cff_git_hook.Rd @@ -26,9 +26,9 @@ A pre-commit hook is a script that identifies simple issues before submission to code review. This pre-commit hook would warn you if any of the following conditions are met: \itemize{ -\item You included in a commit your DESCRIPTION or inst/CITATION file, you +\item You included in a commit your \code{DESCRIPTION} or \code{inst/CITATION} file, you are not including your \code{CITATION.cff} and the \code{CITATION.cff} file is -"older" than any of your DESCRIPTION or inst/CITATION file, or +"older" than any of your \code{DESCRIPTION} or \code{inst/CITATION} file. \item You have updated your \code{CITATION.cff} but you are not including it on your commit. } @@ -38,14 +38,15 @@ The pre-commit hook may prevent you to commit if you are not updating your \code{CITATION.cff}. However, the mechanism of detection is not perfect and would be triggered also even if you have tried to update your \code{CITATION.cff} file. -This is typically the case when you have updated your DESCRIPTION or -inst/CITATION files but those changes doesn't make a change on your +This is typically the case when you have updated your \code{DESCRIPTION} or +\code{inst/CITATION} files but those changes doesn't make a change on your \code{CITATION.cff} file (i.e. you are including new dependencies). In those cases, you can override the check running \verb{git commit --no-verify} -on the Terminal tab. If you are using -RStudio you can run also this command from a R script by selecting that -line and sending it to the Terminal using: +on the terminal. + +If you are using \strong{RStudio} you can run also this command from a \strong{R} +script by selecting that line and sending it to the terminal using: \itemize{ \item \code{Ctrl+Alt+Enter} (Windows & Linux), or \item \code{Cmd+Option+Return} (Mac). @@ -65,7 +66,7 @@ cff_git_hook_install() \seealso{ \code{\link[usethis:use_git_hook]{usethis::use_git_hook()}}, \code{\link[usethis:use_git]{usethis::use_git()}} -Other Git helpers: +Other Git/GitHub helpers: \code{\link{cff_gha_update}()} } -\concept{Git helpers} +\concept{git} diff --git a/man/cff_modify.Rd b/man/cff_modify.Rd new file mode 100644 index 00000000..69173071 --- /dev/null +++ b/man/cff_modify.Rd @@ -0,0 +1,56 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/cff_modify.R +\name{cff_modify} +\alias{cff_modify} +\title{Modify a \code{\link{cff}} object} +\usage{ +cff_modify(x, ...) +} +\arguments{ +\item{x}{A \code{\link{cff}} object.} + +\item{...}{Named arguments to be used for modifying \code{x}. See also \code{\link[=cff]{cff()}}.} +} +\value{ +A \code{\link{cff}} object. +} +\description{ +Add new keys or modify existing ones on a \code{\link{cff}} object. +} +\details{ +If any key provided in \code{...} is present in \code{x}, the result would have the +key provided in \code{...}. +} +\examples{ +x <- cff() +x + +cff_validate(x) + + +x_mod <- cff_modify(x, + contact = as_cff_person("A contact"), + message = "This overwrites fields", + title = "New Title", + abstract = "New abstract", + doi = "10.21105/joss.03900" +) +cff_validate(x_mod) + +} +\seealso{ +This function is wrapper of \code{\link[utils:modifyList]{utils::modifyList()}}. + +See \code{\link[=cff]{cff()}} for creating \code{\link{cff}} objects from scratch. + +Other core functions of \CRANpkg{cffr}: +\code{\link{cff}()}, +\code{\link{cff_create}()}, +\code{\link{cff_validate}()} + +Other core functions of \CRANpkg{cffr}: +\code{\link{cff}()}, +\code{\link{cff_create}()}, +\code{\link{cff_validate}()} +} +\concept{core} diff --git a/man/cff_parse_citation.Rd b/man/cff_parse_citation.Rd deleted file mode 100644 index 02c768c7..00000000 --- a/man/cff_parse_citation.Rd +++ /dev/null @@ -1,87 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/cff_parse_citation.R -\name{cff_parse_citation} -\alias{cff_parse_citation} -\title{Parse a \code{bibentry} to \code{cff}} -\usage{ -cff_parse_citation(bib) -} -\arguments{ -\item{bib}{A \code{bibentry} object, either created with \code{\link[=bibentry]{bibentry()}} -(preferred) or \code{\link[=citEntry]{citEntry()}}.} -} -\value{ -A \code{\link{cff}} object ready to be used on \code{\link[=cff_create]{cff_create()}}. -} -\description{ -Parse a \code{bibentry} object to a valid format for a \code{CITATION.cff} file. -} -\details{ -This is a helper function designed to help on adding or -replacing the auto-generated authors of the package. See \strong{Examples}. - -This function tries to adapt a \code{bibentry} object (generated with \code{\link[=bibentry]{bibentry()}} -or \code{\link[=citEntry]{citEntry()}}) to the CFF standard. -\subsection{Entry types considered}{ -\itemize{ -\item \strong{Article}, \strong{Book}, \strong{Booklet}, \strong{InBook}, \strong{InCollection}, -\strong{InProceedings}, \strong{Manual}, \strong{MastersThesis}, \strong{Misc}, \strong{PhDThesis}, -\strong{Proceedings}, \strong{TechReport}, \strong{Unpublished}. See \code{\link[=bibentry]{bibentry()}} -for more information. -} - -Note that \strong{Conference} is not implemented in -\code{\link[=bibentry]{bibentry()}}, however is equivalent to \strong{InProceedings} (Patashnik (1988)). -} - -\subsection{Fields considered}{ -\itemize{ -\item \strong{address}, \strong{author}, \strong{booktitle}, \strong{chapter}, \strong{edition}, -\strong{editor}, \strong{howpublished}, \strong{institution}, \strong{journal}, \strong{key}, -\strong{month}, \strong{note}, \strong{number}, \strong{organization}, \strong{pages}, -\strong{publisher}, \strong{school}, \strong{series}, \strong{title}, \strong{type}, \strong{year}. -} - -\strong{annote} and \strong{crossref} fields are ignored. -} -} -\examples{ -\donttest{ -bib <- citation("base") -bib - - -# To cff -bib_to_cff <- cff_parse_citation(bib) -bib_to_cff - -# Create the object -new_cff <- cff() - -full <- cff_create(new_cff, keys = list("preferred-citation" = bib_to_cff)) - -full -# Validate -cff_validate(full) - -# Several citations - -cff_parse_citation(citation("rmarkdown")) -} -} -\references{ -\itemize{ -\item Patashnik, Oren. "BIBTEXTING" February 1988. -\url{https://osl.ugr.es/CTAN/biblio/bibtex/base/btxdoc.pdf}. -\item Haines, R., & The Ruby Citation File Format Developers. (2021). -\emph{Ruby CFF Library (Version 0.9.0)} (Computer software). -\doi{10.5281/zenodo.1184077}. -} -} -\seealso{ -\code{\link[=cff_create]{cff_create()}}, \code{vignette("bibtex_cff", "cffr")}, \code{\link[=bibentry]{bibentry()}} - -Other Parsers: -\code{\link{cff_parse_person}()} -} -\concept{Parsers} diff --git a/man/cff_parse_person.Rd b/man/cff_parse_person.Rd deleted file mode 100644 index 3246797c..00000000 --- a/man/cff_parse_person.Rd +++ /dev/null @@ -1,82 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/cff_parse_person.R -\name{cff_parse_person} -\alias{cff_parse_person} -\alias{cff_parse_person_bibtex} -\title{Parse a person to \code{cff}} -\usage{ -cff_parse_person(person) - -cff_parse_person_bibtex(person) -} -\arguments{ -\item{person}{A \code{person} object created with \code{\link[=person]{person()}} or a -character string. See \strong{Details}.} -} -\value{ -A \code{\link{cff}} object ready to be used on \code{\link[=cff_create]{cff_create()}}. -} -\description{ -Parse a person or string to a valid format for a \code{CITATION.cff} file. This -is a helper function designed to help on adding or replacing the -auto-generated authors of the package. -} -\details{ -The \code{person} parameter of the function could be: -\itemize{ -\item For \code{cff_parse_person()}: A \code{person} object or a character coercible to -\code{person}. See \code{\link[=person]{person()}} for details. -\item For \code{cff_parse_person_bibtex()}: A string with the definition of an author -or several authors, using the standard BibTeX notation. See Markey (2007) -for a full explanation. -} - -See \strong{Examples} for more information. -} -\examples{ -# Parse a person object - -cff_parse_person(person( - given = "First", - family = "Author", - role = c("aut", "cre"), - email = "first.last@example.com", - comment = c( - ORCID = "0000-0001-8457-4658", - affiliation = "An affiliation" - ) -)) - -# Parse a string - -cff_parse_person("Julio Iglesias ") - -# Several persons -persons <- c(person("Clark", "Kent"), person("Lois", "Lane")) - -cff_parse_person(persons) - -# Or you can use BibTeX style if you prefer - -x <- "Frank Sinatra and Dean Martin and Davis, Jr., Sammy and Joey Bishop" - -cff_parse_person_bibtex(x) - -cff_parse_person_bibtex("Herbert von Karajan") -} -\references{ -\itemize{ -\item Patashnik, Oren. "BIBTEXTING" February 1988. -\url{https://osl.ugr.es/CTAN/biblio/bibtex/base/btxdoc.pdf}. -\item Markey, Nicolas. "Tame the BeaST." -\emph{The B to X of BibTeX, Version 1.4} (October 2007). -\url{https://osl.ugr.es/CTAN/info/bibtex/tamethebeast/ttb_en.pdf}. -} -} -\seealso{ -\code{\link[=cff_create]{cff_create()}}, \code{vignette("cffr", "cffr")}, \code{\link[utils:person]{utils::person()}} - -Other Parsers: -\code{\link{cff_parse_citation}()} -} -\concept{Parsers} diff --git a/man/cff_read.Rd b/man/cff_read.Rd index 3dfdb77b..5a7fef5e 100644 --- a/man/cff_read.Rd +++ b/man/cff_read.Rd @@ -2,114 +2,145 @@ % Please edit documentation in R/cff_read.R \name{cff_read} \alias{cff_read} -\alias{cff} -\alias{as.cff} -\title{Read and manipulate \code{cff} objects} +\alias{cff_read_cff_citation} +\alias{cff_read_description} +\alias{cff_read_citation} +\alias{cff_read_bib} +\title{Read an external file as a \code{\link{cff}} object} \usage{ -cff_read(path) +cff_read(path, ...) -cff(path, ...) +cff_read_cff_citation(path, ...) -as.cff(x) +cff_read_description( + path, + cff_version = "1.2.0", + gh_keywords = TRUE, + authors_roles = c("aut", "cre"), + ... +) + +cff_read_citation(path, meta = NULL, ...) + +cff_read_bib(path, encoding = "UTF-8", ...) } \arguments{ -\item{path}{The path to a \code{CITATION.cff} file.} +\item{path}{Path to a file.} + +\item{...}{Arguments to be passed to other functions (i.e. to +\code{\link[yaml:read_yaml]{yaml::read_yaml()}}, \code{\link[bibtex:read.bib]{bibtex::read.bib()}}, etc.).} + +\item{cff_version}{The Citation File Format schema version that the +\code{CITATION.cff} file adheres to for providing the citation metadata.} + +\item{gh_keywords}{Logical \code{TRUE/FALSE}. If the package is hosted on +GitHub, would you like to add the repo topics as keywords?} -\item{...}{Named arguments to be used for creating a \code{\link{cff}} object. See -\strong{Details}.} +\item{authors_roles}{Roles to be considered as authors of the package when +generating the \code{\link{cff}} object.} -\item{x}{a character string for the \code{\link{as.cff}} default method} +\item{meta}{A list of package metadata as obtained by +\code{\link[utils:packageDescription]{utils::packageDescription()}} or \code{NULL} (the default). See \strong{Details}.} + +\item{encoding}{Encoding to be assumed for \code{path}. See \code{\link[=readLines]{readLines()}}.} } \value{ -A \code{cff} object. Under the hood, a \code{cff} object is a regular \code{\link{list}} object -with a special \code{\link[=print]{print()}} method. +A \code{\link{cff}} object. In the case of \code{\link[=cff_read_cff_citation]{cff_read_cff_citation()}} and +\code{\link[=cff_read_description]{cff_read_description()}} a full and (potentially) valid \code{cff} object. + +In the case of \code{\link[=cff_read_bib]{cff_read_bib()}} and \code{\link[=cff_read_citation]{cff_read_citation()}}, the result is +the \code{cff} version of a \code{\link[=bibentry]{bibentry()}} object (i.e. a bibliographic reference), +that can be used to complement another \code{cff} object. See +\code{vignette("bibtex_cff", "cffr")} to get further insights on how this +conversion is performed. } \description{ -A class and utility methods for reading, creating and holding CFF -information. +Read files and convert them to \code{\link{cff}} objects. Files supported +are: +\itemize{ +\item \code{CITATION.cff} files. +\item \code{DESCRIPTION} files. +\item \strong{R} citation files (usually located in \code{inst/CITATION}). +\item BibTeX files (with extension \verb{*.bib}). +} + +\code{\link[=cff_read]{cff_read()}} would try to guess the type of file provided in \code{path}. However +we provide a series of alias for each specific type of file: +\itemize{ +\item \code{\link[=cff_read_cff_citation]{cff_read_cff_citation()}}, that uses \code{\link[yaml:read_yaml]{yaml::read_yaml()}}. +\item \code{\link[=cff_read_description]{cff_read_description()}}, using \code{\link[desc:desc]{desc::desc()}}. +\item \code{\link[=cff_read_citation]{cff_read_citation()}} uses \code{\link[utils:citation]{utils::readCitationFile()}}. +\item \code{\link[=cff_read_bib]{cff_read_bib()}} requires \CRANpkg{bibtex} (>= 0.5.0) and uses +\code{\link[bibtex:read.bib]{bibtex::read.bib()}}. } -\details{ -This object can be manipulated using \code{\link[=cff_create]{cff_create()}}. - -\strong{Note that} this function reads \code{CITATION.cff} files. If you want to -create \code{cff} objects from DESCRIPTION files use \code{\link[=cff_create]{cff_create()}}. - -If no additional \code{...} parameters are supplied (the default behavior), -a minimal valid \code{cff} object is created. Valid parameters are those -specified on \code{\link[=cff_schema_keys]{cff_schema_keys()}}:\tabular{l}{ - \strong{valid cff keys} \cr - cff-version \cr - message \cr - type \cr - license \cr - title \cr - version \cr - doi \cr - abstract \cr - authors \cr - preferred-citation \cr - repository \cr - repository-artifact \cr - repository-code \cr - url \cr - date-released \cr - contact \cr - keywords \cr - references \cr - commit \cr - identifiers \cr - license-url \cr } +\section{The \code{meta} object}{ +Section 1.9 CITATION files of \emph{Writing R Extensions} (R Core Team 2023) +specifies how to create dynamic \code{CITATION} files using \code{meta} object, hence +the \code{meta} argument in \code{\link[=cff_read_citation]{cff_read_citation()}} may be needed for reading +some files correctly. } + \examples{ -# Blank cff -cff() +# Create cff object from cff file -# From file -cff_read(system.file("examples/CITATION_basic.cff", +from_cff_file <- cff_read(system.file("examples/CITATION_basic.cff", package = "cffr" )) -# Use custom params -test <- cff( - title = "Manipulating files", - keywords = c("A", "new", "list", "of", "keywords"), - authors = list(cff_parse_person("New author")) -) -test -\donttest{ -# Would fail -cff_validate(test) - +head(from_cff_file, 7) -# Modify with cff_create -new <- cff_create(test, keys = list( - "cff-version" = "1.2.0", - message = "A blank file" +# Create cff object from DESCRIPTION +from_desc <- cff_read(system.file("examples/DESCRIPTION_basic", + package = "cffr" )) -new -# Would pass -cff_validate(new) -} +from_desc +# Create cff object from BibTex -# Convert a list to "cff" object -cffobj <- as.cff(list( - "cff-version" = "1.2.0", - title = "Manipulating files" -)) +if (requireNamespace("bibtex", quietly = TRUE)) { + from_bib <- cff_read(system.file("examples/example.bib", + package = "cffr" + )) + + # First item only + from_bib[[1]] +} +# Create cff object from CITATION +from_citation <- cff_read(system.file("CITATION", package = "cffr")) -class(cffobj) +# First item only +from_citation[[1]] -# Nice display thanks to yaml package -cffobj +} +\references{ +\itemize{ +\item R Core Team (2023). \emph{Writing R Extensions}. +\url{https://cran.r-project.org/doc/manuals/r-release/R-exts.html} +\item Hernangomez D (2022). "BibTeX and CFF, a potential crosswalk." +\emph{The cffr package, Vignettes}. \doi{10.21105/joss.03900}, +\url{https://docs.ropensci.org/cffr/articles/bibtex_cff.html}. +} } \seealso{ -Other Core functions: -\code{\link{cff_create}()}, -\code{\link{cff_validate}()}, -\code{\link{cff_write}()} +The underlying functions used for reading external files: +\itemize{ +\item \code{\link[yaml:read_yaml]{yaml::read_yaml()}} for \code{CITATION.cff} files. +\item \code{\link[desc:desc]{desc::desc()}} for \code{DESCRIPTION} files. +\item \code{\link[utils:citation]{utils::readCitationFile()}} for \strong{R} citation files. +\item \code{\link[bibtex:read.bib]{bibtex::read.bib()}} for BibTeX files (extension \verb{*.bib}). +} + +Other functions for reading external files: +\code{\link{cff_read_bib_text}()} + +Other functions for working with BibTeX format: +\code{\link{as_bibentry}()}, +\code{\link{cff_read_bib_text}()}, +\code{\link{cff_write_bib}()}, +\code{\link{encoded_utf_to_latex}()} } -\concept{Core functions} +\concept{bibtex} +\concept{reading} diff --git a/man/cff_read_bib_text.Rd b/man/cff_read_bib_text.Rd new file mode 100644 index 00000000..f101d62c --- /dev/null +++ b/man/cff_read_bib_text.Rd @@ -0,0 +1,73 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/cff_read_bib_text.R +\name{cff_read_bib_text} +\alias{cff_read_bib_text} +\title{Read BibTeX markup as a \code{\link{cff}} object} +\usage{ +cff_read_bib_text(x, encoding = "UTF-8", ...) +} +\arguments{ +\item{x}{A vector of \code{character} objects with the full BibTeX string.} + +\item{encoding}{Encoding to be assumed for \code{x}, see \code{\link[=readLines]{readLines()}}.} + +\item{...}{ + Arguments passed on to \code{\link[=cff_read_bib]{cff_read_bib}} + \describe{ + \item{\code{}}{} + }} +} +\value{ +A \code{\link[=cff-class]{cff}} object ready to be used with other functions (i.e. +\code{\link[=cff_create]{cff_create()}}. +} +\description{ +Convert a \code{\link[=character]{character}} representing a BibTeX entry to a +\code{\link{cff}} object. +} +\details{ +This is a helper function that writes \code{x} to a \verb{*.bib} file and reads it with +\code{\link[=cff_read_bib]{cff_read_bib()}}. + +This function requires \CRANpkg{bibtex} (>= 0.5.0) and uses +\code{\link[bibtex:read.bib]{bibtex::read.bib()}}. +} +\examples{ +if (requireNamespace("bibtex", quietly = TRUE)) { + x <- c( + "@book{einstein1921, + title = {Relativity: The Special and the General Theory}, + author = {Einstein, Albert}, + year = 1920, + publisher = {Henry Holt and Company}, + address = {London, United Kingdom}, + isbn = 9781587340925 + }", + "@misc{misc-full, + title = {Handing out random pamphlets in airports}, + author = {Joe-Bob Missilany}, + year = 1984, + month = oct, + note = {This is a full MISC entry}, + howpublished = {Handed out at O'Hare} + }" + ) + + + cff_read_bib_text(x) +} +} +\seealso{ +\code{\link[=cff_read_bib]{cff_read_bib()}} for reading \verb{*.bib} files. + +Other functions for working with BibTeX format: +\code{\link{as_bibentry}()}, +\code{\link{cff_read}()}, +\code{\link{cff_write_bib}()}, +\code{\link{encoded_utf_to_latex}()} + +Other functions for reading external files: +\code{\link{cff_read}()} +} +\concept{bibtex} +\concept{reading} diff --git a/man/cff_schema.Rd b/man/cff_schema.Rd index d55efe2a..359023a3 100644 --- a/man/cff_schema.Rd +++ b/man/cff_schema.Rd @@ -59,4 +59,4 @@ cff_schema_definitions_entity() cff_schema_definitions_refs() } -\concept{Schemas} +\concept{schemas} diff --git a/man/cff_to_bibentry.Rd b/man/cff_to_bibentry.Rd deleted file mode 100644 index 338a14e4..00000000 --- a/man/cff_to_bibentry.Rd +++ /dev/null @@ -1,104 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/cff_to_bibentry.R -\name{cff_to_bibentry} -\alias{cff_to_bibentry} -\alias{cff_to_bibtex} -\title{Create BibTeX entries from several sources} -\usage{ -cff_to_bibentry(x, what = c("preferred", "references", "all")) -} -\arguments{ -\item{x}{The source that would be used for generating -the \code{\link[=bibentry]{bibentry()}} object via \code{cff}. It could be: -\itemize{ -\item A missing value. That would retrieve the DESCRIPTION -file on your in-development package. -\item An existing \code{\link{cff}} object, -\item Path to a CITATION.cff file (\code{"*/CITATION.cff*"}), -\item The name of an installed package (\code{"jsonlite"}), or -\item Path to a DESCRIPTION file (\code{"*/DESCRIPTION*"}). -}} - -\item{what}{Fields to extract. The value could be: -\itemize{ -\item \code{preferred}: This would create a single entry with the main citation -info of the package. -\item \code{references}: Extract all the entries on \code{references}. -\item \code{all}: A combination of the previous two options. This would extract -both the preferred citation info and the references. -}} -} -\value{ -A \code{bibentry} object or a list of \code{bibentry} objects. This could -be parsed to BibTeX using \code{\link[=toBibtex]{toBibtex()}} -} -\description{ -This function creates \code{\link[=bibentry]{bibentry()}} objects -from different metadata sources (\code{cff} objects, \code{DESCRIPTION} files, etc.). -The function tries to map the information of the source \code{x} into a \code{cff} -object and performs a mapping of the metadata to BibTeX, according to -\code{vignette("bibtex_cff", "cffr")}. - -Note that a \strong{R} \code{\link[=bibentry]{bibentry()}} object is the representation of a BibTeX -entry, see \strong{Examples}. -} -\examples{ -\donttest{ -# From a cff object -cff_object <- cff() - -cff_object - -# bibentry object -bib <- cff_to_bibentry(cff_object) - -class(bib) - -bib - -# Print as bibtex - -toBibtex(bib) - -# From a CITATION.cff file with options - -path <- system.file("examples/CITATION_complete.cff", package = "cffr") -cff_file <- cff_to_bibentry(path, what = "all") - -toBibtex(cff_file) - -# For an installed package - -installed_package <- cff_to_bibentry("jsonvalidate") - -toBibtex(installed_package) - - -# Use a DESCRIPTION file - -path2 <- system.file("examples/DESCRIPTION_gitlab", package = "cffr") -desc_file <- cff_to_bibentry(path2) - -toBibtex(desc_file) -} -} -\references{ -\itemize{ -\item Patashnik, Oren. "BIBTEXTING" February 1988. -\url{https://osl.ugr.es/CTAN/biblio/bibtex/base/btxdoc.pdf}. -\item Haines, R., & The Ruby Citation File Format Developers. (2021). -\emph{Ruby CFF Library (Version 0.9.0)} (Computer software). -\doi{10.5281/zenodo.1184077}. -\item Hernangómez D (2022). "BibTeX and CFF, a potential crosswalk." -\emph{The cffr package, Vignettes}. \doi{10.21105/joss.03900}, -\url{https://docs.ropensci.org/cffr/articles/bibtex_cff.html}. -} -} -\seealso{ -Other BibTeX helpers: -\code{\link{cff_from_bibtex}()}, -\code{\link{encoded_utf_to_latex}()}, -\code{\link{write_bib}()}, -\code{\link{write_citation}()} -} -\concept{BibTeX helpers} diff --git a/man/cff_validate.Rd b/man/cff_validate.Rd index 4478e99b..6b6079ff 100644 --- a/man/cff_validate.Rd +++ b/man/cff_validate.Rd @@ -7,7 +7,7 @@ cff_validate(x = "CITATION.cff", verbose = TRUE) } \arguments{ -\item{x}{This is expected to be either a \code{\link{cff}} object created +\item{x}{This is expected to be either a \code{cff} object created with \code{\link[=cff_create]{cff_create()}} or the path to a \code{CITATION.cff} file to be validated.} \item{verbose}{Logical \code{TRUE/FALSE}. On \code{TRUE} the function would display @@ -15,8 +15,8 @@ informative messages.} } \value{ A message indicating the result of the validation and an invisible -value \code{TRUE/FALSE}. On error, the results would have an attribute \verb{"errors} -containing the error summary (see \strong{Examples} and \code{\link[=attr]{attr()}}). +value \code{TRUE/FALSE}. On error, the results would have an attribute +\code{"errors"} containing the error summary (see \strong{Examples} and \code{\link[=attr]{attr()}}). } \description{ Validate a \code{CITATION.cff} file or a \code{\link{cff}} object created with @@ -50,9 +50,9 @@ try(cff_validate(system.file("CITATION", package = "cffr"))) \seealso{ \href{https://github.com/citation-file-format/citation-file-format/blob/main/schema-guide.md}{Guide to Citation File Format schema version 1.2.0}. -Other Core functions: +Other core functions of \CRANpkg{cffr}: +\code{\link{cff}()}, \code{\link{cff_create}()}, -\code{\link{cff_read}()}, -\code{\link{cff_write}()} +\code{\link{cff_modify}()} } -\concept{Core functions} +\concept{core} diff --git a/man/cff_write.Rd b/man/cff_write.Rd index cc4e592e..2dd826b1 100644 --- a/man/cff_write.Rd +++ b/man/cff_write.Rd @@ -20,16 +20,16 @@ cff_write( \item{x}{The source that would be used for generating the \code{CITATION.cff} file. It could be: \itemize{ -\item A missing value. That would retrieve the DESCRIPTION -file on your in-development package. -\item A \code{\link{cff}} object, +\item A missing value. That would retrieve the \code{DESCRIPTION} file on your +in-development package. +\item A \code{cff} object, \item The name of an installed package (\code{"jsonlite"}), or -\item Path to a DESCRIPTION file (\code{"*/DESCRIPTION*"}). +\item Path to a DESCRIPTION file (\code{"./DESCRIPTION"}). }} \item{outfile}{The name and path of the \code{CITATION.cff} to be created.} -\item{keys}{List of additional keys to add to the \code{\link{cff}} object. See +\item{keys}{List of additional keys to add to the \code{cff} object. See \code{\link[=cff_create]{cff_create()}} for details and examples.} \item{cff_version}{The Citation File Format schema version that the @@ -39,7 +39,7 @@ file on your in-development package. GitHub, would you like to add the repo topics as keywords?} \item{dependencies}{Logical \code{TRUE/FALSE}. Would you like to add the -of your package to the \code{reference} key?} +of your package to the \code{references} CFF key?} \item{validate}{Logical \code{TRUE/FALSE}. Should the new file be validated using \code{\link[=cff_validate]{cff_validate()}}?} @@ -51,7 +51,7 @@ informative messages.} generating the \code{CITATION.cff} file. See \strong{Details} on \code{\link[=cff_create]{cff_create()}}.} } \value{ -A \code{CITATION.cff} file and an (invisible) \code{\link{cff}} object. +A \code{CITATION.cff} file and an (invisible) \code{cff} object. } \description{ \strong{This is the core function of the package and likely to be the only one @@ -59,7 +59,8 @@ you would need when developing a package}. This function writes out a \code{CITATION.cff} file for a given package. This function is basically a wrapper around \code{\link[=cff_create]{cff_create()}} to both create the -\code{\link{cff}} object and writes it out to a YAML-formatted file in one command. +\code{\link{cff}} object and writes it out to a YAML-formatted file in +one command. } \details{ When creating and writing a \code{CITATION.cff} for the first time, the function @@ -78,10 +79,10 @@ file.remove(tmpfile) } \seealso{ \href{https://github.com/citation-file-format/citation-file-format/blob/main/schema-guide.md}{Guide to Citation File Format schema version 1.2.0}. +This function unifies the workflow \code{\link[=cff_create]{cff_create()}} + \code{\link[=cff_write]{cff_write()}} + +\code{\link[=cff_validate]{cff_validate()}}. -Other Core functions: -\code{\link{cff_create}()}, -\code{\link{cff_read}()}, -\code{\link{cff_validate}()} +Other functions for creating external files: +\code{\link{cff_write_bib}()} } -\concept{Core functions} +\concept{writing} diff --git a/man/cff_write_misc.Rd b/man/cff_write_misc.Rd new file mode 100644 index 00000000..68eccee6 --- /dev/null +++ b/man/cff_write_misc.Rd @@ -0,0 +1,125 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/cff_write_misc.R +\name{cff_write_bib} +\alias{cff_write_bib} +\alias{cff_write_citation} +\title{Export \strong{R} objects to different file types} +\usage{ +cff_write_bib( + x, + file = tempfile(fileext = ".bib"), + append = FALSE, + verbose = TRUE, + ascii = FALSE, + ... +) + +cff_write_citation( + x, + file = tempfile("CITATION_"), + append = FALSE, + verbose = TRUE, + ... +) +} +\arguments{ +\item{x}{A \code{\link[=bibentry]{bibentry}} or a \code{\link{cff}} object.} + +\item{file}{Name of the file to be created. If \code{NULL} it would display the +lines to be written.} + +\item{append}{Whether to append the entries to an existing file or not.} + +\item{verbose}{Display informative messages} + +\item{ascii}{Whether to write the entries using ASCII characters only or not.} + +\item{...}{ + Arguments passed on to \code{\link[=as_bibentry]{as_bibentry}} + \describe{ + \item{\code{what}}{Fields to extract. The value could be: +\itemize{ +\item \code{preferred}: This would create a single entry with the main citation +info of the package. +\item \code{references}: Extract all the entries on \code{references}. +\item \code{all}: A combination of the previous two options. This would extract +both the preferred citation info and the references. +}} + }} +} +\value{ +Writes the corresponding file specified on the \code{file} parameter. +} +\description{ +Export \strong{R} objects representing citations to specific file types: +\itemize{ +\item \code{\link[=cff_write_bib]{cff_write_bib()}} creates a \code{.bib} file. +\item \code{\link[=cff_write_citation]{cff_write_citation()}} creates a \strong{R} citation file as explained in +Section 1.9 CITATION files of \emph{Writing R Extensions} (R Core Team 2023). +} +} +\details{ +When \code{x} is a \code{cff} object it would be converted to \code{bibentry} using +\code{\link[=as_bibentry]{as_bibentry()}}. + +For security reasons, if the file already exists the function would create +a backup copy on the same directory. +} +\examples{ + +bib <- bibentry("Misc", + title = "My title", + author = "Fran Pérez" +) + +my_temp_bib <- tempfile(fileext = ".bib") + +cff_write_bib(bib, file = my_temp_bib) + +cat(readLines(my_temp_bib), sep = "\n") + +cff_write_bib(bib, file = my_temp_bib, ascii = TRUE, append = TRUE) + +cat(readLines(my_temp_bib), sep = "\n") + +# Create a CITATION file + +# Use a system file +f <- system.file("examples/preferred-citation-book.cff", package = "cffr") +a_cff <- cff_read(f) + +out <- file.path(tempdir(), "CITATION") +cff_write_citation(a_cff, file = out) + +# Check by reading, use meta object +meta <- packageDescription("cffr") +meta$Encoding <- "UTF-8" + +utils::readCitationFile(out, meta) +} +\references{ +\itemize{ +\item R Core Team (2023). \emph{Writing R Extensions}. +\url{https://cran.r-project.org/doc/manuals/r-release/R-exts.html} +} +} +\seealso{ +\code{vignette("bibtex_cff", "cffr")}, \code{\link[knitr:write_bib]{knitr::write_bib()}} and the +following packages: +\itemize{ +\item \CRANpkg{bibtex}. +\item \CRANpkg{RefManageR} +\item \CRANpkg{rbibutils} +} + +Other functions for working with BibTeX format: +\code{\link{as_bibentry}()}, +\code{\link{cff_read}()}, +\code{\link{cff_read_bib_text}()}, +\code{\link{encoded_utf_to_latex}()} + +Other functions for creating external files: +\code{\link{cff_write}()} +} +\concept{bibtex} +\concept{writing} diff --git a/man/chunks/cffclass.Rmd b/man/chunks/cffclass.Rmd new file mode 100644 index 00000000..0c549fc6 --- /dev/null +++ b/man/chunks/cffclass.Rmd @@ -0,0 +1,85 @@ +## The `cff` class + +**cffr** implements a S3 object with [class()] `cff`, that it is used to +represent the information of a `*.cff` file in **R**. + +Under the hood, a `cff` object is simply a named [`list`] to which we added +additional methods, most notably [print()] and [as_cff()]. + +```{r include=FALSE} +library(cffr) +``` + +```{r} +a_named_list <- list( + first = "I", second = "am", third = "a", fourth = "list", + fifth = "with", sixth = "names", "none" = NULL +) + + +dput(a_named_list) + +# Default print +a_named_list + +# But +a_cff_object <- as_cff(a_named_list) + +class(a_cff_object) + +a_cff_object + +dput(a_cff_object) +``` + +[as_cff()] not only converts a `list` to `cff` but also removes items (known +as `keys` in CFF terminology) that are `NULL` or `NA`. + +## Valid `cff` objects + +Although `a_cff_object` is a `cff` object, it is not valid, since it does not +comply with the validation rules of the CFF specification. + +```{r} +cff_validate(a_cff_object) +``` + +[cff_validate()] gives minimal messages of what's wrong with our `cff` and +(invisibly) returns the result of the validation (`TRUE/FALSE`). + +## Other methods + +### [as.data.frame()] + +```{r} +minimal_cff <- cff() + +minimal_cff + +as_df <- as.data.frame(minimal_cff) + +class(as_df) + +t(as_df) +``` + +## [c()] + +```{r} +new_keys <- c("date-released" = "2020-01-31", abstract = "Minimal example") + +c(minimal_cff, new_keys) +``` + +## [as.person()] + +Special case for those CFF keys that are person-like. + +```{r} +path <- system.file("examples/CITATION_complete.cff", package = "cffr") +the_cff <- cff_read(path) + +the_cff$authors + +as.person(the_cff$authors) +``` diff --git a/man/chunks/person.Rmd b/man/chunks/person.Rmd new file mode 100644 index 00000000..38a02d67 --- /dev/null +++ b/man/chunks/person.Rmd @@ -0,0 +1,20 @@ +```{r include=FALSE} +library(cffr) +initopt <- getOption("cffr_message_verbosity", NULL) +options("cffr_message_verbosity" = NULL) +``` + +```{r} +# Don't do +entity <- "Elephant and Castle" +as_cff_person(entity) + +# Do +entity_protect <- "{Elephant and Castle}" +as_cff_person(entity_protect) +``` + +```{r include=FALSE} +# Restore +options("cffr_message_verbosity" = initopt) +``` diff --git a/man/chunks/value.Rmd b/man/chunks/value.Rmd new file mode 100644 index 00000000..5d8ae303 --- /dev/null +++ b/man/chunks/value.Rmd @@ -0,0 +1,2 @@ +A [`cff`][cff-class] object ready to be used with other functions (i.e. +[cff_create()]. diff --git a/man/cran_to_spdx.Rd b/man/cran_to_spdx.Rd index 5ad515ee..9ad8e40f 100644 --- a/man/cran_to_spdx.Rd +++ b/man/cran_to_spdx.Rd @@ -31,4 +31,5 @@ head(cran_to_spdx, 20) \seealso{ \emph{Writing R Extensions}, \href{https://cran.r-project.org/doc/manuals/r-release/R-exts.html#Licensing}{Licensing section}. } +\concept{datasets} \keyword{datasets} diff --git a/man/deprecated_cff_bibentry.Rd b/man/deprecated_cff_bibentry.Rd new file mode 100644 index 00000000..543209c7 --- /dev/null +++ b/man/deprecated_cff_bibentry.Rd @@ -0,0 +1,39 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/deprecated.R +\name{cff_parse_citation} +\alias{cff_parse_citation} +\title{Previous API: Parse a \code{bibentry} to \code{cff}} +\usage{ +cff_parse_citation(bib) +} +\arguments{ +\item{bib}{A \code{bibentry} object.} +} +\value{ +A \code{bibentry} in format \code{cff}. +} +\description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} Please use \code{\link[=as_cff.bibentry]{as_cff.bibentry()}} method +} +\examples{ + +bib <- citation("base") +bib + + +# To cff +bib_to_cff <- as_cff(bib) +bib_to_cff + +} +\seealso{ +\code{\link[=as_cff.bibentry]{as_cff.bibentry()}} + +Other deprecated functions: +\code{\link{cff_extract_to_bibtex}()}, +\code{\link{cff_from_bibtex}()}, +\code{\link{cff_parse_person}()}, +\code{\link{write_bib}()} +} +\concept{deprecated} +\keyword{internal} diff --git a/man/cff_from_bibtex.Rd b/man/deprecated_cff_from_bib.Rd similarity index 54% rename from man/cff_from_bibtex.Rd rename to man/deprecated_cff_from_bib.Rd index d87fc3b4..24063661 100644 --- a/man/cff_from_bibtex.Rd +++ b/man/deprecated_cff_from_bib.Rd @@ -1,17 +1,17 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/cff_from_bibtex.R +% Please edit documentation in R/deprecated.R \name{cff_from_bibtex} \alias{cff_from_bibtex} -\title{Create a cff object from BibTeX entries} +\title{Previous API: Create a \code{\link{cff}} object from BibTeX entries} \usage{ cff_from_bibtex(x, encoding = "UTF-8", ...) } \arguments{ -\item{x}{The source that would be used for generating the \code{cff} object. A -\code{character} object indicating either: +\item{x}{The source that would be used for generating the +\code{\link{cff}} object. Must be \code{character} object indicating either: \itemize{ \item The path to a BibTeX file. -\item A vector of characters with the full BibTeX string. See \strong{Examples} +\item A vector of characters with the full BibTeX string. See \strong{Examples}. }} \item{encoding}{Encoding to be assumed for \code{x}. See \code{\link[=readLines]{readLines()}}.} @@ -19,15 +19,12 @@ cff_from_bibtex(x, encoding = "UTF-8", ...) \item{...}{Other arguments passed to \code{\link[bibtex:read.bib]{bibtex::read.bib()}}.} } \value{ -A \code{\link{cff}} object ready to be used on \code{\link[=cff_create]{cff_create()}}. +See \code{\link[=cff_read_bib]{cff_read_bib()}} from reading \verb{*.bib} files and \code{\link[=cff_read_bib_text]{cff_read_bib_text()}} +for reading a \code{character} object representing a BibTeX entry. } \description{ -Extract the information of a BibTeX file or BibTeX entry and creates the -corresponding \code{\link{cff}} object with \code{\link[=cff_parse_citation]{cff_parse_citation()}}. -} -\details{ -This function requires the package \CRANpkg{bibtex} (>= 0.5.0), that is -listed as \code{Suggested} by \CRANpkg{cffr}. +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} Please use either \code{\link[=cff_read_bib]{cff_read_bib()}} or +\code{\link[=cff_read_bib_text]{cff_read_bib_text()}} instead. } \examples{ if (requireNamespace("bibtex", quietly = TRUE)) { @@ -50,22 +47,20 @@ if (requireNamespace("bibtex", quietly = TRUE)) { }" ) - cff_from_bibtex(x) + cff_read_bib_text(x) # From a file x2 <- system.file("examples/example.bib", package = "cffr") - cff_from_bibtex(x2) + cff_read_bib(x2) } } \seealso{ -\code{vignette("bibtex_cff", package = "cffr")} to learn about the mapping of -information between BibTeX and CITATION.cff. - -Other BibTeX helpers: -\code{\link{cff_to_bibentry}()}, -\code{\link{encoded_utf_to_latex}()}, -\code{\link{write_bib}()}, -\code{\link{write_citation}()} +Other deprecated functions: +\code{\link{cff_extract_to_bibtex}()}, +\code{\link{cff_parse_citation}()}, +\code{\link{cff_parse_person}()}, +\code{\link{write_bib}()} } -\concept{BibTeX helpers} +\concept{deprecated} +\keyword{internal} diff --git a/man/deprecated_cff_person.Rd b/man/deprecated_cff_person.Rd new file mode 100644 index 00000000..cd4f1140 --- /dev/null +++ b/man/deprecated_cff_person.Rd @@ -0,0 +1,76 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/deprecated.R +\name{cff_parse_person} +\alias{cff_parse_person} +\alias{cff_parse_person_bibtex} +\title{Previous API: Parse a \code{person} to \code{\link{cff}}} +\usage{ +cff_parse_person(person) + +cff_parse_person_bibtex(person) +} +\arguments{ +\item{person}{It can be either: +\itemize{ +\item A \code{person} or list of \code{person} object created with \code{\link[utils:person]{utils::person()}}. +\item A \code{character} object or vector representing a person or persons. +See \strong{Examples}. +}} +} +\value{ +A person in format \code{cff}. +} +\description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} Please use \code{\link[=as_cff_person]{as_cff_person()}} +} +\examples{ +# Create a person object +a_person <- person( + given = "First", family = "Author", + role = c("aut", "cre"), + email = "first.last@example.com", comment = c( + ORCID = "0000-0001-8457-4658", + affiliation = "An affiliation" + ) +) + +a_person + +cff_person <- as_cff_person(a_person) + +cff_person + +# Back to person object with S3 Method +as.person(cff_person) + +# Parse a string +a_str <- paste0( + "Julio Iglesias ", + "()" +) +as_cff_person(a_str) + +# Several persons +persons <- c(person("Clark", "Kent"), person("Lois", "Lane")) + +as_cff_person(persons) + +# Or you can use BibTeX style if you prefer + +x <- "Frank Sinatra and Dean Martin and Davis, Jr., Sammy and Joey Bishop" + +as_cff_person(x) + +as_cff_person("Herbert von Karajan") +} +\seealso{ +\code{\link[=as_cff_person]{as_cff_person()}} + +Other deprecated functions: +\code{\link{cff_extract_to_bibtex}()}, +\code{\link{cff_from_bibtex}()}, +\code{\link{cff_parse_citation}()}, +\code{\link{write_bib}()} +} +\concept{deprecated} +\keyword{internal} diff --git a/man/previous_cff_to_bib.Rd b/man/deprecated_cff_to_bib.Rd similarity index 72% rename from man/previous_cff_to_bib.Rd rename to man/deprecated_cff_to_bib.Rd index 94761d70..3d6cca79 100644 --- a/man/previous_cff_to_bib.Rd +++ b/man/deprecated_cff_to_bib.Rd @@ -2,9 +2,12 @@ % Please edit documentation in R/deprecated.R \name{cff_extract_to_bibtex} \alias{cff_extract_to_bibtex} +\alias{cff_to_bibtex} \title{Previous API: Create BibTeX entries from several sources} \usage{ cff_extract_to_bibtex(x, what = c("preferred", "references", "all")) + +cff_to_bibtex(x, what = c("preferred", "references", "all")) } \arguments{ \item{x}{The source that would be used for generating @@ -28,11 +31,10 @@ both the preferred citation info and the references. }} } \value{ -See \code{\link[=cff_to_bibentry]{cff_to_bibentry()}} +See \code{\link[=as_bibentry]{as_bibentry()}}. } \description{ -\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#superseded}{\figure{lifecycle-superseded.svg}{options: alt='[Superseded]'}}}{\strong{[Superseded]}} -Please use \code{\link[=cff_to_bibentry]{cff_to_bibentry()}} instead. +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} Please use \code{\link[=as_bibentry]{as_bibentry()}} instead. } \examples{ \donttest{ @@ -42,7 +44,15 @@ cff_object <- cff() cff_object # bibentry object -bib <- cff_to_bibentry(cff_object) +bib <- as_bibentry(cff_object) +} } +\seealso{ +Other deprecated functions: +\code{\link{cff_from_bibtex}()}, +\code{\link{cff_parse_citation}()}, +\code{\link{cff_parse_person}()}, +\code{\link{write_bib}()} } +\concept{deprecated} \keyword{internal} diff --git a/man/deprecated_write.Rd b/man/deprecated_write.Rd new file mode 100644 index 00000000..645d0b02 --- /dev/null +++ b/man/deprecated_write.Rd @@ -0,0 +1,67 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/deprecated.R +\name{write_bib} +\alias{write_bib} +\alias{write_citation} +\title{Previous API: Write files} +\usage{ +write_bib(x, file = tempfile(), append = FALSE, verbose = TRUE, ascii = FALSE) + +write_citation( + x, + file = "./inst/CITATION", + append = FALSE, + verbose = TRUE, + ... +) +} +\arguments{ +\item{x}{A \code{\link[=bibentry]{bibentry}} or a \code{\link{cff}} object.} + +\item{file}{Name of the file to be created. If \code{NULL} it would display the +lines to be written.} + +\item{append}{Whether to append the entries to an existing file or not.} + +\item{verbose}{Display informative messages} + +\item{ascii}{Whether to write the entries using ASCII characters only or not.} +} +\value{ +Write a file. +} +\description{ +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} Please use \code{\link[=cff_write_bib]{cff_write_bib()}} or +\code{\link[=cff_write_citation]{cff_write_citation()}} instead. +} +\examples{ + +bib <- bibentry("Misc", + title = "My title", + author = "Fran Pérez" +) + +my_temp_bib <- tempfile(fileext = ".bib") + +cff_write_bib(bib, file = my_temp_bib) + +cat(readLines(my_temp_bib), sep = "\n") + +cff_write_bib(bib, file = my_temp_bib, ascii = TRUE, append = TRUE) + +cat(readLines(my_temp_bib), sep = "\n") +} +\seealso{ +\itemize{ +\item \code{\link[=cff_write_bib]{cff_write_bib()}} for writing \verb{*.bib} files. +\item \code{\link[=cff_write_citation]{cff_write_citation()}} for writing \strong{R} \code{CITATION} files. +} + +Other deprecated functions: +\code{\link{cff_extract_to_bibtex}()}, +\code{\link{cff_from_bibtex}()}, +\code{\link{cff_parse_citation}()}, +\code{\link{cff_parse_person}()} +} +\concept{deprecated} +\keyword{internal} diff --git a/man/encoded_utf_to_latex.Rd b/man/encoded_utf_to_latex.Rd index 43cd3d1d..339e1068 100644 --- a/man/encoded_utf_to_latex.Rd +++ b/man/encoded_utf_to_latex.Rd @@ -1,5 +1,5 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/utils-bibtex.R +% Please edit documentation in R/encoded_utf_to_latex.R \name{encoded_utf_to_latex} \alias{encoded_utf_to_latex} \title{Encode UTF-8 text to LaTeX} @@ -20,7 +20,6 @@ This is a variation of \code{\link[tools:encoded]{tools::encoded_text_to_latex() additional replacements to increase compatibility. } \examples{ -\dontshow{if (getRversion() >= "4.0.0") (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} # Full range of supported characters on R library(tools) @@ -40,16 +39,15 @@ ascii_table$latex_base <- encoded_text_to_latex(ascii_table$utf8, ascii_table$latex_cffr <- encoded_utf_to_latex(ascii_table$utf8) ascii_table -\dontshow{\}) # examplesIf} } \seealso{ \code{\link[tools:encoded]{tools::encoded_text_to_latex()}} -Other BibTeX helpers: -\code{\link{cff_from_bibtex}()}, -\code{\link{cff_to_bibentry}()}, -\code{\link{write_bib}()}, -\code{\link{write_citation}()} +Other functions for working with BibTeX format: +\code{\link{as_bibentry}()}, +\code{\link{cff_read}()}, +\code{\link{cff_read_bib_text}()}, +\code{\link{cff_write_bib}()} } -\concept{BibTeX helpers} +\concept{bibtex} \keyword{internal} diff --git a/man/roxygen/meta.R b/man/roxygen/meta.R new file mode 100644 index 00000000..54a0daf6 --- /dev/null +++ b/man/roxygen/meta.R @@ -0,0 +1,13 @@ +list( + rd_family_title = list( + core = "Other core functions of \\CRANpkg{cffr}:", + reading = "Other functions for reading external files:", + coercing = "Other functions for converting between \\strong{R} classes:", + writing = "Other functions for creating external files:", + bibtex = "Other functions for working with BibTeX format:", + schemas = "Other CFF schemas:", + git = "Other Git/GitHub helpers:", + deprecated = "Other deprecated functions:", + s3method = "Other S3 Methods for \\code{cff}:" + ) +) diff --git a/man/roxygen2/meta.R b/man/roxygen2/meta.R deleted file mode 100644 index b8aec5fc..00000000 --- a/man/roxygen2/meta.R +++ /dev/null @@ -1,7 +0,0 @@ -list( - rd_family_title = list( - bibtex = "Coercing objects from/to BibTeX:", - git = "Git utils:", - schema = "CFF schemas:" - ) -) diff --git a/man/write_bib.Rd b/man/write_bib.Rd deleted file mode 100644 index 5240e5a0..00000000 --- a/man/write_bib.Rd +++ /dev/null @@ -1,63 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/write_bib.R -\name{write_bib} -\alias{write_bib} -\title{Create a \code{.bib} file} -\usage{ -write_bib(x, file = NULL, append = FALSE, verbose = TRUE, ascii = FALSE) -} -\arguments{ -\item{x}{A \code{bibentry} object created with: -\itemize{ -\item \code{\link[=cff_to_bibentry]{cff_to_bibentry()}} -\item \code{\link[=citation]{citation()}} or \code{\link[=bibentry]{bibentry()}} -}} - -\item{file}{Name of the file. If \code{NULL} it would display the lines to be -written.} - -\item{append}{Whether to append the entries to an existing file or not.} - -\item{verbose}{Display informative messages} - -\item{ascii}{Whether to write the entries using ASCII characters only or not.} -} -\value{ -Writes an \code{.bib} file specified on \code{file} parameter and the -equivalent \code{Bibtex} object created with \code{\link[utils:toLatex]{utils::toBibtex()}}. It also -(invisibly) returns the \code{bibentry} object that has been written to the file. -} -\description{ -Creates \verb{a .bib} file from a \code{bibentry} object(s) -} -\details{ -For security reasons, if the file already exists the function would create -a backup copy on the same directory. -} -\examples{ - -bib <- bibentry("Misc", - title = "My title", - author = "Fran Pérez" -) - -write_bib(bib) - -write_bib(bib, ascii = TRUE) -} -\seealso{ -\code{vignette("bibtex_cff", "cffr")}, \code{\link[knitr:write_bib]{knitr::write_bib()}} and the -following packages: -\itemize{ -\item \CRANpkg{bibtex}. -\item \CRANpkg{RefManageR} -\item \CRANpkg{rbibutils} -} - -Other BibTeX helpers: -\code{\link{cff_from_bibtex}()}, -\code{\link{cff_to_bibentry}()}, -\code{\link{encoded_utf_to_latex}()}, -\code{\link{write_citation}()} -} -\concept{BibTeX helpers} diff --git a/man/write_citation.Rd b/man/write_citation.Rd deleted file mode 100644 index 55d8d8fe..00000000 --- a/man/write_citation.Rd +++ /dev/null @@ -1,98 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/write_citation.R -\name{write_citation} -\alias{write_citation} -\title{Create a \code{inst/CITATION} file} -\usage{ -write_citation( - x, - file = "./inst/CITATION", - append = FALSE, - verbose = TRUE, - ... -) -} -\arguments{ -\item{x}{It could be -\itemize{ -\item A \code{bibentry} object created with \code{\link[=cff_to_bibentry]{cff_to_bibentry()}}, \code{\link[=citation]{citation()}} or -\code{\link[=bibentry]{bibentry()}} -\item Any of the valid inputs of \code{\link[=cff_to_bibentry]{cff_to_bibentry()}}: -\itemize{ -\item A missing value. That would retrieve the DESCRIPTION file on your -in-development package. -\item An existing \code{\link{cff}} object, -\item Path to a CITATION.cff file (\code{"*/CITATION.cff*"}), -\item The name of an installed package (\code{"jsonlite"}), or -\item Path to a DESCRIPTION file (\code{"*/DESCRIPTION*"}). -} -}} - -\item{file}{Name of the file to write.} - -\item{append}{Whether to append the entries to an existing file or not.} - -\item{verbose}{Display informative messages} - -\item{...}{ - Arguments passed on to \code{\link[=cff_to_bibentry]{cff_to_bibentry}} - \describe{ - \item{\code{what}}{Fields to extract. The value could be: -\itemize{ -\item \code{preferred}: This would create a single entry with the main citation -info of the package. -\item \code{references}: Extract all the entries on \code{references}. -\item \code{all}: A combination of the previous two options. This would extract -both the preferred citation info and the references. -}} - }} -} -\value{ -Writes an \code{inst/CITATION} file and (invisibly) returns the -\code{bibentry} object that has been written to the file. -} -\description{ -Creates a R CITATION file (inst/CITATION) from the metadata of a -CITATION.cff file or \code{cff} object. -} -\details{ -For security reasons, if the file already exists the function would create -a backup copy on the same directory. -} -\examples{ -# Use a system file -f <- system.file("examples/preferred-citation-book.cff", package = "cffr") - -# Write to tmp dir -out <- file.path(tempdir(), "CITATION") -write_citation(f, file = out) - -# Check by reading, use meta object - -meta <- packageDescription("cffr") -meta$Encoding <- "UTF-8" - -utils::readCitationFile(out, meta) - - -# Append to the same file -bib2 <- citation() -write_citation(bib2, file = out, append = TRUE) - -utils::readCitationFile(out, meta) -} -\references{ -R Core Team (2023). "CITATION files." In Writing R Extensions, chapter 1.9, -R version 4.3.0 (2023-04-21) edition. -\url{https://cran.r-project.org/doc/manuals/R-exts.html#CITATION-files}. -} -\seealso{ -\code{\link[=bibentry]{bibentry()}} and \code{style} argument. - -Other BibTeX helpers: -\code{\link{cff_from_bibtex}()}, -\code{\link{cff_to_bibentry}()}, -\code{\link{encoded_utf_to_latex}()}, -\code{\link{write_bib}()} -} -\concept{BibTeX helpers} diff --git a/pkgdown/_pkgdown.yml b/pkgdown/_pkgdown.yml index 3c09c5f9..ca293aec 100644 --- a/pkgdown/_pkgdown.yml +++ b/pkgdown/_pkgdown.yml @@ -1,46 +1,62 @@ url: 'https://docs.ropensci.org/cffr' + template: opengraph: twitter: creator: '@dhernangomez' card: summary_large_image + repo: branch: main + +home: + title: cffr | Generate Citation File Format (CFF) files for R packages + description: >- + Utilities to generate and validate CFF files with R. + reference: - - title: Main function + - title: The whole game + - subtitle: The function desc: >- The main function of the package and likely to be the only one you would need. + contents: cff_write + - subtitle: Other core functions + desc: 'Create, modify and write and `cff` objects.' + contents: has_concept("core") + - subtitle: The `cff` class + desc: Brief introduction to the `cff` class and S3 Methods available. contents: - - cff_write - - title: Other core functions - desc: 'Create, write and manipulate files and objects.' - contents: - - has_concept("Core functions") - - title: Citation File Format schema + - cff-class + - has_concept("s3method") + - subtitle: Citation File Format schema desc: >- These functions provides lists of valid keys and fields as defined by the CFF schema.json **(v1.2.0)**. - contents: - - has_concept("Schemas") - - title: Parsers - desc: Helper functions to parse information. - contents: - - has_concept("Parsers") - - title: BibTeX - desc: Convert CFF to BibTeX and viceversa - contents: - - has_concept("BibTeX helpers") - - cff_parse_citation - - title: Datasets - contents: - - has_keyword("datasets") + contents: has_concept("schemas") - title: Continuous Integration + contents: has_concept("git") + - title: Additional features + - subtitle: Read and write files + desc: >- + Read and write local files on different formats (CFF files, BibTeX, + etc.). contents: - - has_concept("Git helpers") + - has_concept("reading") + - has_concept("writing") + - subtitle: Coercing objects + desc: >- + Coerce **R** objects into different classes (`cff`, `person`, `bibentry`) + and more: + contents: has_concept("coercing") + - subtitle: BibTeX helpers + desc: Functions that works with BibTeX markup language. + contents: has_concept("bibtex") + - title: Datasets + contents: has_concept("datasets") - title: About the package - contents: - - cffr-package + contents: cffr-package + navbar: structure: left: @@ -64,12 +80,14 @@ navbar: href: 'https://ropensci.org/blog/2021/11/23/how-i-test-cffr/' - text: '---' - text: Blogs - - text: 'How To Call Package Citations in R programming' - href: 'https://medium.com/analytics-vidhya/how-to-call-package-citations-in-r-programming-6f01f1176301' + - text: How To Call Package Citations in R programming + href: >- + https://medium.com/analytics-vidhya/how-to-call-package-citations-in-r-programming-6f01f1176301 - text: '---' - text: Podcasts - text: 'R Weekly Highlights: Issue 2021-W48 Highlights' href: 'https://share.fireside.fm/episode/87RSVeFz+4R-j8_xW' + authors: Diego Hernangómez: href: 'https://dieghernan.github.io/' diff --git a/revdep/README.md b/revdep/README.md index 78b0eb13..3048da07 100644 --- a/revdep/README.md +++ b/revdep/README.md @@ -1,34 +1,32 @@ # Platform -|field |value | -|:--------|:--------------------------------------| -|version |R version 4.3.0 (2023-04-21 ucrt) | -|os |Windows 11 x64 (build 22621) | -|system |x86_64, mingw32 | -|ui |RStudio | -|language |(EN) | -|collate |Spanish_Spain.utf8 | -|ctype |Spanish_Spain.utf8 | -|tz |Europe/Madrid | -|date |2023-05-05 | -|rstudio |2023.03.0+386 Cherry Blossom (desktop) | -|pandoc |2.19.2 @ C:\PROGRA~1\Pandoc\pandoc.exe | +|field |value | +|:--------|:------------------------------| +|version |R version 4.3.2 (2023-10-31) | +|os |macOS Monterey 12.7.3 | +|system |x86_64, darwin20 | +|ui |X11 | +|language |(EN) | +|collate |en_US.UTF-8 | +|ctype |en_US.UTF-8 | +|tz |UTC | +|date |2024-03-01 | +|pandoc |3.1.11 @ /usr/local/bin/pandoc | # Dependencies -|package |old |new |Δ | -|:------------|:------|:------|:--| -|cffr |0.4.1 |0.5.0 |* | -|cli |3.6.1 |3.6.1 | | -|curl |5.0.0 |5.0.0 | | -|desc |1.4.2 |1.4.2 | | -|jsonlite |1.8.4 |1.8.4 | | -|jsonvalidate |1.3.2 |1.3.2 | | -|R6 |2.5.1 |2.5.1 | | -|Rcpp |1.0.10 |1.0.10 | | -|rprojroot |2.0.3 |2.0.3 | | -|V8 |4.3.0 |4.3.0 | | -|yaml |2.3.7 |2.3.7 | | +|package |old |new |Δ | +|:------------|:------|:----------|:--| +|cffr |0.5.0 |0.5.0.9000 |* | +|cli |3.6.2 |3.6.2 | | +|curl |5.2.0 |5.2.0 | | +|desc |1.4.3 |1.4.3 | | +|jsonlite |1.8.8 |1.8.8 | | +|jsonvalidate |1.3.2 |1.3.2 | | +|R6 |2.5.1 |2.5.1 | | +|Rcpp |1.0.12 |1.0.12 | | +|V8 |4.4.2 |4.4.2 | | +|yaml |2.3.8 |2.3.8 | | # Revdeps diff --git a/tests/testthat/_snaps/cff_to_bibentry.md b/tests/testthat/_snaps/as_bibentry.md similarity index 91% rename from tests/testthat/_snaps/cff_to_bibentry.md rename to tests/testthat/_snaps/as_bibentry.md index 80e419b9..6bb63ce4 100644 --- a/tests/testthat/_snaps/cff_to_bibentry.md +++ b/tests/testthat/_snaps/as_bibentry.md @@ -12,9 +12,7 @@ number = {2}, pages = {97--111}, month = {January}, - keywords = {Some}, - keywords = {simple}, - keywords = {keywords}, + keywords = {Some, simple, keywords}, } --- @@ -226,6 +224,23 @@ organization = {IJCAI}, } +--- + + Code + toBibtex(bib) + Output + @InProceedings{aberdeenbayer:1999, + title = {Implementing Practical Dialogue Systems with the DARPA Communicator Architecture}, + author = {John Aberdeen and Samuel Bayer and Sasha Caskey and Laurie Damianos and Alan Goldschen and Lynette Hirschman and Dan Loehr and Hugo Trapper}, + year = {1999}, + booktitle = {I Am a conference}, + publisher = {International Joint Conference on Artificial Intelligence}, + address = {Murray Hill, New Jersey}, + editor = {Jan Alexandersson}, + pages = {81--86}, + organization = {IJCAI}, + } + # Manual to bibtex Code @@ -394,23 +409,35 @@ note = {Unpublished MS, Computer Science Department, University of Pittsburgh.}, } +--- + + Code + toBibtex(bib) + Output + @Unpublished{aronisprovost:1959, + title = {Efficiently Constructing Relational Features from Background}, + author = {John M. Aronis and Foster J. Provost}, + year = {1959}, + note = {Extracted with cffr R package}, + } + # particle names Code bibparsed Output - type: book - title: A Handbook for Scholars - authors: - - family-names: Leunen - given-names: Mary-Claire - name-particle: van - - family-names: Davis - given-names: Sammy - name-suffix: Jr. - year: '1979' - publisher: - name: Knopf + - type: book + title: A Handbook for Scholars + authors: + - family-names: Leunen + given-names: Mary-Claire + name-particle: van + - family-names: Davis + given-names: Sammy + name-suffix: Jr. + year: '1979' + publisher: + name: Knopf --- @@ -618,9 +645,18 @@ Code toBibtex(parsed) Output - @Misc{doe, + @Misc{doe:2020, title = {My Research Software}, author = {John Doe}, year = {2020}, } +# Corrupt entry + + Code + n <- as_bibentry(x) + Message + x Can't convert to `bibentry()`: + i A bibentry of bibtype 'Article' has to specify the fields: journal, year + ! Returning "NULL" + diff --git a/tests/testthat/_snaps/as_cff.md b/tests/testthat/_snaps/as_cff.md new file mode 100644 index 00000000..9c131a6b --- /dev/null +++ b/tests/testthat/_snaps/as_cff.md @@ -0,0 +1,39 @@ +# as.cff still works + + Code + l2 + Output + cff-version: 1.2.0 + title: Manipulating files + +# as_cff.person + + Code + as_cff(pers) + Output + - family-names: person + given-names: A + email: fake@gmail.com + orcid: https://orcid.org/0000-0000-0000-0000 + affiliation: Real Madrid + website: https://www.google.com/ + +# as_cff.bibentry, toBibtex + + Code + bbb + Output + - type: generic + title: title + authors: + - name: Author + editors: + - name: Editor + +# as_cff.default + + Code + as_cff(b) + Output + a: '1' + diff --git a/tests/testthat/_snaps/as_cff_person.md b/tests/testthat/_snaps/as_cff_person.md new file mode 100644 index 00000000..86569528 --- /dev/null +++ b/tests/testthat/_snaps/as_cff_person.md @@ -0,0 +1,97 @@ +# debugging messages + + Code + a <- as_cff_person(ap) + Message + i In `as_cff_person()` using internal for "person". + +--- + + Code + b <- as_cff_person("Example") + Message + i In `as_cff_person()` using internal for "txt". + +# Parse one person + + Code + as_cff_person(p) + Output + - family-names: person + given-names: one + +# Parse several persons + + Code + as_cff_person(p) + Output + - family-names: person + given-names: one + - family-names: human + given-names: another + - family-names: more + given-names: and one + +# Parse bibtex persons + + Code + as_cff_person(s) + Output + - family-names: Wright + given-names: Frank Edwin + name-suffix: III + +--- + + Code + as_cff_person(s) + Output + - family-names: person + given-names: A + - name: another + - family-names: one + given-names: Another + +# Parse bibtex persons with masks + + Code + as_cff_person(s) + Output + - name: Elephant + - name: Castle + +--- + + Code + as_cff_person(s) + Output + - name: Elephant and Castle + +--- + + Code + as_cff_person(s) + Output + - name: Elephant and Castle + - name: this + - name: Ltd. + +--- + + Code + as_cff_person(s) + Output + - name: Elephant and Castle + - name: this AND Ltd. + +# Can extract comments from format + + Code + pp2 + Output + - family-names: Doe + given-names: John + email: first_mail@gmail.com + orcid: https://orcid.org/0000-0001-8457-4658 + website: https://www.google.com/ + diff --git a/tests/testthat/_snaps/as_cff_reference.md b/tests/testthat/_snaps/as_cff_reference.md new file mode 100644 index 00000000..909d91e2 --- /dev/null +++ b/tests/testthat/_snaps/as_cff_reference.md @@ -0,0 +1,767 @@ +# Test full with CITATION and (option = author) + + Code + cffobj + Output + cff-version: 1.2.0 + message: 'To cite package "rgeos" in publications use:' + type: software + license: GPL-2.0-or-later + title: 'rgeos: Interface to Geometry Engine - Open Source (''GEOS'')' + version: 0.5-7 + abstract: 'Interface to Geometry Engine - Open Source (''GEOS'') using the C ''API'' + for topology operations on geometries. Please note that ''rgeos'' will be retired + by the end of 2023, plan transition to sf functions using ''GEOS'' at your earliest + convenience. The ''GEOS'' library is external to the package, and, when installing + the package from source, must be correctly installed first. Windows and Mac Intel + OS X binaries are provided on ''CRAN''. (''rgeos'' >= 0.5-1): Up to and including + ''GEOS'' 3.7.1, topological operations succeeded with some invalid geometries for + which the same operations fail from and including ''GEOS'' 3.7.2. The ''checkValidity='' + argument defaults and structure have been changed, from default FALSE to integer + default ''0L'' for ''GEOS'' < 3.7.2 (no check), ''1L'' ''GEOS'' >= 3.7.2 (check + and warn). A value of ''2L'' is also provided that may be used, assigned globally + using ''set_RGEOS_CheckValidity(2L)'', or locally using the ''checkValidity=2L'' + argument, to attempt zero-width buffer repair if invalid geometries are found. The + previous default (FALSE, now ''0L'') is fastest and used for ''GEOS'' < 3.7.2, but + will not warn users of possible problems before the failure of topological operations + that previously succeeded. From ''GEOS'' 3.8.0, repair of geometries may also be + attempted using ''gMakeValid()'', which may, however, return a collection of geometries + of different types.' + authors: + - family-names: Bivand + given-names: Roger + email: Roger.Bivand@nhh.no + orcid: https://orcid.org/0000-0003-2392-6140 + - family-names: Rundel + given-names: Colin + repository: https://CRAN.R-project.org/package=rgeos + repository-code: https://r-forge.r-project.org/projects/rgeos/ + url: https://trac.osgeo.org/geos/ + date-released: '2020-09-07' + contact: + - family-names: Bivand + given-names: Roger + email: Roger.Bivand@nhh.no + orcid: https://orcid.org/0000-0003-2392-6140 + references: + - type: manual + title: 'rgeos: Interface to Geometry Engine - Open Source (''GEOS'')' + authors: + - family-names: Bivand + given-names: Roger + email: Roger.Bivand@nhh.no + orcid: https://orcid.org/0000-0003-2392-6140 + - family-names: Rundel + given-names: Colin + year: '2020' + notes: R package version 0.5-7 + url: https://CRAN.R-project.org/package=rgeos + - type: article + title: 'RNeXML: A Package for Reading and Writing Richly Annotated Phylogenetic, + Character, and Trait Data in R' + authors: + - family-names: Boettiger + given-names: Carl + - family-names: Chamberlain + given-names: Scott + - family-names: Vos + given-names: Rutger + - family-names: Lapp + given-names: Hilmar + journal: Methods in Ecology and Evolution + year: '2016' + volume: '7' + doi: 10.1111/2041-210X.12469 + start: '352' + end: '357' + - type: book + title: 'ggplot2: Elegant Graphics for Data Analysis' + authors: + - family-names: Wickham + given-names: Hadley + publisher: + name: Springer-Verlag New York + year: '2016' + isbn: 978-3-319-24277-4 + url: https://ggplot2.tidyverse.org + identifiers: + - type: url + value: http://rgeos.r-forge.r-project.org/index.html + +# Parsed several citations + + Code + citobj + Output + - type: manual + title: 'rgeos: Interface to Geometry Engine - Open Source (''GEOS'')' + authors: + - family-names: Bivand + given-names: Roger + email: Roger.Bivand@nhh.no + orcid: https://orcid.org/0000-0003-2392-6140 + - family-names: Rundel + given-names: Colin + year: '2020' + notes: R package version 0.5-7 + url: https://CRAN.R-project.org/package=rgeos + - type: article + title: 'RNeXML: A Package for Reading and Writing Richly Annotated Phylogenetic, + Character, and Trait Data in R' + authors: + - family-names: Boettiger + given-names: Carl + - family-names: Chamberlain + given-names: Scott + - family-names: Vos + given-names: Rutger + - family-names: Lapp + given-names: Hilmar + journal: Methods in Ecology and Evolution + year: '2016' + volume: '7' + doi: 10.1111/2041-210X.12469 + start: '352' + end: '357' + - type: book + title: 'ggplot2: Elegant Graphics for Data Analysis' + authors: + - family-names: Wickham + given-names: Hadley + publisher: + name: Springer-Verlag New York + year: '2016' + isbn: 978-3-319-24277-4 + url: https://ggplot2.tidyverse.org + +# Add wrong field to citation + + Code + cffobj + Output + cff-version: 1.2.0 + message: If you use this software, please cite it using these metadata. + title: My Research Software + authors: + - family-names: Doe + given-names: John + references: + - type: manual + title: favoritefood is not valid on cff schema + authors: + - family-names: Smith + given-names: Jane + +# Fix wrong orcid + + Code + cffobj + Output + cff-version: 1.2.0 + message: If you use this software, please cite it using these metadata. + title: My Research Software + authors: + - family-names: Doe + given-names: John + references: + - type: manual + title: Wrong orcid fixed by cffr + authors: + - family-names: Smith + given-names: Jane + orcid: https://orcid.org/0000-0000-0000-306X + +# Several identifiers and duplicates + + Code + cffobj + Output + cff-version: 1.2.0 + message: If you use this software, please cite it using these metadata. + title: My Research Software + authors: + - family-names: Doe + given-names: John + references: + - type: manual + title: A Language and Environment for Statistical Computing + authors: + - name: R Core Team + year: '2022' + url: https://www.R-project.org/ + doi: 10.5281/zenodo.5366600 + identifiers: + - type: doi + value: 10.5281/zenodo.5366601 + - type: doi + value: 10.5281/zenodo.5366602 + - type: url + value: https://google.com/ + +# Test keywords and urls + + Code + cffobj + Output + cff-version: 1.2.0 + message: If you use this software, please cite it using these metadata. + title: My Research Software + authors: + - family-names: Doe + given-names: John + references: + - type: manual + title: A Language and Environment for Statistical Computing + authors: + - name: R Core Team + year: '2022' + url: https://www.R-project.org/ + keywords: + - Some + - random keywords + - in + - here + identifiers: + - type: url + value: https://google.com/ + +# Parse persons on CITATION + + Code + bibparsed + Output + - type: manual + title: A Language and Environment for Statistical Computing + authors: + - name: R Core Team + year: '2021' + contact: + - family-names: name + given-names: A + - family-names: contact + given-names: A + conference: + name: A conference + address: A location + database-provider: + name: Database provider + editors: + - family-names: editor + given-names: A + - name: Ben and Jerry + editors-series: + - family-names: editor series + given-names: An + - name: Another + publisher: + name: A publisher + recipients: + - family-names: recipient + given-names: A + senders: + - name: A Sender + - family-names: Sender + given-names: Another + translators: + - family-names: one + given-names: Translator + - family-names: two + given-names: Translator + +# Test inputs + + Code + bibparsed + Output + - type: book + title: Test + authors: + - family-names: Jean + given-names: Billy + year: '2021' + publisher: + name: Random House + +# Article + + Code + bibparsed + Output + - type: article + title: Literate Programming + authors: + - name: R Core Team + journal: The Computer Journal + year: '1984' + volume: '27' + issue: '2' + month: '1' + notes: Example modified for testing purposes + start: '97' + end: '111' + +# Book + + Code + bibparsed + Output + - type: book + title: The LaTeX Companion + authors: + - family-names: Mittelbach + given-names: Frank + - family-names: Gossens + given-names: Michel + - family-names: Braams + given-names: Johannes + - family-names: Carlisle + given-names: David + - family-names: Rowley + given-names: Chris + editors: + - name: Barnes and Noble + publisher: + name: Addison-Wesley Professional + address: Santa Monica + year: '2004' + volume: '3' + issue: '7' + collection-title: The LateX Books + collection-type: book + edition: Fourth + month: '8' + notes: Example modified for testing purposes + keywords: + - Two + - keyword + +# Booklet + + Code + bibparsed + Output + - type: pamphlet + title: Java Booklet + authors: + - family-names: Mustermann + given-names: Max + medium: Internet + location: + name: Stuttgart + month: '2' + year: '2016' + notes: Example modified from Jabref + +# Conference + + Code + bibparsed + Output + - type: conference-paper + title: On Notions of Information Transfer in VLSI Circuits + authors: + - family-names: Oaho + given-names: Alfred V. + - family-names: Ullman + given-names: Jeffrey D. + - family-names: Yannakakis + given-names: Mihalis + collection-title: Proc. Fifteenth Annual ACM STOC + collection-type: conference + year: '1983' + editors: + - family-names: Oz + given-names: Wizard V. + - family-names: Yannakakis + given-names: Mihalis + volume: '41' + issue: '17' + institution: + name: ACM + publisher: + name: Academic Press + notes: Example modified for testing purposes + start: '133' + end: '139' + conference: + name: Proc. Fifteenth Annual ACM STOC + address: Boston + +# InBook + + Code + bibparsed + Output + - type: book + title: A Framework for Freeness Analysis + authors: + - family-names: King + given-names: A. + editors: + - family-names: Tick + given-names: E + - family-names: Succi + given-names: G + section: 7, 14 + publisher: + name: Kluwer Academic Publishers + address: Dordrecht + year: '1994' + volume: '27' + issue: '2' + collection-title: Implementations of Logic Programming Systems + collection-type: book + edition: Second + month: '1' + notes: Example modified for testing purposes + start: '137' + end: '149' + +# InCollection + + Code + bibparsed + Output + - type: generic + title: Knowledge-Based Methods for WSD + authors: + - family-names: Mihalcea + given-names: Rada + collection-title: 'Word Sense Disambiguation: Algorithms and Applications' + collection-type: collection + publisher: + name: Springer + address: 107--132 + year: '2006' + editors: + - family-names: Agirre + given-names: Eneko + - family-names: Edmonds + given-names: Philip + volume: '23' + issue: '3' + section: '1,2,3' + edition: Third + month: '8' + notes: A note + start: '24' + end: '57' + +# InProceedings + + Code + bibparsed + Output + - type: conference-paper + title: On Notions of Information Transfer in VLSI Circuits + authors: + - family-names: Oaho + given-names: Alfred V. + - family-names: Ullman + given-names: Jeffrey D. + - family-names: Yannakakis + given-names: Mihalis + collection-title: Proc. Fifteenth Annual ACM STOC + collection-type: proceedings + year: '1983' + editors: + - family-names: Oz + given-names: Wizard V. + - family-names: Yannakakis + given-names: Mihalis + volume: '41' + issue: '17' + institution: + name: ACM + publisher: + name: Academic Press + notes: Example modified for testing purposes + start: '133' + end: '139' + conference: + name: Proc. Fifteenth Annual ACM STOC + address: Boston + +# Manual + + Code + bibparsed + Output + - type: manual + title: A Language and Environment for Statistical Computing + authors: + - name: R Core Team + institution: + name: R Foundation for Statistical Computing + address: Vienna, Austria + edition: Fourth + month: '8' + year: '2021' + notes: Example modified for testing purposes + +# MastersThesis + + Code + bibparsed + Output + - type: thesis + title: An examination of keystroke dynamics for continuous user authentication + authors: + - family-names: Alsolami + given-names: Eesa + institution: + name: Queensland University of Technology + address: Queensland, NZ + year: '2012' + month: '8' + notes: Example modified for testing purposes + thesis-type: Master's Thesis + +# Misc + + Code + bibparsed + Output + - type: generic + title: A Language and Environment for Statistical Computing + authors: + - name: R Core Team + medium: CD-ROM + month: '1' + year: '2021' + notes: A note + +# PhdThesis + + Code + bibparsed + Output + - type: thesis + title: An examination of keystroke dynamics for continuous user authentication + authors: + - family-names: Alsolami + given-names: Eesa + institution: + name: Queensland University of Technology + address: Queensland, NZ + year: '2012' + month: '8' + notes: Example modified for testing purposes + thesis-type: PhD Thesis + +# Proceedings + + Code + bibparsed + Output + - type: proceedings + title: Proc. Fifteenth Annual STOC + authors: + - name: anonymous + year: '1983' + editors: + - family-names: Oz + given-names: Wizard V. + - family-names: Yannakakis + given-names: Mihalis + volume: '1' + issue: '17' + collection-title: All ACM Conferences + collection-type: proceedings + month: '8' + institution: + name: The OX Association for Computing Machinery + publisher: + name: Academic Press + notes: Example modified for testing purposes + conference: + name: All ACM Conferences + address: Boston, US + +# TechReport + + Code + bibparsed + Output + - type: report + title: Naive tools for studying compilation histories + authors: + - family-names: Jadud + given-names: Matthew C. + - family-names: Fincher + given-names: Sally A. + institution: + name: University of Kent Canterbury + address: Computing Laboratory, University of Kent, Canterbury, Kent, CT2 7NF + year: '2003' + issue: 3-03 + month: '3' + notes: Example modified for testing purposes + +# Unpublished + + Code + bibparsed + Output + - type: unpublished + title: Demonstratives + authors: + - family-names: Kaplan + given-names: D. + notes: Unpublished manuscript, UCLA + year: '1977' + month: '8' + +# InBook with booktitle + + Code + bibparsed + Output + - type: generic + title: Bibliographies and citations + authors: + - family-names: Xie + given-names: Yihui + - family-names: Dervieux + given-names: Christophe + - family-names: Riederer + given-names: Emily + year: '2020' + collection-title: R Markdown Cookbook + collection-type: collection + publisher: + name: Chapman and Hall/CRC + address: Boca Raton, Florida + isbn: '9780367563837' + url: https://bookdown.org/yihui/rmarkdown-cookbook + section: '4.5' + +# Test entry without author + + Code + bibparsed + Output + - type: proceedings + title: Proceedings of the 6th European Conference on Computer Systems + authors: + - name: anonymous + editors: + - family-names: Berbers + given-names: Yolande + - family-names: Zwaenepoel + given-names: Willy + collection-title: Proceedings of the 6th European Conference on Computer Systems + collection-type: proceedings + publisher: + name: ACM + month: '4' + year: '2006' + isbn: 1-59593-322-02 + conference: + name: Proceedings of the 6th European Conference on Computer Systems + +# Test entry without author but has a key + + Code + bibparsed + Output + - type: generic + title: Proceedings of the 6th European Conference on Computer Systems + authors: + - name: anonymous + collection-title: Proceedings of the 6th European Conference on Computer Systems + collection-type: misc + publisher: + name: ACM + month: '4' + year: '2006' + isbn: 1-59593-322-02 + +# Test entry without author and key + + Code + bibparsed + Output + - type: generic + title: Proceedings of the 6th European Conference on Computer Systems + authors: + - name: anonymous + collection-title: Proceedings of the 6th European Conference on Computer Systems + collection-type: misc + publisher: + name: ACM + month: '4' + year: '2006' + isbn: 1-59593-322-02 + +# Skip misc without title + + Code + cffobj + Output + cff-version: 1.2.0 + message: If you use this software, please cite it using these metadata. + title: My Research Software + authors: + - family-names: Doe + given-names: John + +# Skip misc without title, not skipping the good one + + Code + cffobj + Output + cff-version: 1.2.0 + message: If you use this software, please cite it using these metadata. + title: My Research Software + authors: + - family-names: Doe + given-names: John + references: + - type: generic + title: 'rromeo: An R Client for SHERPA/RoMEO API' + authors: + - family-names: Grenié + given-names: Matthias + - family-names: Gruson + given-names: Hugo + year: '2019' + url: https://CRAN.R-project.org/package=rromeo + +# Check extended BibLatex Fields + + Code + bibparsed + Output + - type: article + title: Computation of methodology hyphen independent ionic solvation free energies + from molecular simulations + authors: + - family-names: Kastenholz + given-names: M. A. + - family-names: Hünenbergerb + given-names: Philippe H. + journal: J. Chem. Phys. + year: '2006' + notes: Example modified for testing purposes + date-published: '2006-03-15' + filename: a_file.pdf + issue-title: Semantic 3D Media and Content + translators: + - family-names: Wicksteed + given-names: P. H. + - family-names: Cornford + given-names: F. M. + date-accessed: '2006-10-01' + pages: '528' + abstract: The computation of ionic solvation free energies from atomistic simulations + is a surprisingly difficult problem that has found no satisfactory solution for + more than 15 years. + doi: 10.1063/1.2172593 + isbn: 0-816-52066-6 + issn: 0097-8493 + url: http://www.ctan.org + start: '55' + end: '65' + month: '3' + diff --git a/tests/testthat/_snaps/bibtex2cff.md b/tests/testthat/_snaps/bibtex2cff.md deleted file mode 100644 index f98d5109..00000000 --- a/tests/testthat/_snaps/bibtex2cff.md +++ /dev/null @@ -1,483 +0,0 @@ -# Article - - Code - bibparsed - Output - type: article - title: Literate Programming - authors: - - name: R Core Team - journal: The Computer Journal - year: '1984' - volume: '27' - issue: '2' - month: '1' - notes: Example modified for testing purposes - start: '97' - end: '111' - -# Book - - Code - bibparsed - Output - type: book - title: The LaTeX Companion - authors: - - family-names: Mittelbach - given-names: Frank - - family-names: Gossens - given-names: Michel - - family-names: Braams - given-names: Johannes - - family-names: Carlisle - given-names: David - - family-names: Rowley - given-names: Chris - editors: - - name: Barnes and Noble - publisher: - name: Addison-Wesley Professional - address: Santa Monica - year: '2004' - volume: '3' - issue: '7' - collection-title: The LateX Books - collection-type: book - edition: Fourth - month: '8' - notes: Example modified for testing purposes - keywords: - - Two - - keyword - -# Booklet - - Code - bibparsed - Output - type: pamphlet - title: Java Booklet - authors: - - family-names: Mustermann - given-names: Max - medium: Internet - location: - name: Stuttgart - month: '2' - year: '2016' - notes: Example modified from Jabref - -# Conference - - Code - bibparsed - Output - type: conference-paper - title: On Notions of Information Transfer in VLSI Circuits - authors: - - family-names: Oaho - given-names: Alfred V. - - family-names: Ullman - given-names: Jeffrey D. - - family-names: Yannakakis - given-names: Mihalis - collection-title: Proc. Fifteenth Annual ACM STOC - collection-type: conference - year: '1983' - editors: - - family-names: Oz - given-names: Wizard V. - - family-names: Yannakakis - given-names: Mihalis - volume: '41' - issue: '17' - institution: - name: ACM - publisher: - name: Academic Press - notes: Example modified for testing purposes - start: '133' - end: '139' - conference: - name: Proc. Fifteenth Annual ACM STOC - address: Boston - -# InBook - - Code - bibparsed - Output - type: book - title: A Framework for Freeness Analysis - authors: - - family-names: King - given-names: A. - editors: - - family-names: Tick - given-names: E - - family-names: Succi - given-names: G - section: 7, 14 - publisher: - name: Kluwer Academic Publishers - address: Dordrecht - year: '1994' - volume: '27' - issue: '2' - collection-title: Implementations of Logic Programming Systems - collection-type: book - edition: Second - month: '1' - notes: Example modified for testing purposes - start: '137' - end: '149' - -# InCollection - - Code - bibparsed - Output - type: generic - title: Knowledge-Based Methods for WSD - authors: - - family-names: Mihalcea - given-names: Rada - collection-title: 'Word Sense Disambiguation: Algorithms and Applications' - collection-type: collection - publisher: - name: Springer - address: 107--132 - year: '2006' - editors: - - family-names: Agirre - given-names: Eneko - - family-names: Edmonds - given-names: Philip - volume: '23' - issue: '3' - section: '1,2,3' - edition: Third - month: '8' - notes: A note - start: '24' - end: '57' - -# InProceedings - - Code - bibparsed - Output - type: conference-paper - title: On Notions of Information Transfer in VLSI Circuits - authors: - - family-names: Oaho - given-names: Alfred V. - - family-names: Ullman - given-names: Jeffrey D. - - family-names: Yannakakis - given-names: Mihalis - collection-title: Proc. Fifteenth Annual ACM STOC - collection-type: proceedings - year: '1983' - editors: - - family-names: Oz - given-names: Wizard V. - - family-names: Yannakakis - given-names: Mihalis - volume: '41' - issue: '17' - institution: - name: ACM - publisher: - name: Academic Press - notes: Example modified for testing purposes - start: '133' - end: '139' - conference: - name: Proc. Fifteenth Annual ACM STOC - address: Boston - -# Manual - - Code - bibparsed - Output - type: manual - title: A Language and Environment for Statistical Computing - authors: - - name: R Core Team - institution: - name: R Foundation for Statistical Computing - address: Vienna, Austria - edition: Fourth - month: '8' - year: '2021' - notes: Example modified for testing purposes - -# MastersThesis - - Code - bibparsed - Output - type: thesis - title: An examination of keystroke dynamics for continuous user authentication - authors: - - family-names: Alsolami - given-names: Eesa - institution: - name: Queensland University of Technology - address: Queensland, NZ - year: '2012' - month: '8' - notes: Example modified for testing purposes - thesis-type: Master's Thesis - -# Misc - - Code - bibparsed - Output - type: generic - title: A Language and Environment for Statistical Computing - authors: - - name: R Core Team - medium: CD-ROM - month: '1' - year: '2021' - notes: A note - -# PhdThesis - - Code - bibparsed - Output - type: thesis - title: An examination of keystroke dynamics for continuous user authentication - authors: - - family-names: Alsolami - given-names: Eesa - institution: - name: Queensland University of Technology - address: Queensland, NZ - year: '2012' - month: '8' - notes: Example modified for testing purposes - thesis-type: PhD Thesis - -# Proceedings - - Code - bibparsed - Output - type: proceedings - title: Proc. Fifteenth Annual STOC - authors: - - name: anonymous - year: '1983' - editors: - - family-names: Oz - given-names: Wizard V. - - family-names: Yannakakis - given-names: Mihalis - volume: '1' - issue: '17' - collection-title: All ACM Conferences - collection-type: proceedings - month: '8' - institution: - name: The OX Association for Computing Machinery - publisher: - name: Academic Press - notes: Example modified for testing purposes - conference: - name: All ACM Conferences - address: Boston, US - -# TechReport - - Code - bibparsed - Output - type: report - title: Naive tools for studying compilation histories - authors: - - family-names: Jadud - given-names: Matthew C. - - family-names: Fincher - given-names: Sally A. - institution: - name: University of Kent Canterbury - address: Computing Laboratory, University of Kent, Canterbury, Kent, CT2 7NF - year: '2003' - issue: 3-03 - month: '3' - notes: Example modified for testing purposes - -# Unpublished - - Code - bibparsed - Output - type: unpublished - title: Demonstratives - authors: - - family-names: Kaplan - given-names: D. - notes: Unpublished manuscript, UCLA - year: '1977' - month: '8' - -# InBook with booktitle - - Code - bibparsed - Output - type: generic - title: Bibliographies and citations - authors: - - family-names: Xie - given-names: Yihui - - family-names: Dervieux - given-names: Christophe - - family-names: Riederer - given-names: Emily - year: '2020' - collection-title: R Markdown Cookbook - collection-type: collection - publisher: - name: Chapman and Hall/CRC - address: Boca Raton, Florida - isbn: '9780367563837' - url: https://bookdown.org/yihui/rmarkdown-cookbook - section: '4.5' - -# Test entry without author - - Code - bibparsed - Output - type: proceedings - title: Proceedings of the 6th European Conference on Computer Systems - authors: - - name: anonymous - editors: - - family-names: Berbers - given-names: Yolande - - family-names: Zwaenepoel - given-names: Willy - collection-title: Proceedings of the 6th European Conference on Computer Systems - collection-type: proceedings - publisher: - name: ACM - month: '4' - year: '2006' - isbn: 1-59593-322-02 - conference: - name: Proceedings of the 6th European Conference on Computer Systems - -# Test entry without author but has a key - - Code - bibparsed - Output - type: generic - title: Proceedings of the 6th European Conference on Computer Systems - authors: - - name: anonymous - collection-title: Proceedings of the 6th European Conference on Computer Systems - collection-type: misc - publisher: - name: ACM - month: '4' - year: '2006' - isbn: 1-59593-322-02 - -# Test entry without author and key - - Code - bibparsed - Output - type: generic - title: Proceedings of the 6th European Conference on Computer Systems - authors: - - name: anonymous - collection-title: Proceedings of the 6th European Conference on Computer Systems - collection-type: misc - publisher: - name: ACM - month: '4' - year: '2006' - isbn: 1-59593-322-02 - -# Skip misc without title - - Code - cffobj - Output - cff-version: 1.2.0 - message: If you use this software, please cite it using these metadata. - title: My Research Software - authors: - - family-names: Doe - given-names: John - -# Skip misc without title, not skipping the good one - - Code - cffobj - Output - cff-version: 1.2.0 - message: If you use this software, please cite it using these metadata. - title: My Research Software - authors: - - family-names: Doe - given-names: John - references: - - type: generic - title: 'rromeo: An R Client for SHERPA/RoMEO API' - authors: - - family-names: Grenié - given-names: Matthias - - family-names: Gruson - given-names: Hugo - year: '2019' - url: https://CRAN.R-project.org/package=rromeo - -# Check extended BibLatex Fields - - Code - bibparsed - Output - type: article - title: Computation of methodology hyphen independent ionic solvation free energies - from molecular simulations - authors: - - family-names: Kastenholz - given-names: M. A. - - family-names: Hünenbergerb - given-names: Philippe H. - journal: J. Chem. Phys. - year: '2006' - notes: Example modified for testing purposes - date-published: '2006-03-15' - filename: a_file.pdf - issue-title: Semantic 3D Media and Content - translators: - - family-names: Wicksteed - given-names: P. H. - - family-names: Cornford - given-names: F. M. - date-accessed: '2006-10-01' - pages: '528' - abstract: The computation of ionic solvation free energies from atomistic simulations - is a surprisingly difficult problem that has found no satisfactory solution for - more than 15 years. - doi: 10.1063/1.2172593 - isbn: 0-816-52066-6 - issn: 0097-8493 - url: http://www.ctan.org - start: '55' - end: '65' - month: '3' - diff --git a/tests/testthat/_snaps/cff-methods.md b/tests/testthat/_snaps/cff-methods.md new file mode 100644 index 00000000..15a36553 --- /dev/null +++ b/tests/testthat/_snaps/cff-methods.md @@ -0,0 +1,1057 @@ +# as data frame complete + + Code + names(the_df) + Output + [1] "cff_version" + [2] "message" + [3] "abstract" + [4] "authors.00.family_names" + [5] "authors.00.given_names" + [6] "authors.00.name_particle" + [7] "authors.00.name_suffix" + [8] "authors.00.alias" + [9] "authors.00.affiliation" + [10] "authors.00.address" + [11] "authors.00.city" + [12] "authors.00.region" + [13] "authors.00.post_code" + [14] "authors.00.country" + [15] "authors.00.orcid" + [16] "authors.00.email" + [17] "authors.00.tel" + [18] "authors.00.fax" + [19] "authors.00.website" + [20] "authors.01.name" + [21] "authors.01.address" + [22] "authors.01.city" + [23] "authors.01.region" + [24] "authors.01.post_code" + [25] "authors.01.country" + [26] "authors.01.orcid" + [27] "authors.01.email" + [28] "authors.01.tel" + [29] "authors.01.fax" + [30] "authors.01.website" + [31] "authors.01.date_start" + [32] "authors.01.date_end" + [33] "authors.01.location" + [34] "commit" + [35] "contact.00.family_names" + [36] "contact.00.given_names" + [37] "contact.00.name_particle" + [38] "contact.00.name_suffix" + [39] "contact.00.alias" + [40] "contact.00.affiliation" + [41] "contact.00.address" + [42] "contact.00.city" + [43] "contact.00.region" + [44] "contact.00.post_code" + [45] "contact.00.country" + [46] "contact.00.orcid" + [47] "contact.00.email" + [48] "contact.00.tel" + [49] "contact.00.fax" + [50] "contact.00.website" + [51] "contact.01.name" + [52] "contact.01.address" + [53] "contact.01.city" + [54] "contact.01.region" + [55] "contact.01.post_code" + [56] "contact.01.country" + [57] "contact.01.orcid" + [58] "contact.01.email" + [59] "contact.01.tel" + [60] "contact.01.fax" + [61] "contact.01.website" + [62] "contact.01.date_start" + [63] "contact.01.date_end" + [64] "contact.01.location" + [65] "date_released" + [66] "doi" + [67] "identifiers.00.type" + [68] "identifiers.00.value" + [69] "identifiers.01.type" + [70] "identifiers.01.value" + [71] "identifiers.02.type" + [72] "identifiers.02.value" + [73] "identifiers.03.type" + [74] "identifiers.03.value" + [75] "keywords.00" + [76] "keywords.01" + [77] "keywords.02" + [78] "keywords.03" + [79] "license" + [80] "license_url" + [81] "repository" + [82] "repository_code" + [83] "repository_artifact" + [84] "title" + [85] "type" + [86] "url" + [87] "version" + [88] "preferred_citation.type" + [89] "preferred_citation.title" + [90] "preferred_citation.abbreviation" + [91] "preferred_citation.abstract" + [92] "preferred_citation.collection_doi" + [93] "preferred_citation.collection_title" + [94] "preferred_citation.collection_type" + [95] "preferred_citation.commit" + [96] "preferred_citation.copyright" + [97] "preferred_citation.data_type" + [98] "preferred_citation.database" + [99] "preferred_citation.date_accessed" + [100] "preferred_citation.date_downloaded" + [101] "preferred_citation.date_released" + [102] "preferred_citation.date_published" + [103] "preferred_citation.department" + [104] "preferred_citation.doi" + [105] "preferred_citation.edition" + [106] "preferred_citation.end" + [107] "preferred_citation.entry" + [108] "preferred_citation.filename" + [109] "preferred_citation.format" + [110] "preferred_citation.identifiers.00.type" + [111] "preferred_citation.identifiers.00.value" + [112] "preferred_citation.identifiers.01.type" + [113] "preferred_citation.identifiers.01.value" + [114] "preferred_citation.identifiers.02.type" + [115] "preferred_citation.identifiers.02.value" + [116] "preferred_citation.identifiers.03.type" + [117] "preferred_citation.identifiers.03.value" + [118] "preferred_citation.isbn" + [119] "preferred_citation.issn" + [120] "preferred_citation.issue" + [121] "preferred_citation.issue_date" + [122] "preferred_citation.issue_title" + [123] "preferred_citation.journal" + [124] "preferred_citation.keywords.00" + [125] "preferred_citation.keywords.01" + [126] "preferred_citation.languages.00" + [127] "preferred_citation.languages.01" + [128] "preferred_citation.license" + [129] "preferred_citation.license_url" + [130] "preferred_citation.loc_start" + [131] "preferred_citation.loc_end" + [132] "preferred_citation.medium" + [133] "preferred_citation.month" + [134] "preferred_citation.nihmsid" + [135] "preferred_citation.notes" + [136] "preferred_citation.number" + [137] "preferred_citation.number_volumes" + [138] "preferred_citation.pages" + [139] "preferred_citation.patent-states.00" + [140] "preferred_citation.patent-states.01" + [141] "preferred_citation.patent-states.02" + [142] "preferred_citation.patent-states.03" + [143] "preferred_citation.patent-states.04" + [144] "preferred_citation.pmcid" + [145] "preferred_citation.repository" + [146] "preferred_citation.repository_code" + [147] "preferred_citation.repository_artifact" + [148] "preferred_citation.scope" + [149] "preferred_citation.section" + [150] "preferred_citation.status" + [151] "preferred_citation.start" + [152] "preferred_citation.thesis_type" + [153] "preferred_citation.url" + [154] "preferred_citation.version" + [155] "preferred_citation.volume" + [156] "preferred_citation.volume_title" + [157] "preferred_citation.year" + [158] "preferred_citation.year_original" + [159] "preferred_citation.conference.name" + [160] "preferred_citation.conference.address" + [161] "preferred_citation.conference.city" + [162] "preferred_citation.conference.region" + [163] "preferred_citation.conference.post-code" + [164] "preferred_citation.conference.country" + [165] "preferred_citation.conference.orcid" + [166] "preferred_citation.conference.email" + [167] "preferred_citation.conference.tel" + [168] "preferred_citation.conference.fax" + [169] "preferred_citation.conference.website" + [170] "preferred_citation.conference.date-start" + [171] "preferred_citation.conference.date-end" + [172] "preferred_citation.conference.location" + [173] "preferred_citation.authors.00.family_names" + [174] "preferred_citation.authors.00.given_names" + [175] "preferred_citation.authors.00.name_particle" + [176] "preferred_citation.authors.00.name_suffix" + [177] "preferred_citation.authors.00.alias" + [178] "preferred_citation.authors.00.affiliation" + [179] "preferred_citation.authors.00.address" + [180] "preferred_citation.authors.00.city" + [181] "preferred_citation.authors.00.region" + [182] "preferred_citation.authors.00.post_code" + [183] "preferred_citation.authors.00.country" + [184] "preferred_citation.authors.00.orcid" + [185] "preferred_citation.authors.00.email" + [186] "preferred_citation.authors.00.tel" + [187] "preferred_citation.authors.00.fax" + [188] "preferred_citation.authors.00.website" + [189] "preferred_citation.authors.01.name" + [190] "preferred_citation.authors.01.address" + [191] "preferred_citation.authors.01.city" + [192] "preferred_citation.authors.01.region" + [193] "preferred_citation.authors.01.post_code" + [194] "preferred_citation.authors.01.country" + [195] "preferred_citation.authors.01.orcid" + [196] "preferred_citation.authors.01.email" + [197] "preferred_citation.authors.01.tel" + [198] "preferred_citation.authors.01.fax" + [199] "preferred_citation.authors.01.website" + [200] "preferred_citation.authors.01.date_start" + [201] "preferred_citation.authors.01.date_end" + [202] "preferred_citation.authors.01.location" + [203] "preferred_citation.contact.00.family_names" + [204] "preferred_citation.contact.00.given_names" + [205] "preferred_citation.contact.00.name_particle" + [206] "preferred_citation.contact.00.name_suffix" + [207] "preferred_citation.contact.00.alias" + [208] "preferred_citation.contact.00.affiliation" + [209] "preferred_citation.contact.00.address" + [210] "preferred_citation.contact.00.city" + [211] "preferred_citation.contact.00.region" + [212] "preferred_citation.contact.00.post_code" + [213] "preferred_citation.contact.00.country" + [214] "preferred_citation.contact.00.orcid" + [215] "preferred_citation.contact.00.email" + [216] "preferred_citation.contact.00.tel" + [217] "preferred_citation.contact.00.fax" + [218] "preferred_citation.contact.00.website" + [219] "preferred_citation.contact.01.name" + [220] "preferred_citation.contact.01.address" + [221] "preferred_citation.contact.01.city" + [222] "preferred_citation.contact.01.region" + [223] "preferred_citation.contact.01.post_code" + [224] "preferred_citation.contact.01.country" + [225] "preferred_citation.contact.01.orcid" + [226] "preferred_citation.contact.01.email" + [227] "preferred_citation.contact.01.tel" + [228] "preferred_citation.contact.01.fax" + [229] "preferred_citation.contact.01.website" + [230] "preferred_citation.contact.01.date_start" + [231] "preferred_citation.contact.01.date_end" + [232] "preferred_citation.contact.01.location" + [233] "preferred_citation.database-provider.name" + [234] "preferred_citation.database-provider.address" + [235] "preferred_citation.database-provider.city" + [236] "preferred_citation.database-provider.region" + [237] "preferred_citation.database-provider.post-code" + [238] "preferred_citation.database-provider.country" + [239] "preferred_citation.database-provider.orcid" + [240] "preferred_citation.database-provider.email" + [241] "preferred_citation.database-provider.tel" + [242] "preferred_citation.database-provider.fax" + [243] "preferred_citation.database-provider.website" + [244] "preferred_citation.database-provider.date-start" + [245] "preferred_citation.database-provider.date-end" + [246] "preferred_citation.database-provider.location" + [247] "preferred_citation.editors.00.family_names" + [248] "preferred_citation.editors.00.given_names" + [249] "preferred_citation.editors.00.name_particle" + [250] "preferred_citation.editors.00.name_suffix" + [251] "preferred_citation.editors.00.alias" + [252] "preferred_citation.editors.00.affiliation" + [253] "preferred_citation.editors.00.address" + [254] "preferred_citation.editors.00.city" + [255] "preferred_citation.editors.00.region" + [256] "preferred_citation.editors.00.post_code" + [257] "preferred_citation.editors.00.country" + [258] "preferred_citation.editors.00.orcid" + [259] "preferred_citation.editors.00.email" + [260] "preferred_citation.editors.00.tel" + [261] "preferred_citation.editors.00.fax" + [262] "preferred_citation.editors.00.website" + [263] "preferred_citation.editors.01.name" + [264] "preferred_citation.editors.01.address" + [265] "preferred_citation.editors.01.city" + [266] "preferred_citation.editors.01.region" + [267] "preferred_citation.editors.01.post_code" + [268] "preferred_citation.editors.01.country" + [269] "preferred_citation.editors.01.orcid" + [270] "preferred_citation.editors.01.email" + [271] "preferred_citation.editors.01.tel" + [272] "preferred_citation.editors.01.fax" + [273] "preferred_citation.editors.01.website" + [274] "preferred_citation.editors.01.date_start" + [275] "preferred_citation.editors.01.date_end" + [276] "preferred_citation.editors.01.location" + [277] "preferred_citation.editors-series.00.family_names" + [278] "preferred_citation.editors-series.00.given_names" + [279] "preferred_citation.editors-series.00.name_particle" + [280] "preferred_citation.editors-series.00.name_suffix" + [281] "preferred_citation.editors-series.00.alias" + [282] "preferred_citation.editors-series.00.affiliation" + [283] "preferred_citation.editors-series.00.address" + [284] "preferred_citation.editors-series.00.city" + [285] "preferred_citation.editors-series.00.region" + [286] "preferred_citation.editors-series.00.post_code" + [287] "preferred_citation.editors-series.00.country" + [288] "preferred_citation.editors-series.00.orcid" + [289] "preferred_citation.editors-series.00.email" + [290] "preferred_citation.editors-series.00.tel" + [291] "preferred_citation.editors-series.00.fax" + [292] "preferred_citation.editors-series.00.website" + [293] "preferred_citation.editors-series.01.name" + [294] "preferred_citation.editors-series.01.address" + [295] "preferred_citation.editors-series.01.city" + [296] "preferred_citation.editors-series.01.region" + [297] "preferred_citation.editors-series.01.post_code" + [298] "preferred_citation.editors-series.01.country" + [299] "preferred_citation.editors-series.01.orcid" + [300] "preferred_citation.editors-series.01.email" + [301] "preferred_citation.editors-series.01.tel" + [302] "preferred_citation.editors-series.01.fax" + [303] "preferred_citation.editors-series.01.website" + [304] "preferred_citation.editors-series.01.date_start" + [305] "preferred_citation.editors-series.01.date_end" + [306] "preferred_citation.editors-series.01.location" + [307] "preferred_citation.institution.name" + [308] "preferred_citation.institution.address" + [309] "preferred_citation.institution.city" + [310] "preferred_citation.institution.region" + [311] "preferred_citation.institution.post-code" + [312] "preferred_citation.institution.country" + [313] "preferred_citation.institution.orcid" + [314] "preferred_citation.institution.email" + [315] "preferred_citation.institution.tel" + [316] "preferred_citation.institution.fax" + [317] "preferred_citation.institution.website" + [318] "preferred_citation.institution.date-start" + [319] "preferred_citation.institution.date-end" + [320] "preferred_citation.institution.location" + [321] "preferred_citation.location.name" + [322] "preferred_citation.location.address" + [323] "preferred_citation.location.city" + [324] "preferred_citation.location.region" + [325] "preferred_citation.location.post-code" + [326] "preferred_citation.location.country" + [327] "preferred_citation.location.orcid" + [328] "preferred_citation.location.email" + [329] "preferred_citation.location.tel" + [330] "preferred_citation.location.fax" + [331] "preferred_citation.location.website" + [332] "preferred_citation.location.date-start" + [333] "preferred_citation.location.date-end" + [334] "preferred_citation.location.location" + [335] "preferred_citation.publisher.name" + [336] "preferred_citation.publisher.address" + [337] "preferred_citation.publisher.city" + [338] "preferred_citation.publisher.region" + [339] "preferred_citation.publisher.post-code" + [340] "preferred_citation.publisher.country" + [341] "preferred_citation.publisher.orcid" + [342] "preferred_citation.publisher.email" + [343] "preferred_citation.publisher.tel" + [344] "preferred_citation.publisher.fax" + [345] "preferred_citation.publisher.website" + [346] "preferred_citation.publisher.date-start" + [347] "preferred_citation.publisher.date-end" + [348] "preferred_citation.publisher.location" + [349] "preferred_citation.recipients.00.family_names" + [350] "preferred_citation.recipients.00.given_names" + [351] "preferred_citation.recipients.00.name_particle" + [352] "preferred_citation.recipients.00.name_suffix" + [353] "preferred_citation.recipients.00.alias" + [354] "preferred_citation.recipients.00.affiliation" + [355] "preferred_citation.recipients.00.address" + [356] "preferred_citation.recipients.00.city" + [357] "preferred_citation.recipients.00.region" + [358] "preferred_citation.recipients.00.post_code" + [359] "preferred_citation.recipients.00.country" + [360] "preferred_citation.recipients.00.orcid" + [361] "preferred_citation.recipients.00.email" + [362] "preferred_citation.recipients.00.tel" + [363] "preferred_citation.recipients.00.fax" + [364] "preferred_citation.recipients.00.website" + [365] "preferred_citation.recipients.01.name" + [366] "preferred_citation.recipients.01.address" + [367] "preferred_citation.recipients.01.city" + [368] "preferred_citation.recipients.01.region" + [369] "preferred_citation.recipients.01.post_code" + [370] "preferred_citation.recipients.01.country" + [371] "preferred_citation.recipients.01.orcid" + [372] "preferred_citation.recipients.01.email" + [373] "preferred_citation.recipients.01.tel" + [374] "preferred_citation.recipients.01.fax" + [375] "preferred_citation.recipients.01.website" + [376] "preferred_citation.recipients.01.date_start" + [377] "preferred_citation.recipients.01.date_end" + [378] "preferred_citation.recipients.01.location" + [379] "preferred_citation.senders.00.family_names" + [380] "preferred_citation.senders.00.given_names" + [381] "preferred_citation.senders.00.name_particle" + [382] "preferred_citation.senders.00.name_suffix" + [383] "preferred_citation.senders.00.alias" + [384] "preferred_citation.senders.00.affiliation" + [385] "preferred_citation.senders.00.address" + [386] "preferred_citation.senders.00.city" + [387] "preferred_citation.senders.00.region" + [388] "preferred_citation.senders.00.post_code" + [389] "preferred_citation.senders.00.country" + [390] "preferred_citation.senders.00.orcid" + [391] "preferred_citation.senders.00.email" + [392] "preferred_citation.senders.00.tel" + [393] "preferred_citation.senders.00.fax" + [394] "preferred_citation.senders.00.website" + [395] "preferred_citation.senders.01.name" + [396] "preferred_citation.senders.01.address" + [397] "preferred_citation.senders.01.city" + [398] "preferred_citation.senders.01.region" + [399] "preferred_citation.senders.01.post_code" + [400] "preferred_citation.senders.01.country" + [401] "preferred_citation.senders.01.orcid" + [402] "preferred_citation.senders.01.email" + [403] "preferred_citation.senders.01.tel" + [404] "preferred_citation.senders.01.fax" + [405] "preferred_citation.senders.01.website" + [406] "preferred_citation.senders.01.date_start" + [407] "preferred_citation.senders.01.date_end" + [408] "preferred_citation.senders.01.location" + [409] "preferred_citation.translators.00.family_names" + [410] "preferred_citation.translators.00.given_names" + [411] "preferred_citation.translators.00.name_particle" + [412] "preferred_citation.translators.00.name_suffix" + [413] "preferred_citation.translators.00.alias" + [414] "preferred_citation.translators.00.affiliation" + [415] "preferred_citation.translators.00.address" + [416] "preferred_citation.translators.00.city" + [417] "preferred_citation.translators.00.region" + [418] "preferred_citation.translators.00.post_code" + [419] "preferred_citation.translators.00.country" + [420] "preferred_citation.translators.00.orcid" + [421] "preferred_citation.translators.00.email" + [422] "preferred_citation.translators.00.tel" + [423] "preferred_citation.translators.00.fax" + [424] "preferred_citation.translators.00.website" + [425] "preferred_citation.translators.01.name" + [426] "preferred_citation.translators.01.address" + [427] "preferred_citation.translators.01.city" + [428] "preferred_citation.translators.01.region" + [429] "preferred_citation.translators.01.post_code" + [430] "preferred_citation.translators.01.country" + [431] "preferred_citation.translators.01.orcid" + [432] "preferred_citation.translators.01.email" + [433] "preferred_citation.translators.01.tel" + [434] "preferred_citation.translators.01.fax" + [435] "preferred_citation.translators.01.website" + [436] "preferred_citation.translators.01.date_start" + [437] "preferred_citation.translators.01.date_end" + [438] "preferred_citation.translators.01.location" + [439] "references.00.type" + [440] "references.00.title" + [441] "references.00.abbreviation" + [442] "references.00.abstract" + [443] "references.00.collection_doi" + [444] "references.00.collection_title" + [445] "references.00.collection_type" + [446] "references.00.commit" + [447] "references.00.copyright" + [448] "references.00.data_type" + [449] "references.00.database" + [450] "references.00.date_accessed" + [451] "references.00.date_downloaded" + [452] "references.00.date_released" + [453] "references.00.date_published" + [454] "references.00.department" + [455] "references.00.doi" + [456] "references.00.edition" + [457] "references.00.end" + [458] "references.00.entry" + [459] "references.00.filename" + [460] "references.00.format" + [461] "references.00.identifiers.00.type" + [462] "references.00.identifiers.00.value" + [463] "references.00.identifiers.01.type" + [464] "references.00.identifiers.01.value" + [465] "references.00.identifiers.02.type" + [466] "references.00.identifiers.02.value" + [467] "references.00.identifiers.03.type" + [468] "references.00.identifiers.03.value" + [469] "references.00.isbn" + [470] "references.00.issn" + [471] "references.00.issue" + [472] "references.00.issue_date" + [473] "references.00.issue_title" + [474] "references.00.journal" + [475] "references.00.keywords.00" + [476] "references.00.keywords.01" + [477] "references.00.languages.00" + [478] "references.00.languages.01" + [479] "references.00.license" + [480] "references.00.license_url" + [481] "references.00.loc_start" + [482] "references.00.loc_end" + [483] "references.00.medium" + [484] "references.00.month" + [485] "references.00.nihmsid" + [486] "references.00.notes" + [487] "references.00.number" + [488] "references.00.number_volumes" + [489] "references.00.pages" + [490] "references.00.patent-states.00" + [491] "references.00.patent-states.01" + [492] "references.00.patent-states.02" + [493] "references.00.patent-states.03" + [494] "references.00.patent-states.04" + [495] "references.00.pmcid" + [496] "references.00.repository" + [497] "references.00.repository_code" + [498] "references.00.repository_artifact" + [499] "references.00.scope" + [500] "references.00.section" + [501] "references.00.status" + [502] "references.00.start" + [503] "references.00.thesis_type" + [504] "references.00.url" + [505] "references.00.version" + [506] "references.00.volume" + [507] "references.00.volume_title" + [508] "references.00.year" + [509] "references.00.year_original" + [510] "references.00.conference.name" + [511] "references.00.conference.address" + [512] "references.00.conference.city" + [513] "references.00.conference.region" + [514] "references.00.conference.post-code" + [515] "references.00.conference.country" + [516] "references.00.conference.orcid" + [517] "references.00.conference.email" + [518] "references.00.conference.tel" + [519] "references.00.conference.fax" + [520] "references.00.conference.website" + [521] "references.00.conference.date-start" + [522] "references.00.conference.date-end" + [523] "references.00.conference.location" + [524] "references.00.authors.00.family_names" + [525] "references.00.authors.00.given_names" + [526] "references.00.authors.00.name_particle" + [527] "references.00.authors.00.name_suffix" + [528] "references.00.authors.00.alias" + [529] "references.00.authors.00.affiliation" + [530] "references.00.authors.00.address" + [531] "references.00.authors.00.city" + [532] "references.00.authors.00.region" + [533] "references.00.authors.00.post_code" + [534] "references.00.authors.00.country" + [535] "references.00.authors.00.orcid" + [536] "references.00.authors.00.email" + [537] "references.00.authors.00.tel" + [538] "references.00.authors.00.fax" + [539] "references.00.authors.00.website" + [540] "references.00.authors.01.name" + [541] "references.00.authors.01.address" + [542] "references.00.authors.01.city" + [543] "references.00.authors.01.region" + [544] "references.00.authors.01.post_code" + [545] "references.00.authors.01.country" + [546] "references.00.authors.01.orcid" + [547] "references.00.authors.01.email" + [548] "references.00.authors.01.tel" + [549] "references.00.authors.01.fax" + [550] "references.00.authors.01.website" + [551] "references.00.authors.01.date_start" + [552] "references.00.authors.01.date_end" + [553] "references.00.authors.01.location" + [554] "references.00.contact.00.family_names" + [555] "references.00.contact.00.given_names" + [556] "references.00.contact.00.name_particle" + [557] "references.00.contact.00.name_suffix" + [558] "references.00.contact.00.alias" + [559] "references.00.contact.00.affiliation" + [560] "references.00.contact.00.address" + [561] "references.00.contact.00.city" + [562] "references.00.contact.00.region" + [563] "references.00.contact.00.post_code" + [564] "references.00.contact.00.country" + [565] "references.00.contact.00.orcid" + [566] "references.00.contact.00.email" + [567] "references.00.contact.00.tel" + [568] "references.00.contact.00.fax" + [569] "references.00.contact.00.website" + [570] "references.00.contact.01.name" + [571] "references.00.contact.01.address" + [572] "references.00.contact.01.city" + [573] "references.00.contact.01.region" + [574] "references.00.contact.01.post_code" + [575] "references.00.contact.01.country" + [576] "references.00.contact.01.orcid" + [577] "references.00.contact.01.email" + [578] "references.00.contact.01.tel" + [579] "references.00.contact.01.fax" + [580] "references.00.contact.01.website" + [581] "references.00.contact.01.date_start" + [582] "references.00.contact.01.date_end" + [583] "references.00.contact.01.location" + [584] "references.00.database-provider.name" + [585] "references.00.database-provider.address" + [586] "references.00.database-provider.city" + [587] "references.00.database-provider.region" + [588] "references.00.database-provider.post-code" + [589] "references.00.database-provider.country" + [590] "references.00.database-provider.orcid" + [591] "references.00.database-provider.email" + [592] "references.00.database-provider.tel" + [593] "references.00.database-provider.fax" + [594] "references.00.database-provider.website" + [595] "references.00.database-provider.date-start" + [596] "references.00.database-provider.date-end" + [597] "references.00.database-provider.location" + [598] "references.00.editors.00.family_names" + [599] "references.00.editors.00.given_names" + [600] "references.00.editors.00.name_particle" + [601] "references.00.editors.00.name_suffix" + [602] "references.00.editors.00.alias" + [603] "references.00.editors.00.affiliation" + [604] "references.00.editors.00.address" + [605] "references.00.editors.00.city" + [606] "references.00.editors.00.region" + [607] "references.00.editors.00.post_code" + [608] "references.00.editors.00.country" + [609] "references.00.editors.00.orcid" + [610] "references.00.editors.00.email" + [611] "references.00.editors.00.tel" + [612] "references.00.editors.00.fax" + [613] "references.00.editors.00.website" + [614] "references.00.editors.01.name" + [615] "references.00.editors.01.address" + [616] "references.00.editors.01.city" + [617] "references.00.editors.01.region" + [618] "references.00.editors.01.post_code" + [619] "references.00.editors.01.country" + [620] "references.00.editors.01.orcid" + [621] "references.00.editors.01.email" + [622] "references.00.editors.01.tel" + [623] "references.00.editors.01.fax" + [624] "references.00.editors.01.website" + [625] "references.00.editors.01.date_start" + [626] "references.00.editors.01.date_end" + [627] "references.00.editors.01.location" + [628] "references.00.editors-series.00.family_names" + [629] "references.00.editors-series.00.given_names" + [630] "references.00.editors-series.00.name_particle" + [631] "references.00.editors-series.00.name_suffix" + [632] "references.00.editors-series.00.alias" + [633] "references.00.editors-series.00.affiliation" + [634] "references.00.editors-series.00.address" + [635] "references.00.editors-series.00.city" + [636] "references.00.editors-series.00.region" + [637] "references.00.editors-series.00.post_code" + [638] "references.00.editors-series.00.country" + [639] "references.00.editors-series.00.orcid" + [640] "references.00.editors-series.00.email" + [641] "references.00.editors-series.00.tel" + [642] "references.00.editors-series.00.fax" + [643] "references.00.editors-series.00.website" + [644] "references.00.editors-series.01.name" + [645] "references.00.editors-series.01.address" + [646] "references.00.editors-series.01.city" + [647] "references.00.editors-series.01.region" + [648] "references.00.editors-series.01.post_code" + [649] "references.00.editors-series.01.country" + [650] "references.00.editors-series.01.orcid" + [651] "references.00.editors-series.01.email" + [652] "references.00.editors-series.01.tel" + [653] "references.00.editors-series.01.fax" + [654] "references.00.editors-series.01.website" + [655] "references.00.editors-series.01.date_start" + [656] "references.00.editors-series.01.date_end" + [657] "references.00.editors-series.01.location" + [658] "references.00.institution.name" + [659] "references.00.institution.address" + [660] "references.00.institution.city" + [661] "references.00.institution.region" + [662] "references.00.institution.post-code" + [663] "references.00.institution.country" + [664] "references.00.institution.orcid" + [665] "references.00.institution.email" + [666] "references.00.institution.tel" + [667] "references.00.institution.fax" + [668] "references.00.institution.website" + [669] "references.00.institution.date-start" + [670] "references.00.institution.date-end" + [671] "references.00.institution.location" + [672] "references.00.location.name" + [673] "references.00.location.address" + [674] "references.00.location.city" + [675] "references.00.location.region" + [676] "references.00.location.post-code" + [677] "references.00.location.country" + [678] "references.00.location.orcid" + [679] "references.00.location.email" + [680] "references.00.location.tel" + [681] "references.00.location.fax" + [682] "references.00.location.website" + [683] "references.00.location.date-start" + [684] "references.00.location.date-end" + [685] "references.00.location.location" + [686] "references.00.publisher.name" + [687] "references.00.publisher.address" + [688] "references.00.publisher.city" + [689] "references.00.publisher.region" + [690] "references.00.publisher.post-code" + [691] "references.00.publisher.country" + [692] "references.00.publisher.orcid" + [693] "references.00.publisher.email" + [694] "references.00.publisher.tel" + [695] "references.00.publisher.fax" + [696] "references.00.publisher.website" + [697] "references.00.publisher.date-start" + [698] "references.00.publisher.date-end" + [699] "references.00.publisher.location" + [700] "references.00.recipients.00.family_names" + [701] "references.00.recipients.00.given_names" + [702] "references.00.recipients.00.name_particle" + [703] "references.00.recipients.00.name_suffix" + [704] "references.00.recipients.00.alias" + [705] "references.00.recipients.00.affiliation" + [706] "references.00.recipients.00.address" + [707] "references.00.recipients.00.city" + [708] "references.00.recipients.00.region" + [709] "references.00.recipients.00.post_code" + [710] "references.00.recipients.00.country" + [711] "references.00.recipients.00.orcid" + [712] "references.00.recipients.00.email" + [713] "references.00.recipients.00.tel" + [714] "references.00.recipients.00.fax" + [715] "references.00.recipients.00.website" + [716] "references.00.recipients.01.name" + [717] "references.00.recipients.01.address" + [718] "references.00.recipients.01.city" + [719] "references.00.recipients.01.region" + [720] "references.00.recipients.01.post_code" + [721] "references.00.recipients.01.country" + [722] "references.00.recipients.01.orcid" + [723] "references.00.recipients.01.email" + [724] "references.00.recipients.01.tel" + [725] "references.00.recipients.01.fax" + [726] "references.00.recipients.01.website" + [727] "references.00.recipients.01.date_start" + [728] "references.00.recipients.01.date_end" + [729] "references.00.recipients.01.location" + [730] "references.00.senders.00.family_names" + [731] "references.00.senders.00.given_names" + [732] "references.00.senders.00.name_particle" + [733] "references.00.senders.00.name_suffix" + [734] "references.00.senders.00.alias" + [735] "references.00.senders.00.affiliation" + [736] "references.00.senders.00.address" + [737] "references.00.senders.00.city" + [738] "references.00.senders.00.region" + [739] "references.00.senders.00.post_code" + [740] "references.00.senders.00.country" + [741] "references.00.senders.00.orcid" + [742] "references.00.senders.00.email" + [743] "references.00.senders.00.tel" + [744] "references.00.senders.00.fax" + [745] "references.00.senders.00.website" + [746] "references.00.senders.01.name" + [747] "references.00.senders.01.address" + [748] "references.00.senders.01.city" + [749] "references.00.senders.01.region" + [750] "references.00.senders.01.post_code" + [751] "references.00.senders.01.country" + [752] "references.00.senders.01.orcid" + [753] "references.00.senders.01.email" + [754] "references.00.senders.01.tel" + [755] "references.00.senders.01.fax" + [756] "references.00.senders.01.website" + [757] "references.00.senders.01.date_start" + [758] "references.00.senders.01.date_end" + [759] "references.00.senders.01.location" + [760] "references.00.translators.00.family_names" + [761] "references.00.translators.00.given_names" + [762] "references.00.translators.00.name_particle" + [763] "references.00.translators.00.name_suffix" + [764] "references.00.translators.00.alias" + [765] "references.00.translators.00.affiliation" + [766] "references.00.translators.00.address" + [767] "references.00.translators.00.city" + [768] "references.00.translators.00.region" + [769] "references.00.translators.00.post_code" + [770] "references.00.translators.00.country" + [771] "references.00.translators.00.orcid" + [772] "references.00.translators.00.email" + [773] "references.00.translators.00.tel" + [774] "references.00.translators.00.fax" + [775] "references.00.translators.00.website" + [776] "references.00.translators.01.name" + [777] "references.00.translators.01.address" + [778] "references.00.translators.01.city" + [779] "references.00.translators.01.region" + [780] "references.00.translators.01.post_code" + [781] "references.00.translators.01.country" + [782] "references.00.translators.01.orcid" + [783] "references.00.translators.01.email" + [784] "references.00.translators.01.tel" + [785] "references.00.translators.01.fax" + [786] "references.00.translators.01.website" + [787] "references.00.translators.01.date_start" + [788] "references.00.translators.01.date_end" + [789] "references.00.translators.01.location" + +# Convert a citation only + + Code + names(the_df) + Output + [1] "references.00.type" + [2] "references.00.title" + [3] "references.00.authors.00.family_names" + [4] "references.00.authors.00.given_names" + [5] "references.00.authors.00.email" + [6] "references.00.authors.00.orcid" + [7] "references.00.authors.01.family_names" + [8] "references.00.authors.01.given_names" + [9] "references.00.authors.01.affiliation" + [10] "references.00.authors.01.country" + [11] "references.00.authors.02.family_names" + [12] "references.00.authors.02.given_names" + [13] "references.00.authors.02.email" + [14] "references.00.authors.03.name" + [15] "references.00.authors.03.date_end" + [16] "references.00.url" + [17] "references.00.keywords.00" + [18] "references.00.keywords.01" + [19] "references.00.keywords.02" + [20] "references.00.keywords.03" + [21] "references.00.keywords.04" + [22] "references.00.keywords.05" + [23] "references.00.keywords.06" + [24] "references.00.keywords.07" + [25] "references.00.abstract" + [26] "references.00.version" + +# Convert authors only + + Code + names(the_df) + Output + [1] "family_names" "given_names" + +# Convert list of authors + + Code + names(the_df) + Output + [1] "person.00.family_names" "person.00.given_names" + [3] "person.00.name_particle" "person.00.name_suffix" + [5] "person.00.alias" "person.00.affiliation" + [7] "person.00.address" "person.00.city" + [9] "person.00.region" "person.00.post_code" + [11] "person.00.country" "person.00.orcid" + [13] "person.00.email" "person.00.tel" + [15] "person.00.fax" "person.00.website" + [17] "person.01.name" "person.01.address" + [19] "person.01.city" "person.01.region" + [21] "person.01.post_code" "person.01.country" + [23] "person.01.orcid" "person.01.email" + [25] "person.01.tel" "person.01.fax" + [27] "person.01.website" "person.01.date_start" + [29] "person.01.date_end" "person.01.location" + +# as.person method + + Code + dput(pub) + Output + structure(list(list(given = "Entity Project Team Conference entity", + family = NULL, role = NULL, email = "project@entity.com", + comment = c(address = "22 Acacia Avenue", city = "Citationburgh", + region = "Renfrewshire", `post-code` = "C13 7X7", country = "GB", + ORCID = "0000-0001-2345-6789", tel = "+44(0)141-323 4567", + fax = "+44(0)141-323 45678", website = "https://www.entity-project-team.io", + `date-start` = "2017-01-01", `date-end` = "2017-01-31", location = "The team garage" + ))), class = "person") + +--- + + Code + format(pub, include = c("given", "family", "email", "role", "comment")) + Output + [1] "Entity Project Team Conference entity (22 Acacia Avenue, Citationburgh, Renfrewshire, C13 7X7, GB, , +44(0)141-323 4567, +44(0)141-323 45678, https://www.entity-project-team.io, 2017-01-01, 2017-01-31, The team garage)" + +--- + + Code + dput(aut) + Output + structure(list(list(given = "One Truly", family = "van der Real Person IV", + role = NULL, email = "project@entity.com", comment = c(alias = "Citey", + affiliation = "Excellent University, Niceplace, Arcadia", + address = "22 Acacia Avenue", city = "Citationburgh", region = "Renfrewshire", + `post-code` = "C13 7X7", country = "GB", ORCID = "0000-0001-2345-6789", + tel = "+44(0)141-323 4567", fax = "+44(0)141-323 45678", + website = "https://www.entity-project-team.io"))), class = "person") + +--- + + Code + format(aut, include = c("given", "family", "email", "role", "comment")) + Output + [1] "One Truly van der Real Person IV (Citey, Excellent University, Niceplace, Arcadia, 22 Acacia Avenue, Citationburgh, Renfrewshire, C13 7X7, GB, , +44(0)141-323 4567, +44(0)141-323 45678, https://www.entity-project-team.io)" + +--- + + Code + dput(aut2) + Output + structure(list(list(given = "One Truly", family = "van der Real Person IV", + role = NULL, email = "project@entity.com", comment = c(alias = "Citey", + affiliation = "Excellent University, Niceplace, Arcadia", + address = "22 Acacia Avenue", city = "Citationburgh", region = "Renfrewshire", + `post-code` = "C13 7X7", country = "GB", ORCID = "0000-0001-2345-6789", + tel = "+44(0)141-323 4567", fax = "+44(0)141-323 45678", + website = "https://www.entity-project-team.io")), list(given = "Entity Project Team Conference entity", + family = NULL, role = NULL, email = "project@entity.com", + comment = c(address = "22 Acacia Avenue", city = "Citationburgh", + region = "Renfrewshire", `post-code` = "C13 7X7", country = "GB", + ORCID = "0000-0001-2345-6789", tel = "+44(0)141-323 4567", + fax = "+44(0)141-323 45678", website = "https://www.entity-project-team.io", + `date-start` = "2017-01-01", `date-end` = "2017-01-31", location = "The team garage" + ))), class = "person") + +--- + + Code + format(aut2, include = c("given", "family", "email", "role", "comment")) + Output + [1] "One Truly van der Real Person IV (Citey, Excellent University, Niceplace, Arcadia, 22 Acacia Avenue, Citationburgh, Renfrewshire, C13 7X7, GB, , +44(0)141-323 4567, +44(0)141-323 45678, https://www.entity-project-team.io)" + [2] "Entity Project Team Conference entity (22 Acacia Avenue, Citationburgh, Renfrewshire, C13 7X7, GB, , +44(0)141-323 4567, +44(0)141-323 45678, https://www.entity-project-team.io, 2017-01-01, 2017-01-31, The team garage)" + +# head and tail + + Code + a_cff + Output + authors: + - family-names: Doe + given-names: John + cff-version: 1.2.0 + message: If you use this software, please cite it using these metadata. + title: My Research Software + +--- + + Code + head(a_cff, 2) + Output + authors: + - family-names: Doe + given-names: John + cff-version: 1.2.0 + +--- + + Code + tail(a_cff, 2) + Output + message: If you use this software, please cite it using these metadata. + title: My Research Software + +# toBibtex + + Code + toBibtex(full_cff) + Output + @Misc{druskatspaaks:2021, + title = {Citation File Format}, + author = {Stephan Druskat and Jurriaan H. Spaaks and Neil {Chue Hong} and Robert Haines and James Baker and Spencer Bliven and Egon Willighagen and David Pérez-Suárez and Alexander Konovalov}, + year = {2021}, + month = {aug}, + doi = {10.5281/zenodo.5171937}, + url = {https://github.com/citation-file-format/citation-file-format}, + abstract = {The Citation File Format lets you provide citation metadata for software or datasets in plaintext files that are easy to read by both humans and machines.}, + urldate = {2021-11-07}, + } + +--- + + Code + toBibtex(full_cff, what = "references") + Output + @Article{hernangomez:2021, + title = {cffr: Generate Citation File Format Metadata for R Packages}, + author = {Diego Hernangómez}, + year = {2021}, + journal = {Journal of Open Source Software}, + publisher = {The Open Journal}, + volume = {6}, + number = {67}, + pages = {3900}, + doi = {10.21105/joss.03900}, + url = {https://doi.org/10.21105/joss.03900}, + note = {Publisher: The Open Journal}, + } + + @Article{boettigerchamberlain:2016, + title = {RNeXML: A Package for Reading and Writing Richly Annotated Phylogenetic, Character, and Trait Data in R}, + author = {Carl Boettiger and Scott Chamberlain and Rutger Vos and Hilmar Lapp}, + year = {2016}, + journal = {Methods in Ecology and Evolution}, + volume = {7}, + pages = {352--357}, + doi = {10.1111/2041-210X.12469}, + } + + @Book{wickham:2016, + title = {ggplot2: Elegant Graphics for Data Analysis}, + author = {Hadley Wickham}, + year = {2016}, + publisher = {Springer-Verlag New York}, + isbn = {978-3-319-24277-4}, + url = {https://ggplot2.tidyverse.org}, + } + +--- + + Code + toBibtex(full_cff, what = "all") + Output + @Misc{druskatspaaks:2021, + title = {Citation File Format}, + author = {Stephan Druskat and Jurriaan H. Spaaks and Neil {Chue Hong} and Robert Haines and James Baker and Spencer Bliven and Egon Willighagen and David Pérez-Suárez and Alexander Konovalov}, + year = {2021}, + month = {aug}, + doi = {10.5281/zenodo.5171937}, + url = {https://github.com/citation-file-format/citation-file-format}, + abstract = {The Citation File Format lets you provide citation metadata for software or datasets in plaintext files that are easy to read by both humans and machines.}, + urldate = {2021-11-07}, + } + + @Article{hernangomez:2021, + title = {cffr: Generate Citation File Format Metadata for R Packages}, + author = {Diego Hernangómez}, + year = {2021}, + journal = {Journal of Open Source Software}, + publisher = {The Open Journal}, + volume = {6}, + number = {67}, + pages = {3900}, + doi = {10.21105/joss.03900}, + url = {https://doi.org/10.21105/joss.03900}, + note = {Publisher: The Open Journal}, + } + + @Article{boettigerchamberlain:2016, + title = {RNeXML: A Package for Reading and Writing Richly Annotated Phylogenetic, Character, and Trait Data in R}, + author = {Carl Boettiger and Scott Chamberlain and Rutger Vos and Hilmar Lapp}, + year = {2016}, + journal = {Methods in Ecology and Evolution}, + volume = {7}, + pages = {352--357}, + doi = {10.1111/2041-210X.12469}, + } + + @Book{wickham:2016, + title = {ggplot2: Elegant Graphics for Data Analysis}, + author = {Hadley Wickham}, + year = {2016}, + publisher = {Springer-Verlag New York}, + isbn = {978-3-319-24277-4}, + url = {https://ggplot2.tidyverse.org}, + } + diff --git a/tests/testthat/_snaps/cff.md b/tests/testthat/_snaps/cff.md new file mode 100644 index 00000000..ee022981 --- /dev/null +++ b/tests/testthat/_snaps/cff.md @@ -0,0 +1,1777 @@ +# Test message on cff + + Code + def <- cff("abcde") + Condition + Warning: + The `path` argument of `cff()` is deprecated as of cffr 1.0.0. + i Argument ignored. + +--- + + Code + afile <- cff(nocff) + Condition + Warning: + The `path` argument of `cff()` is deprecated as of cffr 1.0.0. + i Argument ignored. + +# Walk trough full lifecycle + + Code + read + Output + cff-version: 1.2.0 + message: If you use this software, please cite it as below. + abstract: This is an awesome piece of research software! + authors: + - family-names: Real Person + given-names: One Truly + name-particle: van der + name-suffix: IV + alias: Citey + affiliation: Excellent University, Niceplace, Arcadia + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + - name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + commit: 156a04c74a8a79d40c5d705cddf9d36735feab4d + contact: + - family-names: Real Person + given-names: One Truly + name-particle: van der + name-suffix: IV + alias: Citey + affiliation: Excellent University, Niceplace, Arcadia + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + - name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + date-released: '2017-12-11' + doi: 10.5281/zenodo.1003150 + identifiers: + - type: doi + value: 10.5281/zenodo.1003150 + - type: swh + value: swh:1:rel:99f6850374dc6597af01bd0ee1d3fc0699301b9f + - type: url + value: https://example.com + - type: other + value: other-schema://abcd.1234.efgh.5678 + keywords: + - One + - Two + - Three + - '4' + license: CC-BY-SA-4.0 + license-url: https://spdx.org/licenses/CC-BY-SA-4.0.html#licenseText + repository: https://www.example.com/foo/?bar=baz&inga=42&quux + repository-code: http://foo.com/blah_(wikipedia)_blah#cite-1 + repository-artifact: https://files.pythonhosted.org/packages/0a/84/10507b69a07768bc16981184b4d147a0fc84b71fbf35c03bafc8dcced8e1/cffconvert-1.3.3.tar.gz + title: Citation File Format 1.0.0 + type: software + url: http://userid:password@example.com:8080/ + version: 1.0.0 + preferred-citation: + type: book + title: Book Title + abbreviation: Abbr + abstract: Description of the book. + collection-doi: 10.5281/zenodo.1003150 + collection-title: Collection Title + collection-type: Collection Type + commit: 156a04c74a8a79d40c5d705cddf9d36735feab4d + copyright: 2017 Stephan Druskat + data-type: Data Type + database: Database + date-accessed: '2017-10-31' + date-downloaded: '2017-10-31' + date-released: '2017-10-31' + date-published: '2017-10-31' + department: Department + doi: 10.5281/zenodo.1003150 + edition: 2nd edition + end: '456' + entry: Chapter 9 + filename: book.zip + format: Printed book + identifiers: + - type: doi + value: 10.5281/zenodo.1003150 + - type: swh + value: swh:1:rel:99f6850374dc6597af01bd0ee1d3fc0699301b9f + - type: url + value: https://example.com + - type: other + value: other-schema://abcd.1234.efgh.5678 + isbn: 978-1-89183-044-0 + issn: 1234-543X + issue: '123' + issue-date: December + issue-title: Special Issue on Software Citation + journal: PeerJ + keywords: + - Software + - Citation + languages: + - aaa + - zu + license: Apache-2.0 + license-url: https://spdx.org/licenses/Apache-2.0.html#licenseText + loc-start: '14' + loc-end: '54' + medium: hardcover book + month: '3' + nihmsid: Don't know what format a NIHMSID is in + notes: A field for general notes about the reference, usable in other formats such + as BibTeX. + number: A general-purpose field for accession numbers, cf. the specifications for + examples. + number-volumes: '7' + pages: '765' + patent-states: + - Germany + - ROI + - 'but also for example US states, such as:' + - IL + - RI + pmcid: PMC1234567 + repository: http://code.google.com/events/#&product=browser + repository-code: http://142.42.1.1:8080/ + repository-artifact: https://files.pythonhosted.org/packages/0a/84/10507b69a07768bc16981184b4d147a0fc84b71fbf35c03bafc8dcced8e1/cffconvert-1.3.3.tar.gz + scope: Cite this book if you want to reference the general concepts implemented + in Citation File Format 1.0.0. + section: Chapter 2 - "Reference keys" + status: advance-online + start: '123' + thesis-type: Doctoral dissertation + url: http://j.mp + version: 0.0.1423-BETA + volume: '2' + volume-title: Advances in Software Citation + year: '2017' + year-original: '2012' + conference: + name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + authors: + - family-names: Real Person + given-names: One Truly + name-particle: van der + name-suffix: IV + alias: Citey + affiliation: Excellent University, Niceplace, Arcadia + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + - name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + contact: + - family-names: Real Person + given-names: One Truly + name-particle: van der + name-suffix: IV + alias: Citey + affiliation: Excellent University, Niceplace, Arcadia + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + - name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + database-provider: + name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + editors: + - family-names: Real Person + given-names: One Truly + name-particle: van der + name-suffix: IV + alias: Citey + affiliation: Excellent University, Niceplace, Arcadia + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + - name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + editors-series: + - family-names: Real Person + given-names: One Truly + name-particle: van der + name-suffix: IV + alias: Citey + affiliation: Excellent University, Niceplace, Arcadia + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + - name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + institution: + name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + location: + name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + publisher: + name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + recipients: + - family-names: Real Person + given-names: One Truly + name-particle: van der + name-suffix: IV + alias: Citey + affiliation: Excellent University, Niceplace, Arcadia + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + - name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + senders: + - family-names: Real Person + given-names: One Truly + name-particle: van der + name-suffix: IV + alias: Citey + affiliation: Excellent University, Niceplace, Arcadia + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + - name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + translators: + - family-names: Real Person + given-names: One Truly + name-particle: van der + name-suffix: IV + alias: Citey + affiliation: Excellent University, Niceplace, Arcadia + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + - name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + references: + - type: book + title: Book Title + abbreviation: Abbr + abstract: Description of the book. + collection-doi: 10.5281/zenodo.1003150 + collection-title: Collection Title + collection-type: Collection Type + commit: 156a04c74a8a79d40c5d705cddf9d36735feab4d + copyright: 2017 Stephan Druskat + data-type: Data Type + database: Database + date-accessed: '2017-10-31' + date-downloaded: '2017-10-31' + date-released: '2017-10-31' + date-published: '2017-10-31' + department: Department + doi: 10.5281/zenodo.1003150 + edition: 2nd edition + end: '123' + entry: Chapter 9 + filename: book.zip + format: Printed book + identifiers: + - type: doi + value: 10.5281/zenodo.1003150 + - type: swh + value: swh:1:rel:99f6850374dc6597af01bd0ee1d3fc0699301b9f + - type: url + value: https://example.com + - type: other + value: other-schema://abcd.1234.efgh.5678 + isbn: 978-1-89183-044-0 + issn: 1234-543X + issue: '123' + issue-date: December + issue-title: Special Issue on Software Citation + journal: PeerJ + keywords: + - Software + - Citation + languages: + - aaa + - zu + license: Apache-2.0 + license-url: https://spdx.org/licenses/Apache-2.0.html#licenseText + loc-start: '14' + loc-end: '54' + medium: hardcover book + month: '3' + nihmsid: Don't know what format a NIHMSID is in + notes: A field for general notes about the reference, usable in other formats such + as BibTeX. + number: A general-purpose field for accession numbers, cf. the specifications for + examples. + number-volumes: '7' + pages: '765' + patent-states: + - Germany + - ROI + - 'but also for example US states, such as:' + - IL + - RI + pmcid: PMC1234567 + repository: http://code.google.com/events/#&product=browser + repository-code: http://142.42.1.1:8080/ + repository-artifact: https://files.pythonhosted.org/packages/0a/84/10507b69a07768bc16981184b4d147a0fc84b71fbf35c03bafc8dcced8e1/cffconvert-1.3.3.tar.gz + scope: Cite this book if you want to reference the general concepts implemented + in Citation File Format 1.0.0. + section: Chapter 2 - "Reference keys" + status: advance-online + start: '123' + thesis-type: Doctoral dissertation + url: http://j.mp + version: 0.0.1423-BETA + volume: '2' + volume-title: Advances in Software Citation + year: '2017' + year-original: '2012' + conference: + name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + authors: + - family-names: Real Person + given-names: One Truly + name-particle: van der + name-suffix: IV + alias: Citey + affiliation: Excellent University, Niceplace, Arcadia + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + - name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + contact: + - family-names: Real Person + given-names: One Truly + name-particle: van der + name-suffix: IV + alias: Citey + affiliation: Excellent University, Niceplace, Arcadia + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + - name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + database-provider: + name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + editors: + - family-names: Real Person + given-names: One Truly + name-particle: van der + name-suffix: IV + alias: Citey + affiliation: Excellent University, Niceplace, Arcadia + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + - name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + editors-series: + - family-names: Real Person + given-names: One Truly + name-particle: van der + name-suffix: IV + alias: Citey + affiliation: Excellent University, Niceplace, Arcadia + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + - name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + institution: + name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + location: + name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + publisher: + name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + recipients: + - family-names: Real Person + given-names: One Truly + name-particle: van der + name-suffix: IV + alias: Citey + affiliation: Excellent University, Niceplace, Arcadia + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + - name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + senders: + - family-names: Real Person + given-names: One Truly + name-particle: van der + name-suffix: IV + alias: Citey + affiliation: Excellent University, Niceplace, Arcadia + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + - name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + translators: + - family-names: Real Person + given-names: One Truly + name-particle: van der + name-suffix: IV + alias: Citey + affiliation: Excellent University, Niceplace, Arcadia + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + - name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + +--- + + Code + modify + Output + cff-version: 1.2.0 + message: If you use this software, please cite it as below. + type: software + license: CC-BY-SA-4.0 + title: A new title + version: 1.0.0 + doi: 10.5281/zenodo.1003150 + abstract: This is an awesome piece of research software! + authors: + - family-names: Real Person + given-names: One Truly + name-particle: van der + name-suffix: IV + alias: Citey + affiliation: Excellent University, Niceplace, Arcadia + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + - name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + preferred-citation: + type: book + title: Book Title + abbreviation: Abbr + abstract: Description of the book. + collection-doi: 10.5281/zenodo.1003150 + collection-title: Collection Title + collection-type: Collection Type + commit: 156a04c74a8a79d40c5d705cddf9d36735feab4d + copyright: 2017 Stephan Druskat + data-type: Data Type + database: Database + date-accessed: '2017-10-31' + date-downloaded: '2017-10-31' + date-released: '2017-10-31' + date-published: '2017-10-31' + department: Department + doi: 10.5281/zenodo.1003150 + edition: 2nd edition + end: '456' + entry: Chapter 9 + filename: book.zip + format: Printed book + identifiers: + - type: doi + value: 10.5281/zenodo.1003150 + - type: swh + value: swh:1:rel:99f6850374dc6597af01bd0ee1d3fc0699301b9f + - type: url + value: https://example.com + - type: other + value: other-schema://abcd.1234.efgh.5678 + isbn: 978-1-89183-044-0 + issn: 1234-543X + issue: '123' + issue-date: December + issue-title: Special Issue on Software Citation + journal: PeerJ + keywords: + - Software + - Citation + languages: + - aaa + - zu + license: Apache-2.0 + license-url: https://spdx.org/licenses/Apache-2.0.html#licenseText + loc-start: '14' + loc-end: '54' + medium: hardcover book + month: '3' + nihmsid: Don't know what format a NIHMSID is in + notes: A field for general notes about the reference, usable in other formats such + as BibTeX. + number: A general-purpose field for accession numbers, cf. the specifications for + examples. + number-volumes: '7' + pages: '765' + patent-states: + - Germany + - ROI + - 'but also for example US states, such as:' + - IL + - RI + pmcid: PMC1234567 + repository: http://code.google.com/events/#&product=browser + repository-code: http://142.42.1.1:8080/ + repository-artifact: https://files.pythonhosted.org/packages/0a/84/10507b69a07768bc16981184b4d147a0fc84b71fbf35c03bafc8dcced8e1/cffconvert-1.3.3.tar.gz + scope: Cite this book if you want to reference the general concepts implemented + in Citation File Format 1.0.0. + section: Chapter 2 - "Reference keys" + status: advance-online + start: '123' + thesis-type: Doctoral dissertation + url: http://j.mp + version: 0.0.1423-BETA + volume: '2' + volume-title: Advances in Software Citation + year: '2017' + year-original: '2012' + conference: + name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + authors: + - family-names: Real Person + given-names: One Truly + name-particle: van der + name-suffix: IV + alias: Citey + affiliation: Excellent University, Niceplace, Arcadia + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + - name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + contact: + - family-names: Real Person + given-names: One Truly + name-particle: van der + name-suffix: IV + alias: Citey + affiliation: Excellent University, Niceplace, Arcadia + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + - name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + database-provider: + name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + editors: + - family-names: Real Person + given-names: One Truly + name-particle: van der + name-suffix: IV + alias: Citey + affiliation: Excellent University, Niceplace, Arcadia + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + - name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + editors-series: + - family-names: Real Person + given-names: One Truly + name-particle: van der + name-suffix: IV + alias: Citey + affiliation: Excellent University, Niceplace, Arcadia + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + - name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + institution: + name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + location: + name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + publisher: + name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + recipients: + - family-names: Real Person + given-names: One Truly + name-particle: van der + name-suffix: IV + alias: Citey + affiliation: Excellent University, Niceplace, Arcadia + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + - name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + senders: + - family-names: Real Person + given-names: One Truly + name-particle: van der + name-suffix: IV + alias: Citey + affiliation: Excellent University, Niceplace, Arcadia + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + - name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + translators: + - family-names: Real Person + given-names: One Truly + name-particle: van der + name-suffix: IV + alias: Citey + affiliation: Excellent University, Niceplace, Arcadia + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + - name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + repository: https://www.example.com/foo/?bar=baz&inga=42&quux + repository-artifact: https://files.pythonhosted.org/packages/0a/84/10507b69a07768bc16981184b4d147a0fc84b71fbf35c03bafc8dcced8e1/cffconvert-1.3.3.tar.gz + repository-code: http://foo.com/blah_(wikipedia)_blah#cite-1 + url: http://userid:password@example.com:8080/ + date-released: '2017-12-11' + contact: + - family-names: Real Person + given-names: One Truly + name-particle: van der + name-suffix: IV + alias: Citey + affiliation: Excellent University, Niceplace, Arcadia + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + - name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + keywords: + - One + - Two + - Three + - '4' + references: + - type: book + title: Book Title + abbreviation: Abbr + abstract: Description of the book. + collection-doi: 10.5281/zenodo.1003150 + collection-title: Collection Title + collection-type: Collection Type + commit: 156a04c74a8a79d40c5d705cddf9d36735feab4d + copyright: 2017 Stephan Druskat + data-type: Data Type + database: Database + date-accessed: '2017-10-31' + date-downloaded: '2017-10-31' + date-released: '2017-10-31' + date-published: '2017-10-31' + department: Department + doi: 10.5281/zenodo.1003150 + edition: 2nd edition + end: '123' + entry: Chapter 9 + filename: book.zip + format: Printed book + identifiers: + - type: doi + value: 10.5281/zenodo.1003150 + - type: swh + value: swh:1:rel:99f6850374dc6597af01bd0ee1d3fc0699301b9f + - type: url + value: https://example.com + - type: other + value: other-schema://abcd.1234.efgh.5678 + isbn: 978-1-89183-044-0 + issn: 1234-543X + issue: '123' + issue-date: December + issue-title: Special Issue on Software Citation + journal: PeerJ + keywords: + - Software + - Citation + languages: + - aaa + - zu + license: Apache-2.0 + license-url: https://spdx.org/licenses/Apache-2.0.html#licenseText + loc-start: '14' + loc-end: '54' + medium: hardcover book + month: '3' + nihmsid: Don't know what format a NIHMSID is in + notes: A field for general notes about the reference, usable in other formats such + as BibTeX. + number: A general-purpose field for accession numbers, cf. the specifications for + examples. + number-volumes: '7' + pages: '765' + patent-states: + - Germany + - ROI + - 'but also for example US states, such as:' + - IL + - RI + pmcid: PMC1234567 + repository: http://code.google.com/events/#&product=browser + repository-code: http://142.42.1.1:8080/ + repository-artifact: https://files.pythonhosted.org/packages/0a/84/10507b69a07768bc16981184b4d147a0fc84b71fbf35c03bafc8dcced8e1/cffconvert-1.3.3.tar.gz + scope: Cite this book if you want to reference the general concepts implemented + in Citation File Format 1.0.0. + section: Chapter 2 - "Reference keys" + status: advance-online + start: '123' + thesis-type: Doctoral dissertation + url: http://j.mp + version: 0.0.1423-BETA + volume: '2' + volume-title: Advances in Software Citation + year: '2017' + year-original: '2012' + conference: + name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + authors: + - family-names: Real Person + given-names: One Truly + name-particle: van der + name-suffix: IV + alias: Citey + affiliation: Excellent University, Niceplace, Arcadia + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + - name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + contact: + - family-names: Real Person + given-names: One Truly + name-particle: van der + name-suffix: IV + alias: Citey + affiliation: Excellent University, Niceplace, Arcadia + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + - name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + database-provider: + name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + editors: + - family-names: Real Person + given-names: One Truly + name-particle: van der + name-suffix: IV + alias: Citey + affiliation: Excellent University, Niceplace, Arcadia + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + - name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + editors-series: + - family-names: Real Person + given-names: One Truly + name-particle: van der + name-suffix: IV + alias: Citey + affiliation: Excellent University, Niceplace, Arcadia + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + - name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + institution: + name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + location: + name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + publisher: + name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + recipients: + - family-names: Real Person + given-names: One Truly + name-particle: van der + name-suffix: IV + alias: Citey + affiliation: Excellent University, Niceplace, Arcadia + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + - name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + senders: + - family-names: Real Person + given-names: One Truly + name-particle: van der + name-suffix: IV + alias: Citey + affiliation: Excellent University, Niceplace, Arcadia + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + - name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + translators: + - family-names: Real Person + given-names: One Truly + name-particle: van der + name-suffix: IV + alias: Citey + affiliation: Excellent University, Niceplace, Arcadia + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + - name: Entity Project Team Conference entity + address: 22 Acacia Avenue + city: Citationburgh + region: Renfrewshire + post-code: C13 7X7 + country: GB + orcid: https://orcid.org/0000-0001-2345-6789 + email: project@entity.com + tel: +44(0)141-323 4567 + fax: +44(0)141-323 45678 + website: https://www.entity-project-team.io + date-start: '2017-01-01' + date-end: '2017-01-31' + location: The team garage + commit: 156a04c74a8a79d40c5d705cddf9d36735feab4d + identifiers: + - type: doi + value: 10.5281/zenodo.1003150 + - type: swh + value: swh:1:rel:99f6850374dc6597af01bd0ee1d3fc0699301b9f + - type: url + value: https://example.com + - type: other + value: other-schema://abcd.1234.efgh.5678 + license-url: https://spdx.org/licenses/CC-BY-SA-4.0.html#licenseText + +# Recursive parsing + + Code + read <- cff(complete) + Condition + Warning: + The `path` argument of `cff()` is deprecated as of cffr 1.0.0. + i Please use `cff_read_cff_citation()` instead. + +# Fuzzy matching of keys on cff + + Code + cff(tittle = "a", cff_version = "ar", version = "200", messange = "Fix my keys") + Message + i Found misspelled keys. Trying to map: + v tittle: title + v messange: message + Output + title: a + cff-version: ar + version: '200' + message: Fix my keys + +--- + + Code + cffobj <- cff(tittle = "a", cff_version = "1.2.0", version = "200", messange = "aa", + anthor = list(list(`family-names` = "a", `given-names` = "b"))) + Message + i Found misspelled keys. Trying to map: + v tittle: title + v messange: message + v anthor: authors + +# duplicated + + Code + ss <- cff(tittle = "a", tittle = "ar", version = "200", messange = "Fix my keys") + Message + i Found misspelled keys. Trying to map: + v tittle: title + v tittle: title + v messange: message + ! Removing duplicated keys. + +# unnamed + + Code + ss <- cff(path = "a", "200", "Fix my keys") + Condition + Warning: + The `path` argument of `cff()` is deprecated as of cffr 1.0.0. + i Argument ignored. + Error in `validate_extra_keys()`: + ! Elements in `...` should be named. + +--- + + Code + s1 <- cff(path = NULL, title = "a", "b", version = 1) + Condition + Warning: + The `path` argument of `cff()` is deprecated as of cffr 1.0.0. + i Argument ignored. + Message + ! Found 1 not-named argument in position 2. + i Removing unnamed arguments + +--- + + Code + s2 <- cff(path = NULL, title = "a", "aa", "bb", "cc", "b", version = 1, "h", + "j") + Condition + Warning: + The `path` argument of `cff()` is deprecated as of cffr 1.0.0. + i Argument ignored. + Message + ! Found 6 not-named arguments in positions 2, 3, 4, 5, 7, and 8. + i Removing unnamed arguments + diff --git a/tests/testthat/_snaps/cff_create.md b/tests/testthat/_snaps/cff_create.md index 2aa1451c..968ab77e 100644 --- a/tests/testthat/_snaps/cff_create.md +++ b/tests/testthat/_snaps/cff_create.md @@ -92,3 +92,398 @@ --- +# Parse date + + Code + parsed + Output + cff-version: 1.2.0 + message: 'To cite package "rgeos" in publications use:' + type: software + license: GPL-2.0-or-later + title: 'rgeos: Interface to Geometry Engine - Open Source (''GEOS'')' + version: 0.5-7 + abstract: 'Interface to Geometry Engine - Open Source (''GEOS'') using the C ''API'' + for topology operations on geometries. Please note that ''rgeos'' will be retired + by the end of 2023, plan transition to sf functions using ''GEOS'' at your earliest + convenience. The ''GEOS'' library is external to the package, and, when installing + the package from source, must be correctly installed first. Windows and Mac Intel + OS X binaries are provided on ''CRAN''. (''rgeos'' >= 0.5-1): Up to and including + ''GEOS'' 3.7.1, topological operations succeeded with some invalid geometries for + which the same operations fail from and including ''GEOS'' 3.7.2. The ''checkValidity='' + argument defaults and structure have been changed, from default FALSE to integer + default ''0L'' for ''GEOS'' < 3.7.2 (no check), ''1L'' ''GEOS'' >= 3.7.2 (check + and warn). A value of ''2L'' is also provided that may be used, assigned globally + using ''set_RGEOS_CheckValidity(2L)'', or locally using the ''checkValidity=2L'' + argument, to attempt zero-width buffer repair if invalid geometries are found. The + previous default (FALSE, now ''0L'') is fastest and used for ''GEOS'' < 3.7.2, but + will not warn users of possible problems before the failure of topological operations + that previously succeeded. From ''GEOS'' 3.8.0, repair of geometries may also be + attempted using ''gMakeValid()'', which may, however, return a collection of geometries + of different types.' + authors: + - family-names: Bivand + given-names: Roger + email: Roger.Bivand@nhh.no + orcid: https://orcid.org/0000-0003-2392-6140 + - family-names: Rundel + given-names: Colin + repository: https://CRAN.R-project.org/package=rgeos + repository-code: https://r-forge.r-project.org/projects/rgeos/ + url: https://trac.osgeo.org/geos/ + date-released: '2020-09-07' + contact: + - family-names: Bivand + given-names: Roger + email: Roger.Bivand@nhh.no + orcid: https://orcid.org/0000-0003-2392-6140 + identifiers: + - type: url + value: http://rgeos.r-forge.r-project.org/index.html + +# Parse date in another format + + Code + parsed + Output + cff-version: 1.2.0 + message: 'To cite package "basicdescdate" in publications use:' + type: software + license: GPL-3.0-only + title: 'basicdescdate: A Basic Description with Date' + version: 0.1.6 + abstract: A very basic description. Should parse without problems. I have a Date + authors: + - family-names: Basic + given-names: Marc + email: marcbasic@gmail.com + repository-code: https://github.com/basic/package + url: https://basic.github.io/package + date-released: '1999-01-01' + contact: + - family-names: Basic + given-names: Marc + email: marcbasic@gmail.com + +# Parsing many urls + + Code + parsed + Output + cff-version: 1.2.0 + message: 'To cite package "manyurls" in publications use:' + type: software + license: GPL-3.0-only + title: 'manyurls: A lot of urls' + version: 0.1.6 + abstract: This package has many urls. Specifically, 1 Bug Reports and 6 URLs. Expected + is to have 1 repository-code, 1 url and 3 URLs, since there is 1 duplicate and 1 + invalid url. + authors: + - family-names: Basic + given-names: Marc + email: marcbasic@gmail.com + repository-code: https://github.com/test/package + url: https://test.github.io/package/ + contact: + - family-names: Basic + given-names: Marc + email: marcbasic@gmail.com + identifiers: + - type: url + value: https://r-forge.r-project.org/projects/test/ + - type: url + value: http://google.ru + - type: url + value: https://gitlab.com/r-packages/behaviorchange + +# Parsing Gitlab + + Code + parsed + Output + cff-version: 1.2.0 + message: 'To cite package "codemetar" in publications use:' + type: software + license: GPL-3.0-only + title: 'codemetar: Generate ''CodeMeta'' Metadata for R Packages' + version: 0.1.6 + abstract: The 'Codemeta' Project defines a 'JSON-LD' format for describing software + metadata, as detailed at . This package provides utilities + to generate, parse, and modify 'codemeta.json' files automatically for R packages, + as well as tools and examples for working with 'codemeta.json' 'JSON-LD' more generally. + authors: + - family-names: Boettiger + given-names: Carl + email: cboettig@gmail.com + orcid: https://orcid.org/0000-0002-1642-628X + - family-names: Salmon + given-names: Maëlle + orcid: https://orcid.org/0000-0002-2815-0399 + repository: https://CRAN.R-project.org/package=codemetar + repository-code: https://gitlab.com/ninijay/methoden + url: https://ropensci.github.io/codemetar + contact: + - family-names: Boettiger + given-names: Carl + email: cboettig@gmail.com + orcid: https://orcid.org/0000-0002-1642-628X + keywords: + - metadata + - codemeta + - ropensci + - citation + - credit + - linked-data + +# Parsing many persons + + Code + parsed + Output + cff-version: 1.2.0 + message: 'To cite package "manypersons" in publications use:' + type: software + license: GPL-3.0-only + title: 'manypersons: A lot of persons' + version: 0.1.6 + abstract: Overkill desc with many persons. Try this + authors: + - family-names: Hernangómez + given-names: Diego + email: fake@gmail.com + orcid: https://orcid.org/0000-0001-8457-4658 + - family-names: Doe + given-names: Joe + affiliation: This One + country: ES + - family-names: Doe + given-names: Pepe + email: fake@gmail.com + - name: I am an entity + date-end: '2020-01-01' + repository-code: https://github.com/many/persons + url: https://many.github.io/persons + contact: + - family-names: Hernangómez + given-names: Diego + email: fake@gmail.com + orcid: https://orcid.org/0000-0001-8457-4658 + - name: I am an entity + date-end: '2020-01-01' + keywords: + - metadata + - cffr + - ropensci + - citation + - credit + - linked-data + - one + - two + +# Parsing wrong urls + + Code + parsed + Output + cff-version: 1.2.0 + message: 'To cite package "wrongurls" in publications use:' + type: software + license: MIT + title: 'wrongurls: Generate CodeMeta Metadata for R Packages' + version: 0.1.0 + abstract: Codemeta defines a 'JSON-LD' format for describing software metadata. This + package provides utilities to generate, parse, and modify codemeta.jsonld files + automatically for R packages. + authors: + - family-names: Boettiger + given-names: Carl + email: cboettig@gmail.com + orcid: https://orcid.org/0000-0002-1642-628X + url: https://httpbin.org/status/404 + contact: + - family-names: Boettiger + given-names: Carl + email: cboettig@gmail.com + orcid: https://orcid.org/0000-0002-1642-628X + keywords: + - metadata + - codemeta + - ropensci + - citation + - credit + - linked-data + identifiers: + - type: url + value: https://httpbin.org/status/429 + - type: url + value: https://www.github.es/ropensci/codemeta + +# Parsing two maintainers + + Code + parsed + Output + cff-version: 1.2.0 + message: 'To cite package "codemetar" in publications use:' + type: software + license: GPL-3.0-only + title: 'codemetar: Generate ''CodeMeta'' Metadata for R Packages' + version: 0.1.6 + abstract: The 'Codemeta' Project defines a 'JSON-LD' format for describing software + metadata, as detailed at . This package provides utilities + to generate, parse, and modify 'codemeta.json' files automatically for R packages, + as well as tools and examples for working with 'codemeta.json' 'JSON-LD' more generally. + authors: + - family-names: Ok + given-names: John + email: email@email.edu + - family-names: Doe + given-names: Jane + email: email2@email.edu + - family-names: Doo + given-names: Jane + repository: https://CRAN.R-project.org/package=codemetar + repository-code: https://github.com/ropensci/codemetar + url: https://ropensci.github.io/codemetar + contact: + - family-names: Ok + given-names: John + email: email@email.edu + - family-names: Doe + given-names: Jane + email: email2@email.edu + +# Parsing r-universe + + Code + parsed + Output + cff-version: 1.2.0 + message: 'To cite package "codemetar" in publications use:' + type: software + license: GPL-3.0-only + title: 'codemetar: Generate ''CodeMeta'' Metadata for R Packages' + version: 0.3.5 + abstract: The 'Codemeta' Project defines a 'JSON-LD' format for describing software + metadata, as detailed at . This package provides utilities + to generate, parse, and modify 'codemeta.json' files automatically for R packages, + as well as tools and examples for working with 'codemeta.json' 'JSON-LD' more generally. + authors: + - family-names: Boettiger + given-names: Carl + email: cboettig@gmail.com + orcid: https://orcid.org/0000-0002-1642-628X + - family-names: Salmon + given-names: Maëlle + orcid: https://orcid.org/0000-0002-2815-0399 + repository: https://ropensci.r-universe.dev + repository-code: https://github.com/ropensci/codemetar + url: https://docs.ropensci.org/codemetar/ + date-released: '2024-02-09' + contact: + - family-names: Boettiger + given-names: Carl + email: cboettig@gmail.com + orcid: https://orcid.org/0000-0002-1642-628X + keywords: + - metadata + - codemeta + - ropensci + - citation + - credit + - linked-data + +# Parsing Bioconductor + + Code + parsed + Output + cff-version: 1.2.0 + message: 'To cite package "GenomicRanges" in publications use:' + type: software + license: Artistic-2.0 + title: 'GenomicRanges: Representation and manipulation of genomic intervals' + version: 1.51.4 + abstract: The ability to efficiently represent and manipulate genomic annotations + and alignments is playing a central role when it comes to analyzing high-throughput + sequencing data (a.k.a. NGS data). The GenomicRanges package defines general purpose + containers for storing and manipulating genomic intervals and variables defined + along a genome. More specialized containers for representing and manipulating short + alignments against a reference genome, or a matrix-like summarization of an experiment, + are defined in the GenomicAlignments and SummarizedExperiment packages, respectively. + Both packages build on top of the GenomicRanges infrastructure. + authors: + - family-names: Aboyoun + given-names: Patrick + - family-names: Pagès + given-names: Hervé + email: hpages.on.github@gmail.com + - family-names: Lawrence + given-names: Michael + repository: https://bioconductor.org/ + repository-code: https://github.com/Bioconductor/GenomicRanges + url: https://bioconductor.org/packages/GenomicRanges + date-released: '2022-12-15' + contact: + - family-names: Pagès + given-names: Hervé + email: hpages.on.github@gmail.com + +# Parsing Posit Package Manager + + Code + parsed + Output + cff-version: 1.2.0 + message: 'To cite package "resmush" in publications use:' + type: software + license: MIT + title: 'resmush: Optimize and Compress Image Files with ''reSmush.it''' + version: 0.1.0 + abstract: Compress local and online images using the 'reSmush.it' API service . + authors: + - family-names: Hernangómez + given-names: Diego + email: diego.hernangomezherrero@gmail.com + orcid: https://orcid.org/0000-0001-8457-4658 + repository: https://CRAN.R-project.org/package=resmush + repository-code: https://github.com/dieghernan/resmush + url: https://dieghernan.github.io/resmush/ + date-released: '2024-02-02' + contact: + - family-names: Hernangómez + given-names: Diego + email: diego.hernangomezherrero@gmail.com + orcid: https://orcid.org/0000-0001-8457-4658 + keywords: + - r + - compress-images + - optimize-images + - resmushit + - api + +# Search package on CRAN + + Code + parsed + Output + cff-version: 1.2.0 + message: 'To cite package "ggplot2" in publications use:' + type: software + license: GPL-3.0-only + title: 'ggplot2: A Basic Description' + version: 0.1.6 + abstract: A very basic description. Should parse without problems. + authors: + - family-names: Basic + given-names: Marc + email: marcbasic@gmail.com + repository: https://CRAN.R-project.org/package=ggplot2 + repository-code: https://github.com/basic/package + url: https://basic.github.io/package + contact: + - family-names: Basic + given-names: Marc + email: marcbasic@gmail.com + diff --git a/tests/testthat/_snaps/cff_description.md b/tests/testthat/_snaps/cff_description.md deleted file mode 100644 index 4a203664..00000000 --- a/tests/testthat/_snaps/cff_description.md +++ /dev/null @@ -1,395 +0,0 @@ -# Parse date - - Code - parsed - Output - cff-version: 1.2.0 - message: 'To cite package "rgeos" in publications use:' - type: software - license: GPL-2.0-or-later - title: 'rgeos: Interface to Geometry Engine - Open Source (''GEOS'')' - version: 0.5-7 - abstract: 'Interface to Geometry Engine - Open Source (''GEOS'') using the C ''API'' - for topology operations on geometries. Please note that ''rgeos'' will be retired - by the end of 2023, plan transition to sf functions using ''GEOS'' at your earliest - convenience. The ''GEOS'' library is external to the package, and, when installing - the package from source, must be correctly installed first. Windows and Mac Intel - OS X binaries are provided on ''CRAN''. (''rgeos'' >= 0.5-1): Up to and including - ''GEOS'' 3.7.1, topological operations succeeded with some invalid geometries for - which the same operations fail from and including ''GEOS'' 3.7.2. The ''checkValidity='' - argument defaults and structure have been changed, from default FALSE to integer - default ''0L'' for ''GEOS'' < 3.7.2 (no check), ''1L'' ''GEOS'' >= 3.7.2 (check - and warn). A value of ''2L'' is also provided that may be used, assigned globally - using ''set_RGEOS_CheckValidity(2L)'', or locally using the ''checkValidity=2L'' - argument, to attempt zero-width buffer repair if invalid geometries are found. The - previous default (FALSE, now ''0L'') is fastest and used for ''GEOS'' < 3.7.2, but - will not warn users of possible problems before the failure of topological operations - that previously succeeded. From ''GEOS'' 3.8.0, repair of geometries may also be - attempted using ''gMakeValid()'', which may, however, return a collection of geometries - of different types.' - authors: - - family-names: Bivand - given-names: Roger - email: Roger.Bivand@nhh.no - orcid: https://orcid.org/0000-0003-2392-6140 - - family-names: Rundel - given-names: Colin - repository: https://CRAN.R-project.org/package=rgeos - repository-code: https://r-forge.r-project.org/projects/rgeos/ - url: https://trac.osgeo.org/geos/ - date-released: '2020-09-07' - contact: - - family-names: Bivand - given-names: Roger - email: Roger.Bivand@nhh.no - orcid: https://orcid.org/0000-0003-2392-6140 - identifiers: - - type: url - value: http://rgeos.r-forge.r-project.org/index.html - -# Parse date in another format - - Code - parsed - Output - cff-version: 1.2.0 - message: 'To cite package "basicdescdate" in publications use:' - type: software - license: GPL-3.0-only - title: 'basicdescdate: A Basic Description with Date' - version: 0.1.6 - abstract: A very basic description. Should parse without problems. I have a Date - authors: - - family-names: Basic - given-names: Marc - email: marcbasic@gmail.com - repository-code: https://github.com/basic/package - url: https://basic.github.io/package - date-released: '1999-01-01' - contact: - - family-names: Basic - given-names: Marc - email: marcbasic@gmail.com - -# Parsing many urls - - Code - parsed - Output - cff-version: 1.2.0 - message: 'To cite package "manyurls" in publications use:' - type: software - license: GPL-3.0-only - title: 'manyurls: A lot of urls' - version: 0.1.6 - abstract: This package has many urls. Specifically, 1 Bug Reports and 6 URLs. Expected - is to have 1 repository-code, 1 url and 3 URLs, since there is 1 duplicate and 1 - invalid url. - authors: - - family-names: Basic - given-names: Marc - email: marcbasic@gmail.com - repository-code: https://github.com/test/package - url: https://test.github.io/package/ - contact: - - family-names: Basic - given-names: Marc - email: marcbasic@gmail.com - identifiers: - - type: url - value: https://r-forge.r-project.org/projects/test/ - - type: url - value: http://google.ru - - type: url - value: https://gitlab.com/r-packages/behaviorchange - -# Parsing Gitlab - - Code - parsed - Output - cff-version: 1.2.0 - message: 'To cite package "codemetar" in publications use:' - type: software - license: GPL-3.0-only - title: 'codemetar: Generate ''CodeMeta'' Metadata for R Packages' - version: 0.1.6 - abstract: The 'Codemeta' Project defines a 'JSON-LD' format for describing software - metadata, as detailed at . This package provides utilities - to generate, parse, and modify 'codemeta.json' files automatically for R packages, - as well as tools and examples for working with 'codemeta.json' 'JSON-LD' more generally. - authors: - - family-names: Boettiger - given-names: Carl - email: cboettig@gmail.com - orcid: https://orcid.org/0000-0002-1642-628X - - family-names: Salmon - given-names: Maëlle - orcid: https://orcid.org/0000-0002-2815-0399 - repository: https://CRAN.R-project.org/package=codemetar - repository-code: https://gitlab.com/ninijay/methoden - url: https://ropensci.github.io/codemetar - contact: - - family-names: Boettiger - given-names: Carl - email: cboettig@gmail.com - orcid: https://orcid.org/0000-0002-1642-628X - keywords: - - metadata - - codemeta - - ropensci - - citation - - credit - - linked-data - -# Parsing many persons - - Code - parsed - Output - cff-version: 1.2.0 - message: 'To cite package "manypersons" in publications use:' - type: software - license: GPL-3.0-only - title: 'manypersons: A lot of persons' - version: 0.1.6 - abstract: Overkill desc with many persons. Try this - authors: - - family-names: Hernangómez - given-names: Diego - email: fake@gmail.com - orcid: https://orcid.org/0000-0001-8457-4658 - - family-names: Doe - given-names: Joe - affiliation: This One - country: ES - - family-names: Doe - given-names: Pepe - email: fake@gmail.com - - name: I am an entity - date-end: '2020-01-01' - repository-code: https://github.com/many/persons - url: https://many.github.io/persons - contact: - - family-names: Hernangómez - given-names: Diego - email: fake@gmail.com - orcid: https://orcid.org/0000-0001-8457-4658 - - name: I am an entity - date-end: '2020-01-01' - keywords: - - metadata - - cffr - - ropensci - - citation - - credit - - linked-data - - one - - two - -# Parsing wrong urls - - Code - parsed - Output - cff-version: 1.2.0 - message: 'To cite package "wrongurls" in publications use:' - type: software - license: MIT - title: 'wrongurls: Generate CodeMeta Metadata for R Packages' - version: 0.1.0 - abstract: Codemeta defines a 'JSON-LD' format for describing software metadata. This - package provides utilities to generate, parse, and modify codemeta.jsonld files - automatically for R packages. - authors: - - family-names: Boettiger - given-names: Carl - email: cboettig@gmail.com - orcid: https://orcid.org/0000-0002-1642-628X - url: https://httpbin.org/status/404 - contact: - - family-names: Boettiger - given-names: Carl - email: cboettig@gmail.com - orcid: https://orcid.org/0000-0002-1642-628X - keywords: - - metadata - - codemeta - - ropensci - - citation - - credit - - linked-data - identifiers: - - type: url - value: https://httpbin.org/status/429 - - type: url - value: https://www.github.es/ropensci/codemeta - -# Parsing two maintainers - - Code - parsed - Output - cff-version: 1.2.0 - message: 'To cite package "codemetar" in publications use:' - type: software - license: GPL-3.0-only - title: 'codemetar: Generate ''CodeMeta'' Metadata for R Packages' - version: 0.1.6 - abstract: The 'Codemeta' Project defines a 'JSON-LD' format for describing software - metadata, as detailed at . This package provides utilities - to generate, parse, and modify 'codemeta.json' files automatically for R packages, - as well as tools and examples for working with 'codemeta.json' 'JSON-LD' more generally. - authors: - - family-names: Ok - given-names: John - email: email@email.edu - - family-names: Doe - given-names: Jane - email: email2@email.edu - - family-names: Doo - given-names: Jane - repository: https://CRAN.R-project.org/package=codemetar - repository-code: https://github.com/ropensci/codemetar - url: https://ropensci.github.io/codemetar - contact: - - family-names: Ok - given-names: John - email: email@email.edu - - family-names: Doe - given-names: Jane - email: email2@email.edu - -# Parsing r-universe - - Code - parsed - Output - cff-version: 1.2.0 - message: 'To cite package "codemetar" in publications use:' - type: software - license: GPL-3.0-only - title: 'codemetar: Generate ''CodeMeta'' Metadata for R Packages' - version: 0.3.5 - abstract: The 'Codemeta' Project defines a 'JSON-LD' format for describing software - metadata, as detailed at . This package provides utilities - to generate, parse, and modify 'codemeta.json' files automatically for R packages, - as well as tools and examples for working with 'codemeta.json' 'JSON-LD' more generally. - authors: - - family-names: Boettiger - given-names: Carl - email: cboettig@gmail.com - orcid: https://orcid.org/0000-0002-1642-628X - - family-names: Salmon - given-names: Maëlle - orcid: https://orcid.org/0000-0002-2815-0399 - repository: https://ropensci.r-universe.dev - repository-code: https://github.com/ropensci/codemetar - url: https://docs.ropensci.org/codemetar/ - date-released: '2024-02-09' - contact: - - family-names: Boettiger - given-names: Carl - email: cboettig@gmail.com - orcid: https://orcid.org/0000-0002-1642-628X - keywords: - - metadata - - codemeta - - ropensci - - citation - - credit - - linked-data - -# Parsing Bioconductor - - Code - parsed - Output - cff-version: 1.2.0 - message: 'To cite package "GenomicRanges" in publications use:' - type: software - license: Artistic-2.0 - title: 'GenomicRanges: Representation and manipulation of genomic intervals' - version: 1.51.4 - abstract: The ability to efficiently represent and manipulate genomic annotations - and alignments is playing a central role when it comes to analyzing high-throughput - sequencing data (a.k.a. NGS data). The GenomicRanges package defines general purpose - containers for storing and manipulating genomic intervals and variables defined - along a genome. More specialized containers for representing and manipulating short - alignments against a reference genome, or a matrix-like summarization of an experiment, - are defined in the GenomicAlignments and SummarizedExperiment packages, respectively. - Both packages build on top of the GenomicRanges infrastructure. - authors: - - family-names: Aboyoun - given-names: Patrick - - family-names: Pagès - given-names: Hervé - email: hpages.on.github@gmail.com - - family-names: Lawrence - given-names: Michael - repository: https://bioconductor.org/ - repository-code: https://github.com/Bioconductor/GenomicRanges - url: https://bioconductor.org/packages/GenomicRanges - date-released: '2022-12-15' - contact: - - family-names: Pagès - given-names: Hervé - email: hpages.on.github@gmail.com - -# Parsing Posit Package Manager - - Code - parsed - Output - cff-version: 1.2.0 - message: 'To cite package "resmush" in publications use:' - type: software - license: MIT - title: 'resmush: Optimize and Compress Image Files with ''reSmush.it''' - version: 0.1.0 - abstract: Compress local and online images using the 'reSmush.it' API service . - authors: - - family-names: Hernangómez - given-names: Diego - email: diego.hernangomezherrero@gmail.com - orcid: https://orcid.org/0000-0001-8457-4658 - repository: https://CRAN.R-project.org/package=resmush - repository-code: https://github.com/dieghernan/resmush - url: https://dieghernan.github.io/resmush/ - date-released: '2024-02-02' - contact: - - family-names: Hernangómez - given-names: Diego - email: diego.hernangomezherrero@gmail.com - orcid: https://orcid.org/0000-0001-8457-4658 - keywords: - - r - - compress-images - - optimize-images - - resmushit - - api - -# Search package on CRAN - - Code - parsed - Output - cff-version: 1.2.0 - message: 'To cite package "ggplot2" in publications use:' - type: software - license: GPL-3.0-only - title: 'ggplot2: A Basic Description' - version: 0.1.6 - abstract: A very basic description. Should parse without problems. - authors: - - family-names: Basic - given-names: Marc - email: marcbasic@gmail.com - repository: https://CRAN.R-project.org/package=ggplot2 - repository-code: https://github.com/basic/package - url: https://basic.github.io/package - contact: - - family-names: Basic - given-names: Marc - email: marcbasic@gmail.com - diff --git a/tests/testthat/_snaps/cff_parse_citation.md b/tests/testthat/_snaps/cff_parse_citation.md deleted file mode 100644 index c2081654..00000000 --- a/tests/testthat/_snaps/cff_parse_citation.md +++ /dev/null @@ -1,284 +0,0 @@ -# Test full with CITATION and (option = author) - - Code - cffobj - Output - cff-version: 1.2.0 - message: 'To cite package "rgeos" in publications use:' - type: software - license: GPL-2.0-or-later - title: 'rgeos: Interface to Geometry Engine - Open Source (''GEOS'')' - version: 0.5-7 - abstract: 'Interface to Geometry Engine - Open Source (''GEOS'') using the C ''API'' - for topology operations on geometries. Please note that ''rgeos'' will be retired - by the end of 2023, plan transition to sf functions using ''GEOS'' at your earliest - convenience. The ''GEOS'' library is external to the package, and, when installing - the package from source, must be correctly installed first. Windows and Mac Intel - OS X binaries are provided on ''CRAN''. (''rgeos'' >= 0.5-1): Up to and including - ''GEOS'' 3.7.1, topological operations succeeded with some invalid geometries for - which the same operations fail from and including ''GEOS'' 3.7.2. The ''checkValidity='' - argument defaults and structure have been changed, from default FALSE to integer - default ''0L'' for ''GEOS'' < 3.7.2 (no check), ''1L'' ''GEOS'' >= 3.7.2 (check - and warn). A value of ''2L'' is also provided that may be used, assigned globally - using ''set_RGEOS_CheckValidity(2L)'', or locally using the ''checkValidity=2L'' - argument, to attempt zero-width buffer repair if invalid geometries are found. The - previous default (FALSE, now ''0L'') is fastest and used for ''GEOS'' < 3.7.2, but - will not warn users of possible problems before the failure of topological operations - that previously succeeded. From ''GEOS'' 3.8.0, repair of geometries may also be - attempted using ''gMakeValid()'', which may, however, return a collection of geometries - of different types.' - authors: - - family-names: Bivand - given-names: Roger - email: Roger.Bivand@nhh.no - orcid: https://orcid.org/0000-0003-2392-6140 - - family-names: Rundel - given-names: Colin - repository: https://CRAN.R-project.org/package=rgeos - repository-code: https://r-forge.r-project.org/projects/rgeos/ - url: https://trac.osgeo.org/geos/ - date-released: '2020-09-07' - contact: - - family-names: Bivand - given-names: Roger - email: Roger.Bivand@nhh.no - orcid: https://orcid.org/0000-0003-2392-6140 - references: - - type: manual - title: 'rgeos: Interface to Geometry Engine - Open Source (''GEOS'')' - authors: - - family-names: Bivand - given-names: Roger - email: Roger.Bivand@nhh.no - orcid: https://orcid.org/0000-0003-2392-6140 - - family-names: Rundel - given-names: Colin - year: '2020' - notes: R package version 0.5-7 - url: https://CRAN.R-project.org/package=rgeos - - type: article - title: 'RNeXML: A Package for Reading and Writing Richly Annotated Phylogenetic, - Character, and Trait Data in R' - authors: - - family-names: Boettiger - given-names: Carl - - family-names: Chamberlain - given-names: Scott - - family-names: Vos - given-names: Rutger - - family-names: Lapp - given-names: Hilmar - journal: Methods in Ecology and Evolution - year: '2016' - volume: '7' - doi: 10.1111/2041-210X.12469 - start: '352' - end: '357' - - type: book - title: 'ggplot2: Elegant Graphics for Data Analysis' - authors: - - family-names: Wickham - given-names: Hadley - publisher: - name: Springer-Verlag New York - year: '2016' - isbn: 978-3-319-24277-4 - url: https://ggplot2.tidyverse.org - identifiers: - - type: url - value: http://rgeos.r-forge.r-project.org/index.html - -# Parsed several citations - - Code - citobj - Output - - type: manual - title: 'rgeos: Interface to Geometry Engine - Open Source (''GEOS'')' - authors: - - family-names: Bivand - given-names: Roger - email: Roger.Bivand@nhh.no - orcid: https://orcid.org/0000-0003-2392-6140 - - family-names: Rundel - given-names: Colin - year: '2020' - notes: R package version 0.5-7 - url: https://CRAN.R-project.org/package=rgeos - - type: article - title: 'RNeXML: A Package for Reading and Writing Richly Annotated Phylogenetic, - Character, and Trait Data in R' - authors: - - family-names: Boettiger - given-names: Carl - - family-names: Chamberlain - given-names: Scott - - family-names: Vos - given-names: Rutger - - family-names: Lapp - given-names: Hilmar - journal: Methods in Ecology and Evolution - year: '2016' - volume: '7' - doi: 10.1111/2041-210X.12469 - start: '352' - end: '357' - - type: book - title: 'ggplot2: Elegant Graphics for Data Analysis' - authors: - - family-names: Wickham - given-names: Hadley - publisher: - name: Springer-Verlag New York - year: '2016' - isbn: 978-3-319-24277-4 - url: https://ggplot2.tidyverse.org - -# Add wrong field to citation - - Code - cffobj - Output - cff-version: 1.2.0 - message: If you use this software, please cite it using these metadata. - title: My Research Software - authors: - - family-names: Doe - given-names: John - references: - - type: manual - title: favoritefood is not valid on cff schema - authors: - - family-names: Smith - given-names: Jane - -# Fix wrong orcid - - Code - cffobj - Output - cff-version: 1.2.0 - message: If you use this software, please cite it using these metadata. - title: My Research Software - authors: - - family-names: Doe - given-names: John - references: - - type: manual - title: Wrong orcid fixed by cffr - authors: - - family-names: Smith - given-names: Jane - orcid: https://orcid.org/0000-0000-0000-306X - -# Several identifiers and duplicates - - Code - cffobj - Output - cff-version: 1.2.0 - message: If you use this software, please cite it using these metadata. - title: My Research Software - authors: - - family-names: Doe - given-names: John - references: - - type: manual - title: A Language and Environment for Statistical Computing - authors: - - name: R Core Team - year: '2022' - url: https://www.R-project.org/ - doi: 10.5281/zenodo.5366600 - identifiers: - - type: doi - value: 10.5281/zenodo.5366601 - - type: doi - value: 10.5281/zenodo.5366602 - - type: url - value: https://google.com/ - -# Test keywords and urls - - Code - cffobj - Output - cff-version: 1.2.0 - message: If you use this software, please cite it using these metadata. - title: My Research Software - authors: - - family-names: Doe - given-names: John - references: - - type: manual - title: A Language and Environment for Statistical Computing - authors: - - name: R Core Team - year: '2022' - url: https://www.R-project.org/ - keywords: - - Some - - random keywords - - in - - here - identifiers: - - type: url - value: https://google.com/ - -# Parse persons on CITATION - - Code - bibparsed - Output - type: manual - title: A Language and Environment for Statistical Computing - authors: - - name: R Core Team - year: '2021' - contact: - - family-names: name - given-names: A - - family-names: contact - given-names: A - conference: - name: A conference - address: A location - database-provider: - name: Database provider - editors: - - family-names: editor - given-names: A - - name: Ben and Jerry - editors-series: - - family-names: editor series - given-names: An - - name: Another - publisher: - name: A publisher - recipients: - - family-names: recipient - given-names: A - senders: - - name: A Sender - - family-names: Sender - given-names: Another - translators: - - family-names: one - given-names: Translator - - family-names: two - given-names: Translator - -# Test inputs - - Code - bibparsed - Output - type: book - title: Test - authors: - - family-names: Jean - given-names: Billy - year: '2021' - publisher: - name: Random House - diff --git a/tests/testthat/_snaps/cff_parse_person.md b/tests/testthat/_snaps/cff_parse_person.md deleted file mode 100644 index 648f980e..00000000 --- a/tests/testthat/_snaps/cff_parse_person.md +++ /dev/null @@ -1,72 +0,0 @@ -# Parse one person - - Code - cff_parse_person(p) - Output - family-names: person - given-names: one - -# Parse several persons - - Code - cff_parse_person(p) - Output - - family-names: person - given-names: one - - family-names: human - given-names: another - - family-names: more - given-names: and one - -# Parse bibtex persons - - Code - cff_parse_person_bibtex(s) - Output - family-names: Wright - given-names: Frank Edwin - name-suffix: III - ---- - - Code - cff_parse_person_bibtex(s) - Output - - family-names: person - given-names: A - - name: another - - family-names: one - given-names: Another - -# Parse bibtex persons with masks - - Code - cff_parse_person_bibtex(s) - Output - - name: Elephant - - name: Castle - ---- - - Code - cff_parse_person_bibtex(s) - Output - name: Elephant and Castle - ---- - - Code - cff_parse_person_bibtex(s) - Output - - name: Elephant and Castle - - name: this - - name: Ltd. - ---- - - Code - cff_parse_person_bibtex(s) - Output - - name: Elephant and Castle - - name: this AND Ltd. - diff --git a/tests/testthat/_snaps/cff_read.md b/tests/testthat/_snaps/cff_read.md index 435bfce9..b6e4e4be 100644 --- a/tests/testthat/_snaps/cff_read.md +++ b/tests/testthat/_snaps/cff_read.md @@ -1,1709 +1,77 @@ -# Walk trough full lifecycle +# Test errors on cff_read Code - print_snapshot("Read object", read) - Output - - - ## Read object - - cff-version: 1.2.0 - message: If you use this software, please cite it as below. - abstract: This is an awesome piece of research software! - authors: - - family-names: Real Person - given-names: One Truly - name-particle: van der - name-suffix: IV - alias: Citey - affiliation: Excellent University, Niceplace, Arcadia - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - commit: 156a04c74a8a79d40c5d705cddf9d36735feab4d - contact: - - family-names: Real Person - given-names: One Truly - name-particle: van der - name-suffix: IV - alias: Citey - affiliation: Excellent University, Niceplace, Arcadia - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - date-released: '2017-12-11' - doi: 10.5281/zenodo.1003150 - identifiers: - - type: doi - value: 10.5281/zenodo.1003150 - - type: swh - value: swh:1:rel:99f6850374dc6597af01bd0ee1d3fc0699301b9f - - type: url - value: https://example.com - - type: other - value: other-schema://abcd.1234.efgh.5678 - keywords: - - One - - Two - - Three - - '4' - license: CC-BY-SA-4.0 - license-url: https://spdx.org/licenses/CC-BY-SA-4.0.html#licenseText - repository: https://www.example.com/foo/?bar=baz&inga=42&quux - repository-code: http://foo.com/blah_(wikipedia)_blah#cite-1 - repository-artifact: https://files.pythonhosted.org/packages/0a/84/10507b69a07768bc16981184b4d147a0fc84b71fbf35c03bafc8dcced8e1/cffconvert-1.3.3.tar.gz - title: Citation File Format 1.0.0 - type: software - url: http://userid:password@example.com:8080/ - version: 1.0.0 - preferred-citation: - type: book - title: Book Title - abbreviation: Abbr - abstract: Description of the book. - collection-doi: 10.5281/zenodo.1003150 - collection-title: Collection Title - collection-type: Collection Type - commit: 156a04c74a8a79d40c5d705cddf9d36735feab4d - copyright: 2017 Stephan Druskat - data-type: Data Type - database: Database - date-accessed: '2017-10-31' - date-downloaded: '2017-10-31' - date-released: '2017-10-31' - date-published: '2017-10-31' - department: Department - doi: 10.5281/zenodo.1003150 - edition: 2nd edition - end: '456' - entry: Chapter 9 - filename: book.zip - format: Printed book - identifiers: - - type: doi - value: 10.5281/zenodo.1003150 - - type: swh - value: swh:1:rel:99f6850374dc6597af01bd0ee1d3fc0699301b9f - - type: url - value: https://example.com - - type: other - value: other-schema://abcd.1234.efgh.5678 - isbn: 978-1-89183-044-0 - issn: 1234-543X - issue: '123' - issue-date: December - issue-title: Special Issue on Software Citation - journal: PeerJ - keywords: - - Software - - Citation - languages: - - aaa - - zu - license: Apache-2.0 - license-url: https://spdx.org/licenses/Apache-2.0.html#licenseText - loc-start: '14' - loc-end: '54' - medium: hardcover book - month: '3' - nihmsid: Don't know what format a NIHMSID is in - notes: A field for general notes about the reference, usable in other formats such - as BibTeX. - number: A general-purpose field for accession numbers, cf. the specifications for - examples. - number-volumes: '7' - pages: '765' - patent-states: - - Germany - - ROI - - 'but also for example US states, such as:' - - IL - - RI - pmcid: PMC1234567 - repository: http://code.google.com/events/#&product=browser - repository-code: http://142.42.1.1:8080/ - repository-artifact: https://files.pythonhosted.org/packages/0a/84/10507b69a07768bc16981184b4d147a0fc84b71fbf35c03bafc8dcced8e1/cffconvert-1.3.3.tar.gz - scope: Cite this book if you want to reference the general concepts implemented - in Citation File Format 1.0.0. - section: Chapter 2 - "Reference keys" - status: advance-online - start: '123' - thesis-type: Doctoral dissertation - url: http://j.mp - version: 0.0.1423-BETA - volume: '2' - volume-title: Advances in Software Citation - year: '2017' - year-original: '2012' - conference: - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - authors: - - family-names: Real Person - given-names: One Truly - name-particle: van der - name-suffix: IV - alias: Citey - affiliation: Excellent University, Niceplace, Arcadia - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - contact: - - family-names: Real Person - given-names: One Truly - name-particle: van der - name-suffix: IV - alias: Citey - affiliation: Excellent University, Niceplace, Arcadia - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - database-provider: - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - editors: - - family-names: Real Person - given-names: One Truly - name-particle: van der - name-suffix: IV - alias: Citey - affiliation: Excellent University, Niceplace, Arcadia - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - editors-series: - - family-names: Real Person - given-names: One Truly - name-particle: van der - name-suffix: IV - alias: Citey - affiliation: Excellent University, Niceplace, Arcadia - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - institution: - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - location: - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - publisher: - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - recipients: - - family-names: Real Person - given-names: One Truly - name-particle: van der - name-suffix: IV - alias: Citey - affiliation: Excellent University, Niceplace, Arcadia - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - senders: - - family-names: Real Person - given-names: One Truly - name-particle: van der - name-suffix: IV - alias: Citey - affiliation: Excellent University, Niceplace, Arcadia - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - translators: - - family-names: Real Person - given-names: One Truly - name-particle: van der - name-suffix: IV - alias: Citey - affiliation: Excellent University, Niceplace, Arcadia - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - references: - - type: book - title: Book Title - abbreviation: Abbr - abstract: Description of the book. - collection-doi: 10.5281/zenodo.1003150 - collection-title: Collection Title - collection-type: Collection Type - commit: 156a04c74a8a79d40c5d705cddf9d36735feab4d - copyright: 2017 Stephan Druskat - data-type: Data Type - database: Database - date-accessed: '2017-10-31' - date-downloaded: '2017-10-31' - date-released: '2017-10-31' - date-published: '2017-10-31' - department: Department - doi: 10.5281/zenodo.1003150 - edition: 2nd edition - end: '123' - entry: Chapter 9 - filename: book.zip - format: Printed book - identifiers: - - type: doi - value: 10.5281/zenodo.1003150 - - type: swh - value: swh:1:rel:99f6850374dc6597af01bd0ee1d3fc0699301b9f - - type: url - value: https://example.com - - type: other - value: other-schema://abcd.1234.efgh.5678 - isbn: 978-1-89183-044-0 - issn: 1234-543X - issue: '123' - issue-date: December - issue-title: Special Issue on Software Citation - journal: PeerJ - keywords: - - Software - - Citation - languages: - - aaa - - zu - license: Apache-2.0 - license-url: https://spdx.org/licenses/Apache-2.0.html#licenseText - loc-start: '14' - loc-end: '54' - medium: hardcover book - month: '3' - nihmsid: Don't know what format a NIHMSID is in - notes: A field for general notes about the reference, usable in other formats such - as BibTeX. - number: A general-purpose field for accession numbers, cf. the specifications for - examples. - number-volumes: '7' - pages: '765' - patent-states: - - Germany - - ROI - - 'but also for example US states, such as:' - - IL - - RI - pmcid: PMC1234567 - repository: http://code.google.com/events/#&product=browser - repository-code: http://142.42.1.1:8080/ - repository-artifact: https://files.pythonhosted.org/packages/0a/84/10507b69a07768bc16981184b4d147a0fc84b71fbf35c03bafc8dcced8e1/cffconvert-1.3.3.tar.gz - scope: Cite this book if you want to reference the general concepts implemented - in Citation File Format 1.0.0. - section: Chapter 2 - "Reference keys" - status: advance-online - start: '123' - thesis-type: Doctoral dissertation - url: http://j.mp - version: 0.0.1423-BETA - volume: '2' - volume-title: Advances in Software Citation - year: '2017' - year-original: '2012' - conference: - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - authors: - - family-names: Real Person - given-names: One Truly - name-particle: van der - name-suffix: IV - alias: Citey - affiliation: Excellent University, Niceplace, Arcadia - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - contact: - - family-names: Real Person - given-names: One Truly - name-particle: van der - name-suffix: IV - alias: Citey - affiliation: Excellent University, Niceplace, Arcadia - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - database-provider: - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - editors: - - family-names: Real Person - given-names: One Truly - name-particle: van der - name-suffix: IV - alias: Citey - affiliation: Excellent University, Niceplace, Arcadia - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - editors-series: - - family-names: Real Person - given-names: One Truly - name-particle: van der - name-suffix: IV - alias: Citey - affiliation: Excellent University, Niceplace, Arcadia - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - institution: - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - location: - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - publisher: - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - recipients: - - family-names: Real Person - given-names: One Truly - name-particle: van der - name-suffix: IV - alias: Citey - affiliation: Excellent University, Niceplace, Arcadia - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - senders: - - family-names: Real Person - given-names: One Truly - name-particle: van der - name-suffix: IV - alias: Citey - affiliation: Excellent University, Niceplace, Arcadia - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - translators: - - family-names: Real Person - given-names: One Truly - name-particle: van der - name-suffix: IV - alias: Citey - affiliation: Excellent University, Niceplace, Arcadia - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - - --- + cff_read(c("abcde", "b")) + Condition + Error in `cff_read()`: + ! Use a single value, `path` has length 2 --- Code - print_snapshot("Modify object", modify) - Output - - - ## Modify object - - cff-version: 1.2.0 - message: If you use this software, please cite it as below. - type: software - license: CC-BY-SA-4.0 - title: A new title - version: 1.0.0 - doi: 10.5281/zenodo.1003150 - abstract: This is an awesome piece of research software! - authors: - - family-names: Real Person - given-names: One Truly - name-particle: van der - name-suffix: IV - alias: Citey - affiliation: Excellent University, Niceplace, Arcadia - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - preferred-citation: - type: book - title: Book Title - abbreviation: Abbr - abstract: Description of the book. - collection-doi: 10.5281/zenodo.1003150 - collection-title: Collection Title - collection-type: Collection Type - commit: 156a04c74a8a79d40c5d705cddf9d36735feab4d - copyright: 2017 Stephan Druskat - data-type: Data Type - database: Database - date-accessed: '2017-10-31' - date-downloaded: '2017-10-31' - date-released: '2017-10-31' - date-published: '2017-10-31' - department: Department - doi: 10.5281/zenodo.1003150 - edition: 2nd edition - end: '456' - entry: Chapter 9 - filename: book.zip - format: Printed book - identifiers: - - type: doi - value: 10.5281/zenodo.1003150 - - type: swh - value: swh:1:rel:99f6850374dc6597af01bd0ee1d3fc0699301b9f - - type: url - value: https://example.com - - type: other - value: other-schema://abcd.1234.efgh.5678 - isbn: 978-1-89183-044-0 - issn: 1234-543X - issue: '123' - issue-date: December - issue-title: Special Issue on Software Citation - journal: PeerJ - keywords: - - Software - - Citation - languages: - - aaa - - zu - license: Apache-2.0 - license-url: https://spdx.org/licenses/Apache-2.0.html#licenseText - loc-start: '14' - loc-end: '54' - medium: hardcover book - month: '3' - nihmsid: Don't know what format a NIHMSID is in - notes: A field for general notes about the reference, usable in other formats such - as BibTeX. - number: A general-purpose field for accession numbers, cf. the specifications for - examples. - number-volumes: '7' - pages: '765' - patent-states: - - Germany - - ROI - - 'but also for example US states, such as:' - - IL - - RI - pmcid: PMC1234567 - repository: http://code.google.com/events/#&product=browser - repository-code: http://142.42.1.1:8080/ - repository-artifact: https://files.pythonhosted.org/packages/0a/84/10507b69a07768bc16981184b4d147a0fc84b71fbf35c03bafc8dcced8e1/cffconvert-1.3.3.tar.gz - scope: Cite this book if you want to reference the general concepts implemented - in Citation File Format 1.0.0. - section: Chapter 2 - "Reference keys" - status: advance-online - start: '123' - thesis-type: Doctoral dissertation - url: http://j.mp - version: 0.0.1423-BETA - volume: '2' - volume-title: Advances in Software Citation - year: '2017' - year-original: '2012' - conference: - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - authors: - - family-names: Real Person - given-names: One Truly - name-particle: van der - name-suffix: IV - alias: Citey - affiliation: Excellent University, Niceplace, Arcadia - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - contact: - - family-names: Real Person - given-names: One Truly - name-particle: van der - name-suffix: IV - alias: Citey - affiliation: Excellent University, Niceplace, Arcadia - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - database-provider: - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - editors: - - family-names: Real Person - given-names: One Truly - name-particle: van der - name-suffix: IV - alias: Citey - affiliation: Excellent University, Niceplace, Arcadia - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - editors-series: - - family-names: Real Person - given-names: One Truly - name-particle: van der - name-suffix: IV - alias: Citey - affiliation: Excellent University, Niceplace, Arcadia - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - institution: - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - location: - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - publisher: - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - recipients: - - family-names: Real Person - given-names: One Truly - name-particle: van der - name-suffix: IV - alias: Citey - affiliation: Excellent University, Niceplace, Arcadia - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - senders: - - family-names: Real Person - given-names: One Truly - name-particle: van der - name-suffix: IV - alias: Citey - affiliation: Excellent University, Niceplace, Arcadia - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - translators: - - family-names: Real Person - given-names: One Truly - name-particle: van der - name-suffix: IV - alias: Citey - affiliation: Excellent University, Niceplace, Arcadia - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - repository: https://www.example.com/foo/?bar=baz&inga=42&quux - repository-artifact: https://files.pythonhosted.org/packages/0a/84/10507b69a07768bc16981184b4d147a0fc84b71fbf35c03bafc8dcced8e1/cffconvert-1.3.3.tar.gz - repository-code: http://foo.com/blah_(wikipedia)_blah#cite-1 - url: http://userid:password@example.com:8080/ - date-released: '2017-12-11' - contact: - - family-names: Real Person - given-names: One Truly - name-particle: van der - name-suffix: IV - alias: Citey - affiliation: Excellent University, Niceplace, Arcadia - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - keywords: - - One - - Two - - Three - - '4' - references: - - type: book - title: Book Title - abbreviation: Abbr - abstract: Description of the book. - collection-doi: 10.5281/zenodo.1003150 - collection-title: Collection Title - collection-type: Collection Type - commit: 156a04c74a8a79d40c5d705cddf9d36735feab4d - copyright: 2017 Stephan Druskat - data-type: Data Type - database: Database - date-accessed: '2017-10-31' - date-downloaded: '2017-10-31' - date-released: '2017-10-31' - date-published: '2017-10-31' - department: Department - doi: 10.5281/zenodo.1003150 - edition: 2nd edition - end: '123' - entry: Chapter 9 - filename: book.zip - format: Printed book - identifiers: - - type: doi - value: 10.5281/zenodo.1003150 - - type: swh - value: swh:1:rel:99f6850374dc6597af01bd0ee1d3fc0699301b9f - - type: url - value: https://example.com - - type: other - value: other-schema://abcd.1234.efgh.5678 - isbn: 978-1-89183-044-0 - issn: 1234-543X - issue: '123' - issue-date: December - issue-title: Special Issue on Software Citation - journal: PeerJ - keywords: - - Software - - Citation - languages: - - aaa - - zu - license: Apache-2.0 - license-url: https://spdx.org/licenses/Apache-2.0.html#licenseText - loc-start: '14' - loc-end: '54' - medium: hardcover book - month: '3' - nihmsid: Don't know what format a NIHMSID is in - notes: A field for general notes about the reference, usable in other formats such - as BibTeX. - number: A general-purpose field for accession numbers, cf. the specifications for - examples. - number-volumes: '7' - pages: '765' - patent-states: - - Germany - - ROI - - 'but also for example US states, such as:' - - IL - - RI - pmcid: PMC1234567 - repository: http://code.google.com/events/#&product=browser - repository-code: http://142.42.1.1:8080/ - repository-artifact: https://files.pythonhosted.org/packages/0a/84/10507b69a07768bc16981184b4d147a0fc84b71fbf35c03bafc8dcced8e1/cffconvert-1.3.3.tar.gz - scope: Cite this book if you want to reference the general concepts implemented - in Citation File Format 1.0.0. - section: Chapter 2 - "Reference keys" - status: advance-online - start: '123' - thesis-type: Doctoral dissertation - url: http://j.mp - version: 0.0.1423-BETA - volume: '2' - volume-title: Advances in Software Citation - year: '2017' - year-original: '2012' - conference: - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - authors: - - family-names: Real Person - given-names: One Truly - name-particle: van der - name-suffix: IV - alias: Citey - affiliation: Excellent University, Niceplace, Arcadia - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - contact: - - family-names: Real Person - given-names: One Truly - name-particle: van der - name-suffix: IV - alias: Citey - affiliation: Excellent University, Niceplace, Arcadia - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - database-provider: - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - editors: - - family-names: Real Person - given-names: One Truly - name-particle: van der - name-suffix: IV - alias: Citey - affiliation: Excellent University, Niceplace, Arcadia - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - editors-series: - - family-names: Real Person - given-names: One Truly - name-particle: van der - name-suffix: IV - alias: Citey - affiliation: Excellent University, Niceplace, Arcadia - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - institution: - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - location: - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - publisher: - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - recipients: - - family-names: Real Person - given-names: One Truly - name-particle: van der - name-suffix: IV - alias: Citey - affiliation: Excellent University, Niceplace, Arcadia - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - senders: - - family-names: Real Person - given-names: One Truly - name-particle: van der - name-suffix: IV - alias: Citey - affiliation: Excellent University, Niceplace, Arcadia - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - translators: - - family-names: Real Person - given-names: One Truly - name-particle: van der - name-suffix: IV - alias: Citey - affiliation: Excellent University, Niceplace, Arcadia - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - - name: Entity Project Team Conference entity - address: 22 Acacia Avenue - city: Citationburgh - region: Renfrewshire - post-code: C13 7X7 - country: GB - orcid: https://orcid.org/0000-0001-2345-6789 - email: project@entity.com - tel: +44(0)141-323 4567 - fax: +44(0)141-323 45678 - website: https://www.entity-project-team.io - date-start: '2017-01-01' - date-end: '2017-01-31' - location: The team garage - commit: 156a04c74a8a79d40c5d705cddf9d36735feab4d - identifiers: - - type: doi - value: 10.5281/zenodo.1003150 - - type: swh - value: swh:1:rel:99f6850374dc6597af01bd0ee1d3fc0699301b9f - - type: url - value: https://example.com - - type: other - value: other-schema://abcd.1234.efgh.5678 - license-url: https://spdx.org/licenses/CC-BY-SA-4.0.html#licenseText - - --- + cff_read("abcde") + Condition + Error in `cff_read()`: + ! 'abcde' does not exist. Check the '.' directory -# Fuzzy matching of keys on cff +# cff_read citation.cff Code - print_snapshot("Fuzzy keys", cffobj) + cff_read_cff_citation("a") + Condition + Error in `cff_read_cff_citation()`: + ! 'a' does not exist. Check the '.' directory + +# cff_read DESCRIPTION + + Code + cff_read_description("a") + Condition + Error in `cff_read_description()`: + ! 'a' does not exist. Check the '.' directory + +# cff_read bib + + Code + cff_read_bib("a") + Condition + Error in `cff_read_bib()`: + ! 'a' does not exist. Check the '.' directory + +--- + + Code + d Output - - - ## Fuzzy keys - - title: a - cff-version: 1.2.0 - version: '200' + type: article + title: 'cffr: Generate Citation File Format Metadata for R Packages' authors: - - family-names: a - given-names: b - message: Fix my keys - - --- + - family-names: Hernangómez + given-names: Diego + year: '2021' + journal: Journal of Open Source Software + publisher: + name: The Open Journal + volume: '6' + issue: '67' + doi: 10.21105/joss.03900 + url: https://doi.org/10.21105/joss.03900 + copyright: All rights reserved + notes: 'Publisher: The Open Journal' + start: '3900' + +# cff_read citation messages + + Code + cff_read_citation("a") + Condition + Error in `cff_read_citation()`: + ! 'a' does not exist. Check the '.' directory + +--- + + Code + s <- cff_read(f, meta = "aa") + Message + ! `meta` should be "NULL" or a object not a string. Using `meta = NULL` diff --git a/tests/testthat/_snaps/cff_from_bibtex.md b/tests/testthat/_snaps/cff_read_bib_text.md similarity index 53% rename from tests/testthat/_snaps/cff_from_bibtex.md rename to tests/testthat/_snaps/cff_read_bib_text.md index 65d0bb2a..44a59827 100644 --- a/tests/testthat/_snaps/cff_from_bibtex.md +++ b/tests/testthat/_snaps/cff_read_bib_text.md @@ -1,26 +1,22 @@ -# Read from file +# Errors and messages Code - d - Output - type: article - title: 'cffr: Generate Citation File Format Metadata for R Packages' - authors: - - family-names: Hernangómez - given-names: Diego - year: '2021' - journal: Journal of Open Source Software - publisher: - name: The Open Journal - volume: '6' - issue: '67' - doi: 10.21105/joss.03900 - url: https://doi.org/10.21105/joss.03900 - copyright: All rights reserved - notes: 'Publisher: The Open Journal' - start: '3900' - -# From Bibtex entries + cff_read_bib_text(a_cff) + Condition + Error in `cff_read_bib_text()`: + ! `x` should be a , not a . + +--- + + Code + cff_read_bib_text("a bad line") + Message + ! `x` doesn't look as a BibTeX entry. Check the results. + Condition + Error: + ! Invalid bib file + +# Read lines Code list @@ -45,3 +41,11 @@ notes: This is a full MISC entry medium: Handed out at O'Hare +--- + + Code + fromfile <- cff_read_bib_text(tmpbib) + Message + ! `x` seems to be a ".bib" file, not a BibTeX entry. + i Reading `x` with `cffr:cff_read_bib()` + diff --git a/tests/testthat/_snaps/cff_write_misc.md b/tests/testthat/_snaps/cff_write_misc.md new file mode 100644 index 00000000..3204469f --- /dev/null +++ b/tests/testthat/_snaps/cff_write_misc.md @@ -0,0 +1,16 @@ +# Errors + + Code + cff_write_bib(1:4) + Condition + Error in `cff_write_bib()`: + ! `x` should be a object, not a object. + +# Errors citation + + Code + cff_write_citation(1:4) + Condition + Error in `cff_write_citation()`: + ! `x` should be a object, not a object. + diff --git a/tests/testthat/_snaps/cff_write_misc/CITAT_ION b/tests/testthat/_snaps/cff_write_misc/CITAT_ION new file mode 100644 index 00000000..e54d5050 --- /dev/null +++ b/tests/testthat/_snaps/cff_write_misc/CITAT_ION @@ -0,0 +1,16 @@ + +bibentry(bibtype = "Misc", + title = "My title", + author = person(given = "Fran", + family = "Pérez")) + +bibentry(bibtype = "Misc", + key = "basic:1999", + title = "basicdescdate: A Basic Description with Date", + author = person(given = "Marc", + family = "Basic", + email = "marcbasic@gmail.com"), + year = "1999", + url = "https://basic.github.io/package", + abstract = "A very basic description. Should parse without problems. I have a Date", + version = "0.1.6") diff --git a/tests/testthat/_snaps/cff_write_misc/append.bib b/tests/testthat/_snaps/cff_write_misc/append.bib new file mode 100644 index 00000000..999066a3 --- /dev/null +++ b/tests/testthat/_snaps/cff_write_misc/append.bib @@ -0,0 +1,15 @@ +@Misc{, + title = {My title}, + author = {Fran Herrero}, +} +@Misc{key2, + title = {Another title}, + author = {Ian Henderson}, +} +@Misc{basic, + title = {basicdesc: A Basic Description}, + author = {Marc Basic}, + url = {https://basic.github.io/package}, + abstract = {A very basic description. Should parse without problems.}, + version = {0.1.6}, +} diff --git a/tests/testthat/_snaps/write_bib/ascii.bib b/tests/testthat/_snaps/cff_write_misc/ascii.bib similarity index 100% rename from tests/testthat/_snaps/write_bib/ascii.bib rename to tests/testthat/_snaps/cff_write_misc/ascii.bib diff --git a/tests/testthat/_snaps/write_bib/noext.bib b/tests/testthat/_snaps/cff_write_misc/noext.bib similarity index 100% rename from tests/testthat/_snaps/write_bib/noext.bib rename to tests/testthat/_snaps/cff_write_misc/noext.bib diff --git a/tests/testthat/_snaps/deprecated.md b/tests/testthat/_snaps/deprecated.md index ac22bc72..225a91d2 100644 --- a/tests/testthat/_snaps/deprecated.md +++ b/tests/testthat/_snaps/deprecated.md @@ -5,5 +5,98 @@ Condition Warning: `cff_extract_to_bibtex()` was deprecated in cffr 0.5.0. - i Please use `cff_to_bibentry()` instead. + i Function renamed, use `as_bibentry()` instead. + +# cff_to_bibtex + + Code + old1 <- cff_to_bibtex(a_cff) + Condition + Warning: + `cff_extract_to_bibtex()` was deprecated in cffr 1.0.0. + i Function renamed, use `as_bibentry()` instead. + +# cff_from_bibtex + + Code + ffile <- cff_from_bibtex(x2) + Condition + Warning: + `cff_from_bibtex()` was deprecated in cffr 1.0.0. + i Please use `cff_read_bib()` instead. + +--- + + Code + flines <- cff_from_bibtex(x) + Condition + Warning: + `cff_from_bibtex()` was deprecated in cffr 1.0.0. + i Please use `cff_read_bib_text()` instead. + +# write_bib + + Code + write_bib(bib, tmp, verbose = FALSE) + Condition + Warning: + `write_bib()` was deprecated in cffr 1.0.0. + i Please use `cff_write_bib()` instead. + +--- + + Code + cat(readLines(tmp), sep = "\n") + Output + @Misc{, + title = {My title}, + author = {Fran Pérez}, + } + +# write_citation + + Code + write_citation(bib, tmp, verbose = FALSE) + Condition + Warning: + `write_citation()` was deprecated in cffr 1.0.0. + i Please use `cff_write_citation()` instead. + +--- + + Code + cat(readLines(tmp), sep = "\n") + Output + + bibentry(bibtype = "Misc", + title = "My title", + author = person(given = "Fran", + family = "Pérez")) + +# cff_parse_person + + Code + pend <- cff_parse_person(p) + Condition + Warning: + `cff_parse_person()` was deprecated in cffr 1.0.0. + i Please use `as_cff_person()` instead. + +# cff_parse_person_bibtex + + Code + pend <- cff_parse_person_bibtex(p) + Condition + Warning: + `cff_parse_person_bibtex()` was deprecated in cffr 1.0.0. + i Please use `as_cff_person()` instead. + +# cff_parse_citation + + Code + pend <- cff_parse_citation(p) + Condition + Warning: + `cff_parse_citation()` was deprecated in cffr 1.0.0. + i Please use `as_cff.bibentry()` instead. diff --git a/tests/testthat/_snaps/encoding.md b/tests/testthat/_snaps/encoding.md index dc322c5a..2361ac24 100644 --- a/tests/testthat/_snaps/encoding.md +++ b/tests/testthat/_snaps/encoding.md @@ -17,23 +17,24 @@ diseases, but applications could just as well originate from environmetrics, reliability engineering, econometrics, or social sciences. The package implements many typical outbreak detection procedures such as the (improved) Farrington algorithm, or the - negative binomial GLR-CUSUM method of Höhle and Paul (2008) . + negative binomial GLR-CUSUM method of Höhle and Paul (2008) . A novel CUSUM approach combining logistic and multinomial logistic modeling is also included. The package contains several real-world data sets, the ability to simulate outbreak data, and to visualize the results of the monitoring in a temporal, spatial or spatio-temporal fashion. A recent overview of the available monitoring procedures - is given by Salmon et al. (2016) . For the retrospective - analysis of epidemic spread, the package provides three endemic-epidemic modeling - frameworks with tools for visualization, likelihood inference, and simulation. hhh4() - estimates models for (multivariate) count time series following Paul and Held (2011) - and Meyer and Held (2014) . twinSIR() - models the susceptible-infectious-recovered (SIR) event history of a fixed population, - e.g, epidemics across farms or networks, as a multivariate point process as proposed - by Höhle (2009) . twinstim() estimates self-exciting - point process models for a spatio-temporal point pattern of infective events, e.g., - time-stamped geo-referenced surveillance data, as proposed by Meyer et al. (2012) - . A recent overview of the implemented space-time - modeling frameworks for epidemic phenomena is given by Meyer et al. (2017) . + is given by Salmon et al. (2016) . For the + retrospective analysis of epidemic spread, the package provides three endemic-epidemic + modeling frameworks with tools for visualization, likelihood inference, and simulation. + hhh4() estimates models for (multivariate) count time series following Paul and + Held (2011) and Meyer and Held (2014) . + twinSIR() models the susceptible-infectious-recovered (SIR) event history of a fixed + population, e.g, epidemics across farms or networks, as a multivariate point process + as proposed by Höhle (2009) . twinstim() + estimates self-exciting point process models for a spatio-temporal point pattern + of infective events, e.g., time-stamped geo-referenced surveillance data, as proposed + by Meyer et al. (2012) . A recent + overview of the implemented space-time modeling frameworks for epidemic phenomena + is given by Meyer et al. (2017) . authors: - family-names: Höhle given-names: Michael diff --git a/tests/testthat/_snaps/merge_desc_cit.md b/tests/testthat/_snaps/merge_desc_cit.md index 4476fa32..28dc3cec 100644 --- a/tests/testthat/_snaps/merge_desc_cit.md +++ b/tests/testthat/_snaps/merge_desc_cit.md @@ -806,23 +806,24 @@ diseases, but applications could just as well originate from environmetrics, reliability engineering, econometrics, or social sciences. The package implements many typical outbreak detection procedures such as the (improved) Farrington algorithm, or the - negative binomial GLR-CUSUM method of Höhle and Paul (2008) . + negative binomial GLR-CUSUM method of Höhle and Paul (2008) . A novel CUSUM approach combining logistic and multinomial logistic modeling is also included. The package contains several real-world data sets, the ability to simulate outbreak data, and to visualize the results of the monitoring in a temporal, spatial or spatio-temporal fashion. A recent overview of the available monitoring procedures - is given by Salmon et al. (2016) . For the retrospective - analysis of epidemic spread, the package provides three endemic-epidemic modeling - frameworks with tools for visualization, likelihood inference, and simulation. hhh4() - estimates models for (multivariate) count time series following Paul and Held (2011) - and Meyer and Held (2014) . twinSIR() - models the susceptible-infectious-recovered (SIR) event history of a fixed population, - e.g, epidemics across farms or networks, as a multivariate point process as proposed - by Höhle (2009) . twinstim() estimates self-exciting - point process models for a spatio-temporal point pattern of infective events, e.g., - time-stamped geo-referenced surveillance data, as proposed by Meyer et al. (2012) - . A recent overview of the implemented space-time - modeling frameworks for epidemic phenomena is given by Meyer et al. (2017) . + is given by Salmon et al. (2016) . For the + retrospective analysis of epidemic spread, the package provides three endemic-epidemic + modeling frameworks with tools for visualization, likelihood inference, and simulation. + hhh4() estimates models for (multivariate) count time series following Paul and + Held (2011) and Meyer and Held (2014) . + twinSIR() models the susceptible-infectious-recovered (SIR) event history of a fixed + population, e.g, epidemics across farms or networks, as a multivariate point process + as proposed by Höhle (2009) . twinstim() + estimates self-exciting point process models for a spatio-temporal point pattern + of infective events, e.g., time-stamped geo-referenced surveillance data, as proposed + by Meyer et al. (2012) . A recent + overview of the implemented space-time modeling frameworks for epidemic phenomena + is given by Meyer et al. (2017) . repository: https://CRAN.R-project.org/package=surveillance url: https://surveillance.R-Forge.R-project.org/ date-released: '2021-03-30' diff --git a/tests/testthat/_snaps/utils-persons.md b/tests/testthat/_snaps/utils-persons.md index 7e6b7143..a6d1a97f 100644 --- a/tests/testthat/_snaps/utils-persons.md +++ b/tests/testthat/_snaps/utils-persons.md @@ -3,358 +3,358 @@ Code unlist(res) Output - given family - "AA" "BB" + family-names given-names + "BB" "AA" --- Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - family - "AA" + name + "AA" --- Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - given family - "AA" "bb" + family-names given-names + "bb" "AA" --- Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - family - "aa" + name + "aa" --- Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - given von family - "AA" "bb" "CC" + family-names given-names name-particle + "CC" "AA" "bb" --- Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - given von family - "AA" "bb CC dd" "EE" + family-names given-names name-particle + "EE" "AA" "bb CC dd" --- Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - given von family - "AA bB" "cc" "dd" + family-names given-names name-particle + "dd" "AA bB" "cc" --- Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - given von family - "AA \\BBb" "cc" "dd" + family-names given-names name-particle + "dd" "AA \\BBb" "cc" --- Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - given von family - "AA bb" "cc" "DD" + family-names given-names name-particle + "DD" "AA bb" "cc" --- Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - given von family - "AA" "bb" "cc DD" + family-names given-names name-particle + "cc DD" "AA" "bb" --- Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - given family - "AA bb" "CC" + family-names given-names + "CC" "AA bb" # Testing with random names First von Last Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - given von family - "Jean" "de" "La Fontaine" + family-names given-names name-particle + "La Fontaine" "Jean" "de" --- Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - given family - "Diego" "Hernandez Sanz" + family-names given-names + "Hernandez Sanz" "Diego" --- Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - given family - "Juan Manuel" "Miramontes" + family-names given-names + "Miramontes" "Juan Manuel" --- Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - given family - "Juan Manuel" "Miramontes Garcia" + family-names given-names + "Miramontes Garcia" "Juan Manuel" --- Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - given von family - "Juan Manuel" "van" "Halen" + family-names given-names name-particle + "Halen" "Juan Manuel" "van" --- Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - given family - "Bosco" "de la Cruz y Ochoa" + family-names given-names + "de la Cruz y Ochoa" "Bosco" # Test von Last, First Code unlist(res) Output - given von family - "AA" "bb" "CC" + family-names given-names name-particle + "CC" "AA" "bb" --- Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - given von family - "aa" "bb" "CC" + family-names given-names name-particle + "CC" "aa" "bb" --- Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - given von family - "AA" "bb CC dd" "EE" + family-names given-names name-particle + "EE" "AA" "bb CC dd" --- Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - given family - "AA" "bb" + family-names given-names + "bb" "AA" --- Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - family - "BB" + name + "BB" # Test von Last, First with brackets, etc Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - given von family - "Ana" "de" "Armas" + family-names given-names name-particle + "Armas" "Ana" "de" --- Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - given family - "Ana" "de Armas" + family-names given-names + "de Armas" "Ana" --- Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - given family - "Ana" "de Armas, Aguero" + family-names given-names + "de Armas, Aguero" "Ana" --- Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - given family - "Ana Maria" "de Armas, Aguero" + family-names given-names + "de Armas, Aguero" "Ana Maria" # Test von Last, Jr, First Code unlist(res) Output - given von family jr - "AA" "bb" "CC" "XX" + family-names given-names name-particle name-suffix + "CC" "AA" "bb" "XX" --- Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - given family - "AA" "BB" + family-names given-names + "BB" "AA" --- Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - family jr - "BB" "AA" + name + "BB AA" # Test von Last, Jr, First with masking Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - given family jr - "Sammy" "Davis" "Jr" + family-names given-names name-suffix + "Davis" "Sammy" "Jr" --- Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - given family jr - "Sammy" "Davis, and" "Jr, another" + family-names given-names name-suffix + "Davis, and" "Sammy" "Jr, another" # Rest of cases Code unlist(res) Output - family + name "David, and, Jr, another, Sammy" # tames da beast Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - von family - "jean de la" "fontaine" + name + "jean de la fontaine" --- Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - given von family - "Jean" "de la" "fontaine" + family-names given-names name-particle + "fontaine" "Jean" "de la" --- Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - given von family - "Jean de" "la" "fontaine" + family-names given-names name-particle + "fontaine" "Jean de" "la" --- Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - von family - "jean" "de la fontaine" + name + "jean de la fontaine" --- Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - given family - "Jean de la" "fontaine" + family-names given-names + "fontaine" "Jean de la" --- Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - given family - "Jean De La" "Fontaine" + family-names given-names + "Fontaine" "Jean De La" --- Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - von family - "jean De la" "Fontaine" + name + "jean De la Fontaine" --- Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - given von family - "Jean" "de" "La Fontaine" + family-names given-names name-particle + "La Fontaine" "Jean" "de" --- Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - von family - "jean de la" "fontaine" + name + "jean de la fontaine" --- Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - given von family - "Jean" "de la" "fontaine" + family-names given-names name-particle + "fontaine" "Jean" "de la" --- Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - given family - "Jean" "De La Fontaine" + family-names given-names + "De La Fontaine" "Jean" --- Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - given von family - "Jean" "De la" "Fontaine" + family-names given-names name-particle + "Fontaine" "Jean" "De la" --- Code - unlist(as_person_bibtex(x)) + unlist(create_person_from_txt(x)) Output - given von family - "Jean" "de" "La Fontaine" + family-names given-names name-particle + "La Fontaine" "Jean" "de" diff --git a/tests/testthat/_snaps/write_bib.md b/tests/testthat/_snaps/write_bib.md deleted file mode 100644 index 8090ffd1..00000000 --- a/tests/testthat/_snaps/write_bib.md +++ /dev/null @@ -1,20 +0,0 @@ -# Try not writing - - Code - write_bib(bib) - Output - @Misc{, - title = {My title}, - author = {Fran Pérez}, - } - ---- - - Code - write_bib(bib, ascii = TRUE) - Output - @Misc{, - title = {My title}, - author = {Fran P{\'e}rez}, - } - diff --git a/tests/testthat/_snaps/write_bib/append.bib b/tests/testthat/_snaps/write_bib/append.bib deleted file mode 100644 index d0208a19..00000000 --- a/tests/testthat/_snaps/write_bib/append.bib +++ /dev/null @@ -1,8 +0,0 @@ -@Misc{, - title = {My title}, - author = {Fran Herrero}, -} -@Misc{key2, - title = {Another title}, - author = {Ian Henderson}, -} diff --git a/tests/testthat/_snaps/write_citation.md b/tests/testthat/_snaps/write_citation.md deleted file mode 100644 index aace09ca..00000000 --- a/tests/testthat/_snaps/write_citation.md +++ /dev/null @@ -1,35 +0,0 @@ -# Results can be parsed - - @InBook{vanderrealpersoniventityprojectteamconferenceentity:2017, - title = {Book Title}, - author = {One Truly {van der Real Person IV} and {Entity Project Team Conference entity}}, - year = {2017}, - month = {mar}, - journal = {PeerJ}, - publisher = {Entity Project Team Conference entity}, - address = {22 Acacia Avenue, Citationburgh, Renfrewshire, GB}, - editor = {One Truly {van der Real Person IV} and {Entity Project Team Conference entity}}, - series = {Collection Title}, - volume = {2}, - number = {123}, - pages = {123--456}, - doi = {10.5281/zenodo.1003150}, - isbn = {978-1-89183-044-0}, - issn = {1234-543X}, - url = {http://j.mp}, - note = {A field for general notes about the reference, usable in other formats such as BibTeX.}, - chapter = {Chapter 2 - "Reference keys"}, - edition = {2nd edition}, - howpublished = {Hardcover book}, - institution = {Entity Project Team Conference entity}, - keywords = {Software, Citation}, - abstract = {Description of the book.}, - date = {2017-10-31}, - file = {book.zip}, - issuetitle = {Special Issue on Software Citation}, - pagetotal = {765}, - urldate = {2017-10-31}, - version = {0.0.1423-BETA}, - translator = {van der Real Person, IV, One Truly and {Entity Project Team Conference entity}}, - } - diff --git a/tests/testthat/_snaps/write_citation/append b/tests/testthat/_snaps/write_citation/append deleted file mode 100644 index 1bc3229b..00000000 --- a/tests/testthat/_snaps/write_citation/append +++ /dev/null @@ -1,11 +0,0 @@ - -bibentry(bibtype = "Misc", - title = "My title", - author = person(given = "Fran", - family = "Herrero")) - -bibentry(bibtype = "Misc", - key = "key2", - title = "Another title", - author = person(given = "Ian", - family = "Henderson")) diff --git a/tests/testthat/_snaps/write_citation/noext b/tests/testthat/_snaps/write_citation/noext deleted file mode 100644 index 141b29d4..00000000 --- a/tests/testthat/_snaps/write_citation/noext +++ /dev/null @@ -1,5 +0,0 @@ - -bibentry(bibtype = "Misc", - title = "My title", - author = person(given = "Fran", - family = "Pérez")) diff --git a/tests/testthat/_snaps/bibtex-check-ruby.md b/tests/testthat/_snaps/xtra-check-bibtex-ruby.md similarity index 96% rename from tests/testthat/_snaps/bibtex-check-ruby.md rename to tests/testthat/_snaps/xtra-check-bibtex-ruby.md index 931ceb2e..4e11e51f 100644 --- a/tests/testthat/_snaps/bibtex-check-ruby.md +++ b/tests/testthat/_snaps/xtra-check-bibtex-ruby.md @@ -1,3 +1,14 @@ +# preferred-citation-book-missing + + Code + as_bibentry(x) + Message + x Can't convert to `bibentry()`: + i A bibentry of bibtype 'Book' has to specify the field: publisher + ! Returning "NULL" + Output + NULL + # preferred-citation-book Code @@ -91,7 +102,7 @@ Code toBibtex(bib) Output - @Article{hartmannwong, + @Article{hartmannwong:2020, title = {An image-based data-driven analysis of cellular architecture in a developing tissue}, author = {Jonas Hartmann and Mie Wong and Elisa Gallo and Darren Gilmour}, year = {2020}, diff --git a/tests/testthat/test-additional-authors.R b/tests/testthat/test-additional-authors.R deleted file mode 100644 index d20165bd..00000000 --- a/tests/testthat/test-additional-authors.R +++ /dev/null @@ -1,74 +0,0 @@ -test_that("Default roles", { - p <- system.file("examples/DESCRIPTION_no_URL", package = "cffr") - - cf <- cff_create(p, dependencies = FALSE) - - # Same as - cf2 <- cff_create(p, authors_roles = c("aut", "cre"), dependencies = FALSE) - expect_identical(cf, cf2) -}) - -test_that("Add new roles", { - p <- system.file("examples/DESCRIPTION_no_URL", package = "cffr") - - cf <- cff_create(p, dependencies = FALSE) - cf2 <- cff_create(p, - authors_roles = c("aut", "cre", "ctb"), - dependencies = FALSE - ) - - expect_gt(length(cf2$authors), length(cf$authors)) - expect_true(cff_validate(cf2, verbose = FALSE)) -}) - - -test_that("Default roles on write", { - p <- system.file("examples/DESCRIPTION_no_URL", package = "cffr") - - cf <- cff_create(p, dependencies = FALSE) - - # Same as - tmp <- tempfile(fileext = ".cff") - expect_silent( - cf2 <- cff_write(p, - authors_roles = c("aut", "cre"), dependencies = FALSE, - outfile = tmp, verbose = FALSE, validate = FALSE - ) - ) - - expect_identical(cf, cf2) -}) - -test_that("Add new roles", { - p <- system.file("examples/DESCRIPTION_no_URL", package = "cffr") - - cf <- cff_create(p, dependencies = FALSE) - cf2 <- cff_create(p, - authors_roles = c("aut", "cre", "ctb"), - dependencies = FALSE - ) - - expect_gt(length(cf2$authors), length(cf$authors)) - expect_true(cff_validate(cf2, verbose = FALSE)) -}) - -test_that("Add new roles on write", { - p <- system.file("examples/DESCRIPTION_no_URL", package = "cffr") - - cf_def <- cff_create(p) - cf <- cff_create(p, authors_roles = "ctb") - - expect_gt(length(cf$authors), length(cf_def$authors)) - - # Same as - tmp <- tempfile(fileext = ".cff") - expect_message( - cf2 <- cff_write(p, - authors_roles = "ctb", outfile = tmp, - validate = FALSE - ), - "generated" - ) - - expect_identical(cf, cf2) -}) diff --git a/tests/testthat/test-cff_to_bibentry.R b/tests/testthat/test-as_bibentry.R similarity index 76% rename from tests/testthat/test-cff_to_bibentry.R rename to tests/testthat/test-as_bibentry.R index d5438428..0baf3dc6 100644 --- a/tests/testthat/test-cff_to_bibentry.R +++ b/tests/testthat/test-as_bibentry.R @@ -1,3 +1,4 @@ +# Test Bibtex ---- test_that("Article to bibtex", { bib <- bibentry("Article", key = "knuth:1984", @@ -10,11 +11,11 @@ test_that("Article to bibtex", { number = 2, pages = "97--111", month = "January", - keywords = c("Some", "simple", "keywords") + keywords = "Some, simple, keywords" ) expect_snapshot(toBibtex(bib)) - x <- cff_parse_citation(bib) - bib <- cff_to_bibentry(x) + x <- as_cff(bib) + bib <- as_bibentry(x) expect_snapshot(toBibtex(bib)) }) @@ -41,8 +42,8 @@ test_that("Book to bibtex", { ) expect_snapshot(toBibtex(bib)) - bibparsed <- cff_parse_citation(bib) - bib <- cff_to_bibentry(bibparsed) + bibparsed <- as_cff(bib) + bib <- as_bibentry(bibparsed) expect_snapshot(toBibtex(bib)) }) @@ -62,8 +63,8 @@ test_that("Booklet to bibtex", { ) expect_snapshot(toBibtex(bib)) - bibparsed <- cff_parse_citation(bib) - bib <- cff_to_bibentry(bibparsed) + bibparsed <- as_cff(bib) + bib <- as_bibentry(bibparsed) expect_snapshot(toBibtex(bib)) }) @@ -90,8 +91,8 @@ test_that("InBook to bibtex with pages", { ) expect_snapshot(toBibtex(bib)) - bibparsed <- cff_parse_citation(bib) - bib <- cff_to_bibentry(bibparsed) + bibparsed <- as_cff(bib) + bib <- as_bibentry(bibparsed) expect_snapshot(toBibtex(bib)) }) @@ -109,8 +110,8 @@ test_that("InCollection to bibtex", { ) expect_snapshot(toBibtex(bib)) - bibparsed <- cff_parse_citation(bib) - bib <- cff_to_bibentry(bibparsed) + bibparsed <- as_cff(bib) + bib <- as_bibentry(bibparsed) expect_snapshot(toBibtex(bib)) }) @@ -134,8 +135,14 @@ test_that("InProceedings to bibtex", { ) expect_snapshot(toBibtex(bib)) - bibparsed <- cff_parse_citation(bib) - bib <- cff_to_bibentry(bibparsed) + bibparsed <- as_cff(bib) + bib <- as_bibentry(bibparsed) + expect_snapshot(toBibtex(bib)) + + # If we remove collection title use conference + bibparsed[[1]]$`collection-title` <- NULL + bibparsed[[1]]$conference$name <- "I Am a conference" + bib <- as_bibentry(bibparsed) expect_snapshot(toBibtex(bib)) }) @@ -152,8 +159,8 @@ test_that("Manual to bibtex", { ) expect_snapshot(toBibtex(bib)) - bibparsed <- cff_parse_citation(bib) - bib <- cff_to_bibentry(bibparsed) + bibparsed <- as_cff(bib) + bib <- as_bibentry(bibparsed) expect_snapshot(toBibtex(bib)) }) @@ -171,8 +178,8 @@ test_that("MastersThesis to bibtex", { ) expect_snapshot(toBibtex(bib)) - bibparsed <- cff_parse_citation(bib) - bib <- cff_to_bibentry(bibparsed) + bibparsed <- as_cff(bib) + bib <- as_bibentry(bibparsed) expect_snapshot(toBibtex(bib)) }) @@ -188,8 +195,8 @@ test_that("PhdThesis to bibtex", { ) expect_snapshot(toBibtex(bib)) - bibparsed <- cff_parse_citation(bib) - bib <- cff_to_bibentry(bibparsed) + bibparsed <- as_cff(bib) + bib <- as_bibentry(bibparsed) expect_snapshot(toBibtex(bib)) }) @@ -207,8 +214,8 @@ test_that("Proceedings to bibtex", { ) expect_snapshot(toBibtex(bib)) - bibparsed <- cff_parse_citation(bib) - bib <- cff_to_bibentry(bibparsed) + bibparsed <- as_cff(bib) + bib <- as_bibentry(bibparsed) expect_snapshot(toBibtex(bib)) }) @@ -223,8 +230,8 @@ test_that("TechReport to bibtex", { ) expect_snapshot(toBibtex(bib)) - bibparsed <- cff_parse_citation(bib) - bib <- cff_to_bibentry(bibparsed) + bibparsed <- as_cff(bib) + bib <- as_bibentry(bibparsed) expect_snapshot(toBibtex(bib)) }) @@ -233,16 +240,25 @@ test_that("Unpublished to bibtex", { author = "John M. Aronis and Foster J. Provost", title = "Efficiently Constructing Relational Features from Background", year = 1959, - note = "Unpublished MS, Computer Science Department, University of Pittsburgh.", + note = paste0( + "Unpublished MS, Computer Science Department, ", + "University of Pittsburgh." + ), missinginfo = "Date is guess.", ) expect_snapshot(toBibtex(bib)) - bibparsed <- cff_parse_citation(bib) - bib <- cff_to_bibentry(bibparsed) + bibparsed <- as_cff(bib) + bib <- as_bibentry(bibparsed) + expect_snapshot(toBibtex(bib)) + + # With custom note + bibparsed[[1]]$notes <- NULL + bib <- as_bibentry(bibparsed) expect_snapshot(toBibtex(bib)) }) +# Other testers ---- test_that("particle names", { bib <- bibentry("Book", @@ -253,18 +269,20 @@ test_that("particle names", { ) - bibparsed <- cff_parse_citation(bib) - bibparsed$authors <- cff_parse_person_bibtex("van Leunen, Mary-Claire and Davis, Jr., Sammy") + bibparsed <- as_cff(bib) + bibparsed[[1]]$authors <- as_cff_person( + "van Leunen, Mary-Claire and Davis, Jr., Sammy" + ) cffobj <- cff_create(cff(), - keys = list(references = list(bibparsed)) + keys = list(references = bibparsed) ) expect_true(cff_validate(cffobj, verbose = FALSE)) expect_snapshot(bibparsed) - bib <- cff_to_bibentry(bibparsed) + bib <- as_bibentry(bibparsed) expect_snapshot(toBibtex(bib)) }) @@ -278,15 +296,15 @@ test_that("From plain cff with a citation", { month = 3 ) - s$`preferred-citation` <- cff_parse_citation(acit) - s$`preferred-citation`$editors <- list(cff_parse_person("A name")) + s$`preferred-citation` <- as_cff(acit)[[1]] + s$`preferred-citation`$editors <- as_cff_person("A name") - bib <- cff_to_bibentry(s) + bib <- as_bibentry(s) expect_snapshot(toBibtex(bib)) }) test_that("From plain cff", { - expect_message(bib <- cff_to_bibentry(cff())) + expect_silent(bib <- as_bibentry(cff())) expect_snapshot(toBibtex(bib)) }) @@ -295,13 +313,13 @@ test_that("From file", { package = "cffr" ) - bib <- cff_to_bibentry(file) + bib <- as_bibentry(file) expect_snapshot(toBibtex(bib)) }) test_that("NULL", { s <- NULL - expect_null(cff_to_bibentry(s)) + expect_null(as_bibentry(s)) }) @@ -311,7 +329,7 @@ test_that("Test anonymous", { ) - expect_message(back <- cff_to_bibentry(cff_parse_citation(bib))) + expect_silent(back <- as_bibentry(as_cff(bib))) expect_snapshot(toBibtex(back)) @@ -320,7 +338,7 @@ test_that("Test anonymous", { ) - expect_message(back <- cff_to_bibentry(cff_parse_citation(bib))) + expect_silent(back <- as_bibentry(as_cff(bib))) expect_snapshot(toBibtex(back)) bib <- bibentry("misc", @@ -328,7 +346,7 @@ test_that("Test anonymous", { ) - expect_message(back <- cff_to_bibentry(cff_parse_citation(bib))) + expect_silent(back <- as_bibentry(as_cff(bib))) expect_snapshot(toBibtex(back)) bib <- bibentry("proceedings", @@ -337,7 +355,7 @@ test_that("Test anonymous", { ) - expect_silent(back <- cff_to_bibentry(cff_parse_citation(bib))) + expect_silent(back <- as_bibentry(as_cff(bib))) expect_snapshot(toBibtex(back)) }) @@ -351,12 +369,12 @@ test_that("Fallback month", { ) expect_snapshot(toBibtex(bib)) - x <- cff_parse_citation(bib) + x <- as_cff(bib) # Delete here the month x$month <- NULL - bibback <- cff_to_bibentry(x) + bibback <- as_bibentry(x) expect_snapshot(toBibtex(bibback)) }) @@ -387,10 +405,10 @@ test_that("Test BibLateX entry", { url = "http://www.ctan.org" ) expect_snapshot(toBibtex(bib)) - x <- cff_parse_citation(bib) + x <- as_cff(bib) - parsed <- cff_to_bibentry(x) + parsed <- as_bibentry(x) expect_snapshot(toBibtex(parsed)) }) @@ -398,7 +416,7 @@ test_that("Test BibLateX entry", { test_that("Test Fallback year", { x <- cff() - expect_message(msg <- cff_to_bibentry(x)) + expect_silent(msg <- as_bibentry(x)) expect_snapshot(toBibtex(msg)) @@ -407,32 +425,32 @@ test_that("Test Fallback year", { expect_true(cff_validate(x, verbose = FALSE)) - parsed <- cff_to_bibentry(x) + parsed <- as_bibentry(x) expect_snapshot(toBibtex(parsed)) }) test_that("Errors", { - expect_silent(b <- cff_to_bibentry("testthat")) + expect_silent(b <- as_bibentry("testthat")) expect_s3_class(b, "bibentry") - expect_error(cff_to_bibentry("testthat", what = "aa")) + expect_error(as_bibentry("testthat", what = "aa")) }) test_that("From package", { skip_if_not_installed("rmarkdown") - base <- cff_to_bibentry("rmarkdown") + base <- as_bibentry("rmarkdown") expect_s3_class(base, "bibentry") expect_length(base, 1) - refs <- cff_to_bibentry("rmarkdown", "references") + refs <- as_bibentry("rmarkdown", "references") expect_s3_class(refs, "bibentry") expect_gte(length(refs), 1) - all <- cff_to_bibentry("rmarkdown", "all") + all <- as_bibentry("rmarkdown", "all") expect_s3_class(all, "bibentry") expect_length(all, length(base) + length(refs)) @@ -441,10 +459,10 @@ test_that("From package", { test_that("NULL references", { basic <- cff() - expect_null(cff_to_bibentry(basic, "references")) + expect_null(as_bibentry(basic, "references")) # Test all - expect_message(l <- cff_to_bibentry(basic, "all")) + expect_silent(l <- as_bibentry(basic, "all")) expect_length(l, 1) }) @@ -452,9 +470,36 @@ test_that("NULL references", { test_that("From CITATION.cff", { p <- system.file("examples/smith-et-al.cff", package = "cffr") - base <- cff_to_bibentry(p) + base <- as_bibentry(p) expect_s3_class(base, "bibentry") expect_length(base, 1) }) + +test_that("Corrupt entry", { + bib <- bibentry("Article", + key = "knuth:1984", + author = person("R Core Team"), + title = "Literate Programming", + journal = "The Computer Journal", + year = "1984", + # Optional + volume = "27", + number = 2, + pages = "97--111", + month = "January", + keywords = "Some, simple, keywords" + ) + x <- as_cff(bib)[[1]] + x$year <- NULL + x$journal <- NULL + expect_snapshot(n <- as_bibentry(x)) + expect_null(n) +}) + +test_that("Parser return nulls", { + expect_null(make_bibentry(NULL)) +}) + +# Classes ---- diff --git a/tests/testthat/test-as_cff.R b/tests/testthat/test-as_cff.R new file mode 100644 index 00000000..b31c7359 --- /dev/null +++ b/tests/testthat/test-as_cff.R @@ -0,0 +1,107 @@ +test_that("as.cff still works", { + l <- list( + "cff-version" = "1.2.0", + title = "Manipulating files" + ) + + expect_silent(l1 <- as_cff(l)) + expect_silent(l2 <- as.cff(l)) + expect_s3_class(l1, c("cff", "list")) + + expect_snapshot(l2) +}) + + +test_that("as_cff.person", { + pers <- person("A", "person", + email = "fake@gmail.com", + comment = c( + ORCID = "0000-0000-0000-0000", + affiliation = "Real Madrid", + website = "https://www.google.com/" + ) + ) + + expect_identical(as_cff(pers), as_cff_person(pers)) + expect_snapshot(as_cff(pers)) +}) + +test_that("as_cff.bibentry, toBibtex", { + b <- bibentry("Misc", + title = "title", author = "Author", + editor = "Editor" + ) + + bbb <- as_cff(b) + + expect_s3_class(bbb, c("cff_ref_list", "cff", "list"), exact = TRUE) + expect_s3_class(bbb[[1]], c("cff_ref", "cff", "list"), exact = TRUE) + expect_snapshot(bbb) + + b_bib <- toBibtex(b) + expect_s3_class(b_bib, "Bibtex") + + bbbb <- as_cff(b_bib) + + expect_identical(bbb, bbbb) +}) + + +test_that("as_cff.default", { + b <- c(a = 1) + + expect_identical(as_cff(b), as_cff(as.list(b))) + + expect_snapshot(as_cff(b)) +}) + +test_that("Other convertes", { + a <- cff() + expect_s3_class(a, "cff") + a <- as_cff(a) + expect_true(is_cff(a)) + expect_s3_class(a, "cff") + + expect_message(noadd <- cff(address = "New York", version = 5)) + expect_true(is_cff(noadd)) + expect_false(is_cff(list(a = 1, b = 2))) + expect_true(is_cff(as_cff(list(a = 1, b = 2)))) +}) + + +test_that("]] cff_ref", { + b1 <- bibentry("Misc", + title = "title", author = "Author", + editor = "Editor" + ) + b2 <- bibentry("Manual", author = "Another", title = "another title") + + b_all <- c(b1, b2) + + expect_s3_class(b_all, "bibentry", exact = TRUE) + bbb <- as_cff(b_all) + + expect_s3_class(bbb, c("cff_ref_list", "cff", "list"), exact = TRUE) + expect_length(bbb, 2) + + b2_reg <- bbb[2] + expect_length(b2_reg, 1) + expect_s3_class(b2_reg, c("cff_ref", "cff", "list"), exact = TRUE) +}) + +test_that("]] cff_pers", { + b1 <- person("One", "person") + b2 <- person("ntity") + + b_all <- c(b1, b2) + + expect_s3_class(b_all, "person", exact = TRUE) + bbb <- as_cff(b_all) + + expect_s3_class(bbb, c("cff_pers_list", "cff", "list"), exact = TRUE) + expect_length(bbb, 2) + + b2_reg <- bbb[2] + expect_length(b2_reg, 1) + expect_s3_class(b2_reg, c("cff_pers", "cff", "list"), exact = TRUE) +}) diff --git a/tests/testthat/test-as_cff_person.R b/tests/testthat/test-as_cff_person.R new file mode 100644 index 00000000..745ca610 --- /dev/null +++ b/tests/testthat/test-as_cff_person.R @@ -0,0 +1,188 @@ +test_that("NULL gives NULL", { + expect_null(as_cff_person(NULL)) + expect_null(as_cff_person(NA)) + expect_null(as_cff_person(person())) + expect_null(as_cff_person(list())) + expect_null(as_cff_person("")) +}) + +test_that("debugging messages", { + initopt <- getOption("cffr_message_verbosity", NULL) + options("cffr_message_verbosity" = "debug") + ap <- person("Example") + expect_snapshot(a <- as_cff_person(ap)) + expect_snapshot(b <- as_cff_person("Example")) + # Disconnect + options("cffr_message_verbosity" = NULL) + expect_silent(a <- as_cff_person(ap)) + expect_silent(b <- as_cff_person("Example")) + + # Restore init + options("cffr_message_verbosity" = initopt) +}) + +test_that("Parse one person", { + p <- person("one", "person") + expect_snapshot(as_cff_person(p)) +}) + +test_that("Parse several persons", { + p <- c( + person("one", "person"), person("another", "human"), + person("and one", "more") + ) + expect_snapshot(as_cff_person(p)) +}) + + +test_that("Parse bibtex persons", { + s <- "Wright, III, Frank Edwin" + + expect_snapshot(as_cff_person(s)) + + s <- "A person and another and Another one" + + expect_snapshot(as_cff_person(s)) + + # As vector + s2 <- c("A person", "another", "Another one") + expect_identical(as_cff_person(s), as_cff_person(s2)) +}) + +test_that("Parse bibtex persons with masks", { + s <- "Elephant and Castle" + + expect_snapshot(as_cff_person(s)) + + s <- "{Elephant and Castle}" + + expect_snapshot(as_cff_person(s)) + + s <- "{Elephant and Castle} and this AND Ltd." + + expect_snapshot(as_cff_person(s)) + + s <- "{Elephant and Castle} and {this AND Ltd.}" + + expect_snapshot(as_cff_person(s)) +}) + + +test_that("Get same results with both", { + s3 <- as_cff_person( + c(person(family = "Entity"), person("A", "person")) + ) + + b3 <- as_cff_person("Entity and A person") + + expect_identical(s3, b3) + + s4 <- as_cff_person(person(family = "A big fat company")) + b4 <- as_cff_person("{A big fat company}") + + expect_identical(s4, b4) +}) + +test_that("R Core Team", { + p <- as_cff_person(person("R Core", "Team")) + + expect_equal(p[[1]]$name, "R Core Team") + + p <- as_cff_person("R Core Team") + + expect_equal(p[[1]]$name, "R Core Team") +}) + +test_that("Bioconductor", { + # Several tastes of Bioconductor + bio <- person("Bioconductor Package Maintainer", + role = "cre", + email = "maintainer@bioconductor.org" + ) + p <- as_cff_person(bio) + + expect_equal(p[[1]]$name, "Bioconductor Package Maintainer") + + p <- as_cff_person("Bioconductor Package Maintainer") + + expect_equal(p[[1]]$name, "Bioconductor Package Maintainer") + + p <- as_cff_person(person("The Bioconductor", "Package Maintainer")) + expect_equal(p[[1]]$name, "The Bioconductor Package Maintainer") +}) + +test_that("Several emails, select first", { + pp <- person( + given = "John", + family = "Doe", + role = c("aut", "cre", "trl"), + email = c("first_mail@gmail.com", "second_mail@espol.edu.ec") + ) + + p <- as_cff_person(pp) + + expect_equal(p[[1]]$email, "first_mail@gmail.com") +}) + + +test_that("Several emails, select second if first no valid", { + pp <- person( + given = "John", + family = "Doe", + role = c("aut", "cre", "trl"), + email = c("first_mail_gmail.com", "second_mail@espol.edu.ec") + ) + + p <- as_cff_person(pp) + + expect_equal(p[[1]]$email, "second_mail@espol.edu.ec") +}) + + + +test_that("No valid emails", { + pp <- person( + given = "John", + family = "Doe", + role = c("aut", "cre", "trl"), + email = c("first_mail_gmail.com", "second_mail__espol.edu.ec") + ) + + p <- as_cff_person(pp) + + expect_equal(p, as_cff_person(person( + given = "John", + family = "Doe" + ))) + + pp2 <- person( + given = "John", + family = "Doe" + ) + + p2 <- as_cff_person(pp2) + + expect_equal(p, as_cff_person(person( + given = "John", + family = "Doe" + ))) +}) + +test_that("Can extract comments from format", { + pp <- person( + given = "John", + family = "Doe", + email = "first_mail@gmail.com", + comment = c( + ORCID = "https://orcid.org/0000-0001-8457-4658", + website = "https://www.google.com/" + ) + ) + + pp1 <- as_cff_person(pp) + txt <- format(pp) + pp2 <- as_cff_person(txt) + expect_identical(pp1, pp2) + + expect_snapshot(pp2) +}) diff --git a/tests/testthat/test-bibtex2cff.R b/tests/testthat/test-as_cff_reference.R similarity index 65% rename from tests/testthat/test-bibtex2cff.R rename to tests/testthat/test-as_cff_reference.R index 29a49e4b..6806bf89 100644 --- a/tests/testthat/test-bibtex2cff.R +++ b/tests/testthat/test-as_cff_reference.R @@ -1,3 +1,201 @@ +test_that("Test citations with installed packages", { + installed <- as.character(installed.packages()[, 1]) + inst <- c("base", "jsonlite", "rmarkdown") + for (i in seq_len(length(inst))) { + if (inst[i] %in% installed) { + desc <- cff_create(inst[i]) + expect_true(length(desc$`preferred-citation`) > 1) + expect_true(cff_validate(desc, verbose = FALSE)) + } + } +}) + +test_that("Test full with CITATION and (option = author)", { + # Needs an installed package + desc_path <- system.file("examples/DESCRIPTION_rgeos", package = "cffr") + cit_path <- system.file("examples/CITATION_auto", package = "cffr") + parsed <- cff_safe_read_citation(desc_path, cit_path) + expect_s3_class(parsed, "cff") + + # Create cff + cffobj <- cff_create(desc_path, keys = list( + references = parsed + )) + + expect_s3_class(cffobj, "cff") + expect_snapshot(cffobj) + expect_true(cff_validate(cffobj, verbose = FALSE)) +}) + + +test_that("Parsed several citations", { + # Needs an installed package + desc_path <- system.file("examples/DESCRIPTION_rgeos", package = "cffr") + cit_path <- system.file("examples/CITATION_auto", package = "cffr") + citobj <- cff_safe_read_citation(desc_path, cit_path) + expect_s3_class(citobj, c("cff_ref_list", "cff", "list"), exact = TRUE) + + expect_snapshot(citobj) + expect_length(citobj, 3) +}) + + +test_that("Add wrong field to citation", { + bib <- bibentry( + bibtype = "Manual", + title = "favoritefood is not valid on cff schema", + author = "Jane Smith", + favoritefood = "bananas", + type = "I should be removed" + ) + + bibparsed <- as_cff(bib) + + expect_s3_class(bibparsed, "cff") + + cffobj <- cff_create(cff(), + keys = list( + references = bibparsed + ) + ) + + expect_snapshot(cffobj) + expect_true(cff_validate(cffobj, verbose = FALSE)) +}) + +test_that("Fix wrong orcid", { + bib <- bibentry( + bibtype = "Manual", + title = "Wrong orcid fixed by cffr", + author = person("Jane", + "Smith", + comment = c( + ORCID = + "http://orcid.org/0000-0000-0000-306X" + ) + ) + ) + + bibparsed <- as_cff(bib) + + expect_s3_class(bibparsed, "cff") + + cffobj <- cff_create(cff(), + keys = list(references = bibparsed) + ) + + expect_snapshot(cffobj) + expect_true(cff_validate(cffobj, verbose = FALSE)) +}) + +test_that("Several identifiers and duplicates", { + bib <- bibentry( + bibtype = "Manual", + title = "A Language and Environment for Statistical Computing", + year = "2022", + year = "2023", + author = person("R Core Team"), + version = NULL, + error = "", + url = "https://www.R-project.org/", + url = "https://google.com/", + doi = "10.5281/zenodo.5366600", + doi = "10.5281/zenodo.5366601", + doi = "10.5281/zenodo.5366602", + identifiers = "a,b" + ) + + bibparsed <- as_cff(bib) + + expect_s3_class(bibparsed, "cff") + + cffobj <- cff_create(cff(), + keys = list( + references = bibparsed + ) + ) + + expect_snapshot(cffobj) + expect_true(cff_validate(cffobj, verbose = FALSE)) +}) + +test_that("Test keywords and urls", { + bib <- bibentry( + bibtype = "Manual", + title = "A Language and Environment for Statistical Computing", + year = "2022", + author = person("R Core Team"), + url = "https://www.R-project.org/", + url = "https://google.com/", + keywords = "Some, random keywords, in, here, here" + ) + + bibparsed <- as_cff(bib) + + expect_s3_class(bibparsed, "cff") + + cffobj <- cff_create(cff(), + keys = list( + references = bibparsed + ) + ) + + expect_snapshot(cffobj) + expect_true(cff_validate(cffobj, verbose = FALSE)) +}) + +test_that("Parse persons on CITATION", { + bib <- bibentry("Manual", + title = "A Language and Environment for Statistical Computing", + year = "2021", + author = person("R Core Team"), + contact = "A name and A contact", + conference = person("A", "conference"), + "database-provider" = person("Database", "provider"), + editors = "A editor and {Ben and Jerry}", + "editors-series" = "An {editor series} and Another", + "institution" = person("A", "institution"), + "address" = person("A", "location"), + "publisher" = person("A", "publisher"), + "recipients" = "A recipient", + "senders" = "{A Sender} and Another Sender", + "translators" = "Translator one and Translator two" + ) + + bibparsed <- as_cff(bib) + expect_snapshot(bibparsed) + + cffobj <- cff_create(cff(), + keys = list(references = bibparsed) + ) + + expect_true(cff_validate(cffobj, verbose = FALSE)) +}) + +test_that("Test inputs", { + # Remove type + + bib <- bibentry("Book", + title = "Test", + author = "Billy Jean", + year = "2021", + publisher = "Random House", + type = "RANDOM" + ) + + + bibparsed <- as_cff(bib) + expect_snapshot(bibparsed) + + cffobj <- cff_create(cff(), + keys = list(references = bibparsed) + ) + + expect_true(cff_validate(cffobj, verbose = FALSE)) +}) + +# Parse citation from BibTeX ---- + test_that("Article", { bib <- bibentry("Article", key = "knuth:1984", @@ -13,17 +211,17 @@ test_that("Article", { note = "Example modified for testing purposes" ) - bibparsed <- cff_parse_citation(bib) + bibparsed <- as_cff(bib) expect_snapshot(bibparsed) cffobj <- cff_create(cff(), - keys = list(references = list(bibparsed)) + keys = list(references = bibparsed) ) expect_true(cff_validate(cffobj, verbose = FALSE)) # Back to bibtex and check names - tobib <- cff_to_bibentry(bibparsed) + tobib <- as_bibentry(bibparsed) fld1 <- sort(names(unclass(bib)[[1]])) fld2 <- sort(names(unclass(tobib)[[1]])) @@ -52,17 +250,17 @@ test_that("Book", { keywords = c("Two, keyword") ) - bibparsed <- cff_parse_citation(bib) + bibparsed <- as_cff(bib) expect_snapshot(bibparsed) cffobj <- cff_create(cff(), - keys = list(references = list(bibparsed)) + keys = list(references = bibparsed) ) expect_true(cff_validate(cffobj, verbose = FALSE)) # Back to bibtex and check names - tobib <- cff_to_bibentry(bibparsed) + tobib <- as_bibentry(bibparsed) fld1 <- sort(names(unclass(bib)[[1]])) fld2 <- sort(names(unclass(tobib)[[1]])) @@ -84,17 +282,17 @@ test_that("Booklet", { keywords = "java" ) - bibparsed <- cff_parse_citation(bib) + bibparsed <- as_cff(bib) expect_snapshot(bibparsed) cffobj <- cff_create(cff(), - keys = list(references = list(bibparsed)) + keys = list(references = bibparsed) ) expect_true(cff_validate(cffobj, verbose = FALSE)) # Back to bibtex and check names - tobib <- cff_to_bibentry(bibparsed) + tobib <- as_bibentry(bibparsed) fld1 <- sort(names(unclass(bib)[[1]])) fld2 <- sort(names(unclass(tobib)[[1]])) @@ -108,7 +306,10 @@ test_that("Conference", { key = "inproceedings-full", author = "Alfred V. Oaho and Jeffrey D. Ullman and Mihalis Yannakakis", title = "On Notions of Information Transfer in {VLSI} Circuits", - title = "{Statistical Machine Translation: Rapid Development with Limited Resources", + title = paste( + "{Statistical Machine Translation: Rapid Development", + "with Limited Resources" + ), booktitle = "Proc. Fifteenth Annual ACM STOC", year = "1983", # Optional @@ -131,18 +332,18 @@ test_that("Conference", { bib <- list(bib_un) class(bib) <- "bibentry" - bibparsed <- cff_parse_citation(bib) + bibparsed <- as_cff(bib) expect_snapshot(bibparsed) cffobj <- cff_create(cff(), - keys = list(references = list(bibparsed)) + keys = list(references = bibparsed) ) expect_true(cff_validate(cffobj, verbose = FALSE)) # Back to bibtex and check names - tobib <- cff_to_bibentry(bibparsed) + tobib <- as_bibentry(bibparsed) fld1 <- unique(sort(names(unclass(bib)[[1]]))) fld2 <- unique(sort(names(unclass(tobib)[[1]]))) @@ -171,16 +372,16 @@ test_that("InBook", { note = "Example modified for testing purposes" ) - bibparsed <- cff_parse_citation(bib) + bibparsed <- as_cff(bib) expect_snapshot(bibparsed) cffobj <- cff_create(cff(), - keys = list(references = list(bibparsed)) + keys = list(references = bibparsed) ) expect_true(cff_validate(cffobj, verbose = FALSE)) # Back to bibtex and check names - tobib <- cff_to_bibentry(bibparsed) + tobib <- as_bibentry(bibparsed) fld1 <- unique(sort(names(unclass(bib)[[1]]))) fld2 <- unique(sort(names(unclass(tobib)[[1]]))) @@ -211,17 +412,17 @@ test_that("InCollection", { note = "A note" ) - bibparsed <- cff_parse_citation(bib) + bibparsed <- as_cff(bib) expect_snapshot(bibparsed) cffobj <- cff_create(cff(), - keys = list(references = list(bibparsed)) + keys = list(references = bibparsed) ) expect_true(cff_validate(cffobj, verbose = FALSE)) # Back to bibtex and check names - tobib <- cff_to_bibentry(bibparsed) + tobib <- as_bibentry(bibparsed) fld1 <- unique(sort(names(unclass(bib)[[1]]))) fld2 <- unique(sort(names(unclass(tobib)[[1]]))) @@ -234,7 +435,10 @@ test_that("InProceedings", { key = "inproceedings-full", author = "Alfred V. Oaho and Jeffrey D. Ullman and Mihalis Yannakakis", title = "On Notions of Information Transfer in {VLSI} Circuits", - title = "{Statistical Machine Translation: Rapid Development with Limited Resources", + title = paste( + "{Statistical Machine Translation: Rapid", + "Development with Limited Resources" + ), booktitle = "Proc. Fifteenth Annual ACM STOC", year = "1983", # Optional @@ -249,17 +453,17 @@ test_that("InProceedings", { note = "Example modified for testing purposes" ) - bibparsed <- cff_parse_citation(bib) + bibparsed <- as_cff(bib) expect_snapshot(bibparsed) cffobj <- cff_create(cff(), - keys = list(references = list(bibparsed)) + keys = list(references = bibparsed) ) expect_true(cff_validate(cffobj, verbose = FALSE)) # Back to bibtex and check names - tobib <- cff_to_bibentry(bibparsed) + tobib <- as_bibentry(bibparsed) fld1 <- unique(sort(names(unclass(bib)[[1]]))) fld2 <- unique(sort(names(unclass(tobib)[[1]]))) @@ -280,17 +484,17 @@ test_that("Manual", { note = "Example modified for testing purposes" ) - bibparsed <- cff_parse_citation(bib) + bibparsed <- as_cff(bib) expect_snapshot(bibparsed) cffobj <- cff_create(cff(), - keys = list(references = list(bibparsed)) + keys = list(references = bibparsed) ) expect_true(cff_validate(cffobj, verbose = FALSE)) # Back to bibtex and check names - tobib <- cff_to_bibentry(bibparsed) + tobib <- as_bibentry(bibparsed) fld1 <- unique(sort(names(unclass(bib)[[1]]))) fld2 <- unique(sort(names(unclass(tobib)[[1]]))) @@ -312,17 +516,17 @@ test_that("MastersThesis", { month = "August", note = "Example modified for testing purposes" ) - bibparsed <- cff_parse_citation(bib) + bibparsed <- as_cff(bib) expect_snapshot(bibparsed) cffobj <- cff_create(cff(), - keys = list(references = list(bibparsed)) + keys = list(references = bibparsed) ) expect_true(cff_validate(cffobj, verbose = FALSE)) # Back to bibtex and check names - tobib <- cff_to_bibentry(bibparsed) + tobib <- as_bibentry(bibparsed) fld1 <- unique(sort(names(unclass(bib)[[1]]))) fld2 <- unique(sort(names(unclass(tobib)[[1]]))) @@ -341,17 +545,17 @@ test_that("Misc", { note = "A note" ) - bibparsed <- cff_parse_citation(bib) + bibparsed <- as_cff(bib) expect_snapshot(bibparsed) cffobj <- cff_create(cff(), - keys = list(references = list(bibparsed)) + keys = list(references = bibparsed) ) expect_true(cff_validate(cffobj, verbose = FALSE)) # Back to bibtex and check names - tobib <- cff_to_bibentry(bibparsed) + tobib <- as_bibentry(bibparsed) fld1 <- unique(sort(names(unclass(bib)[[1]]))) fld2 <- unique(sort(names(unclass(tobib)[[1]]))) @@ -374,17 +578,17 @@ test_that("PhdThesis", { note = "Example modified for testing purposes" ) - bibparsed <- cff_parse_citation(bib) + bibparsed <- as_cff(bib) expect_snapshot(bibparsed) cffobj <- cff_create(cff(), - keys = list(references = list(bibparsed)) + keys = list(references = bibparsed) ) expect_true(cff_validate(cffobj, verbose = FALSE)) # Back to bibtex and check names - tobib <- cff_to_bibentry(bibparsed) + tobib <- as_bibentry(bibparsed) fld1 <- unique(sort(names(unclass(bib)[[1]]))) fld2 <- unique(sort(names(unclass(tobib)[[1]]))) @@ -409,17 +613,17 @@ test_that("Proceedings", { note = "Example modified for testing purposes" ) - bibparsed <- cff_parse_citation(bib) + bibparsed <- as_cff(bib) expect_snapshot(bibparsed) cffobj <- cff_create(cff(), - keys = list(references = list(bibparsed)) + keys = list(references = bibparsed) ) expect_true(cff_validate(cffobj, verbose = FALSE)) # Back to bibtex and check names - tobib <- cff_to_bibentry(bibparsed) + tobib <- as_bibentry(bibparsed) fld1 <- unique(sort(names(unclass(bib)[[1]]))) fld2 <- unique(sort(names(unclass(tobib)[[1]]))) @@ -436,22 +640,25 @@ test_that("TechReport", { # Optional type = "techreport", number = "3-03", - address = "Computing Laboratory, University of Kent, Canterbury, Kent, CT2 7NF", + address = paste( + "Computing Laboratory, University of Kent,", + "Canterbury, Kent, CT2 7NF" + ), month = "mar", note = "Example modified for testing purposes" ) - bibparsed <- cff_parse_citation(bib) + bibparsed <- as_cff(bib) expect_snapshot(bibparsed) cffobj <- cff_create(cff(), - keys = list(references = list(bibparsed)) + keys = list(references = bibparsed) ) expect_true(cff_validate(cffobj, verbose = FALSE)) # Back to bibtex and check names - tobib <- cff_to_bibentry(bibparsed) + tobib <- as_bibentry(bibparsed) fld1 <- unique(sort(names(unclass(bib)[[1]]))) fld2 <- unique(sort(names(unclass(tobib)[[1]]))) @@ -469,17 +676,17 @@ test_that("Unpublished", { month = "aug", ) - bibparsed <- cff_parse_citation(bib) + bibparsed <- as_cff(bib) expect_snapshot(bibparsed) cffobj <- cff_create(cff(), - keys = list(references = list(bibparsed)) + keys = list(references = bibparsed) ) expect_true(cff_validate(cffobj, verbose = FALSE)) # Back to bibtex and check names - tobib <- cff_to_bibentry(bibparsed) + tobib <- as_bibentry(bibparsed) fld1 <- unique(sort(names(unclass(bib)[[1]]))) fld2 <- unique(sort(names(unclass(tobib)[[1]]))) @@ -501,22 +708,22 @@ test_that("InBook with booktitle", { chapter = "4.5" ) - bibparsed <- cff_parse_citation(bib) + bibparsed <- as_cff(bib) expect_snapshot(bibparsed) cffobj <- cff_create(cff(), - keys = list(references = list(bibparsed)) + keys = list(references = bibparsed) ) expect_true(cff_validate(cffobj, verbose = FALSE)) # Should be an incollection now - res <- cff_to_bibentry(bibparsed) + res <- as_bibentry(bibparsed) init_type <- attr(unclass(res)[[1]], "bibtype") expect_identical(tolower(init_type), "incollection") # Back to bibtex and check names - tobib <- cff_to_bibentry(bibparsed) + tobib <- as_bibentry(bibparsed) fld1 <- unique(sort(names(unclass(bib)[[1]]))) fld2 <- unique(sort(names(unclass(tobib)[[1]]))) @@ -528,7 +735,8 @@ test_that("Test entry without author", { bib <- bibentry("Proceedings", editor = "Yolande Berbers and Willy Zwaenepoel", title = "Proceedings of the 6th European Conference on Computer Systems", - booktitle = "Proceedings of the 6th European Conference on Computer Systems", + booktitle = paste("Proceedings of the 6th European", " + Conference on Computer Systems"), publisher = "ACM", venue = "Leuven, Belgium", month = "apr", @@ -536,17 +744,17 @@ test_that("Test entry without author", { isbn = "1-59593-322-02", ) - bibparsed <- cff_parse_citation(bib) + bibparsed <- as_cff(bib) expect_identical( - bibparsed$authors[[1]]$name, + bibparsed[[1]]$authors[[1]]$name, "anonymous" ) expect_snapshot(bibparsed) cffobj <- cff_create(cff(), - keys = list(references = list(bibparsed)) + keys = list(references = bibparsed) ) expect_true(cff_validate(cffobj, verbose = FALSE)) @@ -557,7 +765,10 @@ test_that("Test entry without author but has a key", { bib <- bibentry("Misc", key = "I am the key", title = "Proceedings of the 6th European Conference on Computer Systems", - booktitle = "Proceedings of the 6th European Conference on Computer Systems", + booktitle = paste( + "Proceedings of the 6th European Conference", + "on Computer Systems" + ), publisher = "ACM", venue = "Leuven, Belgium", month = "apr", @@ -565,10 +776,10 @@ test_that("Test entry without author but has a key", { isbn = "1-59593-322-02", ) - bibparsed <- cff_parse_citation(bib) + bibparsed <- as_cff(bib) expect_identical( - bibparsed$authors[[1]]$name, + bibparsed[[1]]$authors[[1]]$name, "anonymous" ) @@ -576,7 +787,7 @@ test_that("Test entry without author but has a key", { expect_snapshot(bibparsed) cffobj <- cff_create(cff(), - keys = list(references = list(bibparsed)) + keys = list(references = bibparsed) ) expect_true(cff_validate(cffobj, verbose = FALSE)) @@ -586,7 +797,8 @@ test_that("Test entry without author but has a key", { test_that("Test entry without author and key", { bib <- bibentry("Misc", title = "Proceedings of the 6th European Conference on Computer Systems", - booktitle = "Proceedings of the 6th European Conference on Computer Systems", + booktitle = paste("Proceedings of the 6th European", " + Conference on Computer Systems"), publisher = "ACM", venue = "Leuven, Belgium", month = "apr", @@ -594,10 +806,10 @@ test_that("Test entry without author and key", { isbn = "1-59593-322-02", ) - bibparsed <- cff_parse_citation(bib) + bibparsed <- as_cff(bib) expect_identical( - bibparsed$authors[[1]]$name, + bibparsed[[1]]$authors[[1]]$name, "anonymous" ) @@ -605,7 +817,7 @@ test_that("Test entry without author and key", { expect_snapshot(bibparsed) cffobj <- cff_create(cff(), - keys = list(references = list(bibparsed)) + keys = list(references = bibparsed) ) expect_true(cff_validate(cffobj, verbose = FALSE)) @@ -620,12 +832,12 @@ test_that("Skip misc without title", { year = 2018 ) - expect_message(bibparsed <- cff_parse_citation(bib), "Skipping") + expect_message(bibparsed <- as_cff(bib), "Skipping") expect_null(bibparsed) cffobj <- cff_create(cff(), - keys = list(references = list(bibparsed)) + keys = list(references = bibparsed) ) expect_snapshot(cffobj) @@ -637,18 +849,13 @@ test_that("Skip misc without title", { test_that("Skip misc without title, not skipping the good one", { bib <- c( bibentry( - bibtype = "misc", - author = c(person("SHERPA/RoMEO")), - url = "http://www.sherpa.ac.uk/romeo/", - year = 2018 + bibtype = "misc", author = c(person("SHERPA/RoMEO")), + url = "http://www.sherpa.ac.uk/romeo/", year = 2018 ), bibentry( bibtype = "misc", title = "{rromeo}: An {R} Client for {SHERPA/RoMEO} {API}", - author = c( - person("Matthias", "Grenié"), - person("Hugo", "Gruson") - ), + author = c(person("Matthias", "Grenié"), person("Hugo", "Gruson")), year = 2019, header = "To cite this package in publications, please use:", url = "https://CRAN.R-project.org/package=rromeo" @@ -657,13 +864,11 @@ test_that("Skip misc without title, not skipping the good one", { - expect_message(bibparsed <- cff_parse_citation(bib), "SHERPA/RoMEO") - - expect_length(bibparsed, 2) + expect_message(bibparsed <- as_cff(bib), "SHERPA/RoMEO") - expect_null(bibparsed[[1]]) + expect_length(bibparsed, 1) - expect_s3_class(bibparsed[[2]], "cff") + expect_s3_class(bibparsed[[1]], "cff") cffobj <- cff_create(cff(), keys = list(references = bibparsed) @@ -706,11 +911,11 @@ test_that("Check extended BibLatex Fields", { url = "http://www.ctan.org" ) - bibparsed <- cff_parse_citation(bib) + bibparsed <- as_cff(bib) expect_snapshot(bibparsed) cffobj <- cff_create(cff(), - keys = list(references = list(bibparsed)) + keys = list(references = bibparsed) ) expect_true(cff_validate(cffobj, verbose = FALSE)) diff --git a/tests/testthat/test-assertions.R b/tests/testthat/test-assertions.R index aaebfdb9..cd96eabe 100644 --- a/tests/testthat/test-assertions.R +++ b/tests/testthat/test-assertions.R @@ -19,6 +19,8 @@ test_that("Check is_email", { is_email("felix@nicebread@de"), is_email("felixnicebread.de"), is_email("@felixnicebread"), + is_email("a @felixnicebread.co"), + is_email("a@fe lixnicebread.de"), is_email(NULL), is_email(NA) ) diff --git a/tests/testthat/test-cff-methods.R b/tests/testthat/test-cff-methods.R new file mode 100644 index 00000000..e1423439 --- /dev/null +++ b/tests/testthat/test-cff-methods.R @@ -0,0 +1,253 @@ +test_that("as data frame complete", { + path <- system.file("examples/CITATION_complete.cff", package = "cffr") + + the_cff <- cff_read(path) + + # To df + the_df <- as.data.frame(the_cff) + + expect_s3_class(the_df, "data.frame") + expect_equal(nrow(the_df), 1) + + # lengths + allf <- unlist(the_cff, recursive = TRUE, use.names = FALSE) + expect_identical(length(allf), ncol(the_df)) + + + expect_identical(ncol(the_df), length(unique(names(the_df)))) + + # As vector + df_as_v <- as.character(as.vector(the_df[1, ])) + + + expect_identical(allf, df_as_v) + expect_snapshot(names(the_df)) +}) + +test_that("as data frame partial", { + path <- system.file("examples/CITATION_complete.cff", package = "cffr") + + the_cff <- cff_read(path) + + # To df authors only + subcff <- the_cff$authors[[1]] + the_df <- as.data.frame(subcff) + expect_s3_class(the_df, "data.frame") + expect_equal(nrow(the_df), 1) + # lengths + allf <- unlist(subcff, recursive = TRUE, use.names = FALSE) + expect_identical(length(allf), ncol(the_df)) + expect_identical(ncol(the_df), length(unique(names(the_df)))) + + + + # To df references only + subcff <- the_cff$references[[1]] + the_df <- as.data.frame(subcff) + expect_s3_class(the_df, "data.frame") + expect_equal(nrow(the_df), 1) + # lengths + allf <- unlist(subcff, recursive = TRUE, use.names = FALSE) + expect_identical(length(allf), ncol(the_df)) + expect_identical(ncol(the_df), length(unique(names(the_df)))) +}) + + +test_that("Convert a citation only", { + path <- system.file("examples/DESCRIPTION_many_persons", package = "cffr") + a_cit <- as_bibentry(cff_create(path)) + + the_cff <- as_cff(a_cit) + + # To df + the_df <- as.data.frame(the_cff) + + expect_s3_class(the_df, "data.frame") + expect_equal(nrow(the_df), 1) + + # lengths + allf <- unlist(the_cff, recursive = TRUE, use.names = FALSE) + expect_identical(length(allf), ncol(the_df)) + + + expect_identical(ncol(the_df), length(unique(names(the_df)))) + + # As vector + df_as_v <- as.character(as.vector(the_df[1, ])) + + + expect_identical(allf, df_as_v) + expect_snapshot(names(the_df)) +}) + + +test_that("Convert authors only", { + a_pers_list <- as_cff_person( + "A person and {A Entity inc.} and {One person} more" + ) + + the_cff <- a_pers_list[[1]] + + # To df + the_df <- as.data.frame(the_cff) + + expect_s3_class(the_df, "data.frame") + expect_equal(nrow(the_df), 1) + + # lengths + allf <- unlist(the_cff, recursive = TRUE, use.names = FALSE) + expect_identical(length(allf), ncol(the_df)) + + expect_identical(ncol(the_df), length(unique(names(the_df)))) + + # As vector + df_as_v <- as.character(as.vector(the_df[1, ])) + + + expect_identical(allf, df_as_v) + expect_snapshot(names(the_df)) +}) + +test_that("Convert list of authors", { + path <- system.file("examples/CITATION_complete.cff", package = "cffr") + + the_cff <- cff_read(path)$authors + + # To df + the_df <- as.data.frame(the_cff) + + expect_s3_class(the_df, "data.frame") + expect_equal(nrow(the_df), 1) + + # lengths + allf <- unlist(the_cff, recursive = TRUE, use.names = FALSE) + expect_identical(length(allf), ncol(the_df)) + + expect_identical(ncol(the_df), length(unique(names(the_df)))) + + # As vector + df_as_v <- as.character(as.vector(the_df[1, ])) + + + expect_identical(allf, df_as_v) + expect_snapshot(names(the_df)) +}) + + +test_that("as.person method", { + path <- system.file("examples/CITATION_complete.cff", package = "cffr") + + the_cff <- cff_read(path) + + getref <- the_cff$references[[1]] + + # Single entity + pub <- as.person(getref$publisher) + expect_s3_class(pub, "person") + + expect_snapshot(dput(pub)) + expect_snapshot( + format(pub, include = c("given", "family", "email", "role", "comment")) + ) + + # Single person + aut <- as.person(getref$authors[[1]]) + expect_s3_class(aut, "person") + expect_snapshot(dput(aut)) + expect_snapshot( + format(aut, include = c("given", "family", "email", "role", "comment")) + ) + + # List of authors + aut2 <- as.person(getref$authors) + + expect_s3_class(aut2, "person") + expect_s3_class(aut2[1], "person") + expect_s3_class(aut2[2], "person") + expect_snapshot(dput(aut2)) + expect_snapshot( + format(aut2, include = c("given", "family", "email", "role", "comment")) + ) +}) + +test_that("as person with another cff", { + path <- system.file("examples/CITATION_complete.cff", package = "cffr") + the_cff <- cff_read(path) + expect_s3_class(the_cff, "cff") + expect_identical(as.person(the_cff), person()) + + # identifiers + key <- the_cff$identifiers + expect_s3_class(key, "cff") + expect_identical(as.person(key), person()) + + # preferred + key <- the_cff$`preferred-citation` + expect_s3_class(key, "cff") + expect_identical(as.person(key), person()) +}) + +test_that("head and tail", { + a_cff <- cff() + expect_snapshot(a_cff) + expect_snapshot(head(a_cff, 2)) + expect_s3_class(head(a_cff, 2), "cff") + + expect_snapshot(tail(a_cff, 2)) + expect_s3_class(tail(a_cff, 2), "cff") +}) + +test_that("toBibtex", { + # Create several alternatives + descobj <- cff_read_description(system.file("examples/DESCRIPTION_basic", + package = "cffr" + )) + + citobj <- cff_read_citation(system.file("examples/CITATION_basic", + package = "cffr" + )) + newbib <- cff_read_bib(system.file("examples/example.bib", + package = "cffr" + )) + + full_cff <- merge_desc_cit(descobj, c(newbib, citobj)) + full_cff <- new_cff(full_cff) + expect_true(cff_validate(full_cff, verbose = FALSE)) + + # A. validate extractions + expect_snapshot(toBibtex(full_cff)) + expect_snapshot(toBibtex(full_cff, what = "references")) + expect_snapshot(toBibtex(full_cff, what = "all")) + + # single entries + single <- toBibtex(full_cff$`preferred-citation`) + expect_s3_class(single, "Bibtex") + expect_equal(sum(names(single) == "title"), 1) + + # Several entries + several <- toBibtex(full_cff$references) + expect_s3_class(several, "Bibtex") + expect_equal(sum(names(several) == "title"), 3) + + + # One entry + oneent <- toBibtex(full_cff$references[[1]]) + expect_s3_class(single, "Bibtex") + expect_equal(sum(names(oneent) == "title"), 1) + + fromfile <- toBibtex(newbib) + expect_s3_class(fromfile, "Bibtex") + expect_equal(sum(names(fromfile) == "title"), 2) + + # From lines + string <- "@book{einstein1921, + title = {Relativity: The Special and the General Theory}, + author = {Einstein, A.}, + year = 1920, + publisher = {Henry Holt and Company}, + address = {London, United Kingdom}, + isbn = 9781587340925}" + + froml <- toBibtex(cff_read_bib_text(string)) + expect_equal(sum(names(froml) == "title"), 1) +}) diff --git a/tests/testthat/test-cff.R b/tests/testthat/test-cff.R new file mode 100644 index 00000000..02a12d64 --- /dev/null +++ b/tests/testthat/test-cff.R @@ -0,0 +1,110 @@ +test_that("Test message on cff", { + expect_snapshot(def <- cff("abcde")) + + expect_identical(def, cff()) + nocff <- system.file("examples/CITATION_skeleton.cff", + package = "cffR" + ) + expect_snapshot(afile <- cff(nocff)) + + expect_identical(afile, cff()) +}) + + +test_that("Walk trough full lifecycle", { + complete <- system.file("examples/CITATION_complete.cff", + package = "cffr" + ) + + # Read + read <- cff_read(complete) + expect_s3_class(read, "cff") + expect_true(cff_validate(read, verbose = FALSE)) + expect_snapshot(read) + + # Modify + modify <- cff_create(read, keys = list(title = "A new title")) + expect_snapshot(modify) + expect_true(length(read) == length(modify)) + expect_true(length((setdiff(names(read), names(modify)))) == 0) + expect_false(read$title == modify$title) + + + + # Write + tmp <- tempfile(fileext = ".cff") + cff_write(modify, outfile = tmp, validate = FALSE, verbose = FALSE) + stopifnotexists(tmp) + stopifnotcff(tmp) + + # Validate + expect_true(cff_validate(tmp, verbose = FALSE)) + + file.remove(tmp) +}) + +test_that("Recursive parsing", { + complete <- system.file("examples/CITATION_complete.cff", + package = "cffr" + ) + + # Read + expect_snapshot(read <- cff(complete)) + read <- cff_read(complete) + + # Test all levels + expect_s3_class(read, "cff") + expect_s3_class(read$authors, "cff") + expect_s3_class(read$authors[[1]], "cff") + expect_s3_class(read$references, "cff") + expect_s3_class(read$references[[1]]$authors, "cff") + expect_s3_class(read$references[[1]]$authors[[1]], "cff") +}) + + +test_that("Fuzzy matching of keys on cff", { + expect_snapshot(cff( + tittle = "a", + cff_version = "ar", + version = "200", + messange = "Fix my keys" + )) + + expect_snapshot(cffobj <- cff( + tittle = "a", + cff_version = "1.2.0", version = "200", + messange = "aa", + anthor = list(list( + "family-names" = "a", + "given-names" = "b" + )) + )) + + expect_true(is_cff(cffobj)) + expect_true(cff_validate(cffobj, verbose = FALSE)) +}) + +test_that("duplicated", { + expect_snapshot(ss <- cff( + tittle = "a", tittle = "ar", + version = "200", + messange = "Fix my keys" + )) + + expect_s3_class(ss, "cff") + expect_length(ss, 3) +}) + +test_that("unnamed", { + expect_snapshot(ss <- cff( + path = "a", "200", "Fix my keys" + ), error = TRUE) + + expect_snapshot(s1 <- cff(path = NULL, title = "a", "b", version = 1)) + expect_snapshot(s2 <- cff( + path = NULL, title = "a", "aa", "bb", "cc", + "b", version = 1, "h", "j" + )) + + expect_identical(s1, s2) +}) diff --git a/tests/testthat/test-cff_create.R b/tests/testthat/test-cff_create.R index 7c5776f2..883aca28 100644 --- a/tests/testthat/test-cff_create.R +++ b/tests/testthat/test-cff_create.R @@ -86,3 +86,457 @@ test_that("Test installed packages vs call to file", { expect_identical(call1, call2) }) + +# Additional authors ---- + +test_that("Default roles", { + p <- system.file("examples/DESCRIPTION_no_URL", package = "cffr") + + cf <- cff_create(p, dependencies = FALSE) + + # Same as + cf2 <- cff_create(p, authors_roles = c("aut", "cre"), dependencies = FALSE) + expect_identical(cf, cf2) +}) + +test_that("Add new roles", { + p <- system.file("examples/DESCRIPTION_no_URL", package = "cffr") + + cf <- cff_create(p, dependencies = FALSE) + cf2 <- cff_create(p, + authors_roles = c("aut", "cre", "ctb"), + dependencies = FALSE + ) + + expect_gt(length(cf2$authors), length(cf$authors)) + expect_true(cff_validate(cf2, verbose = FALSE)) +}) + + +test_that("Default roles on write", { + p <- system.file("examples/DESCRIPTION_no_URL", package = "cffr") + + cf <- cff_create(p, dependencies = FALSE) + + # Same as + tmp <- tempfile(fileext = ".cff") + expect_silent( + cf2 <- cff_write(p, + authors_roles = c("aut", "cre"), dependencies = FALSE, + outfile = tmp, verbose = FALSE, validate = FALSE + ) + ) + + expect_identical(cf, cf2) +}) + +test_that("Add new roles", { + p <- system.file("examples/DESCRIPTION_no_URL", package = "cffr") + + cf <- cff_create(p, dependencies = FALSE) + cf2 <- cff_create(p, + authors_roles = c("aut", "cre", "ctb"), + dependencies = FALSE + ) + + expect_gt(length(cf2$authors), length(cf$authors)) + expect_true(cff_validate(cf2, verbose = FALSE)) +}) + +test_that("Add new roles on write", { + p <- system.file("examples/DESCRIPTION_no_URL", package = "cffr") + + cf_def <- cff_create(p) + cf <- cff_create(p, authors_roles = "ctb") + + expect_gt(length(cf$authors), length(cf_def$authors)) + + # Same as + tmp <- tempfile(fileext = ".cff") + expect_message( + cf2 <- cff_write(p, + authors_roles = "ctb", outfile = tmp, + validate = FALSE + ), + "generated" + ) + + expect_identical(cf, cf2) +}) + +# Check DESCRIPTION ---- +test_that("Parse date", { + desc_path <- system.file("examples/DESCRIPTION_rgeos", package = "cffr") + + parsed <- cff_create(desc_path, + gh_keywords = FALSE, + keys = list(references = NULL) + ) + + expect_false(is.null(parsed$`date-released`)) + + expect_s3_class(parsed, "cff") + expect_snapshot(parsed) + expect_true(cff_validate(parsed, verbose = FALSE)) +}) + +test_that("Parse date in another format", { + desc_path <- system.file("examples/DESCRIPTION_basicdate", package = "cffr") + + parsed <- cff_create(desc_path, + gh_keywords = FALSE, + keys = list(references = NULL) + ) + + expect_false(is.null(parsed$`date-released`)) + + expect_s3_class(parsed, "cff") + expect_snapshot(parsed) + expect_true(cff_validate(parsed, verbose = FALSE)) +}) + + +test_that("No date parsed in DESCRIPTION without it", { + desc_path <- system.file("examples/DESCRIPTION_basic", package = "cffr") + + parsed <- cff_create(desc_path, + keys = list(references = NULL) + ) + + expect_true(is.null(parsed$`date-released`)) + + expect_s3_class(parsed, "cff") + expect_true(cff_validate(parsed, verbose = FALSE)) +}) + +test_that("Parsing many urls", { + desc_path <- system.file("examples/DESCRIPTION_many_urls", package = "cffr") + + parsed <- cff_create(desc_path, + gh_keywords = FALSE, + keys = list(references = NULL) + ) + + expect_length(parsed$`repository-code`, 1) + expect_length(parsed$url, 1) + expect_length(parsed$identifiers, 3) + expect_s3_class(parsed, "cff") + expect_snapshot(parsed) + expect_true(cff_validate(parsed, verbose = FALSE)) +}) + + +test_that("Parsing Gitlab", { + desc_path <- system.file("examples/DESCRIPTION_gitlab", package = "cffr") + + parsed <- cff_create(desc_path, + keys = list(references = NULL) + ) + + expect_length(parsed$`repository-code`, 1) + expect_length(parsed$url, 1) + expect_length(parsed$identifiers, 0) + expect_s3_class(parsed, "cff") + expect_snapshot(parsed) + expect_true(cff_validate(parsed, verbose = FALSE)) +}) + +test_that("Parsing many persons", { + desc_path <- system.file("examples/DESCRIPTION_many_persons", + package = "cffr" + ) + + parsed <- cff_create(desc_path, + gh_keywords = FALSE, + keys = list(references = NULL) + ) + + + expect_length(parsed$authors, 4) + + + authors <- unlist(parsed$authors) + + + expect_length(grep("erro", authors), 0) + names <- unlist(lapply(parsed$authors, names)) + + expect_s3_class(parsed, "cff") + expect_snapshot(parsed) + expect_true(cff_validate(parsed, verbose = FALSE)) +}) + + +test_that("Parsing wrong urls", { + desc_path <- system.file("examples/DESCRIPTION_wrong_urls", package = "cffr") + + parsed <- cff_create(desc_path, + gh_keywords = FALSE, + keys = list(references = NULL) + ) + + expect_null(parsed$`repository-code`) + expect_length(parsed$url, 1) + expect_length(parsed$identifiers, 2) + + expect_s3_class(parsed, "cff") + expect_snapshot(parsed) + expect_true(cff_validate(parsed, verbose = FALSE)) +}) + + + +test_that("Parsing two maintainers", { + desc_path <- system.file("examples/DESCRIPTION_twomaintainers", + package = "cffr" + ) + + parsed <- cff_create(desc_path, + gh_keywords = FALSE, + keys = list(references = NULL) + ) + + expect_length(parsed$authors, 3) + expect_length(parsed$contact, 2) + + expect_s3_class(parsed, "cff") + expect_snapshot(parsed) + expect_true(cff_validate(parsed, verbose = FALSE)) +}) + +test_that("Parsing r-universe", { + desc_path <- system.file("examples/DESCRIPTION_r_universe", + package = "cffr" + ) + + parsed <- cff_create(desc_path, + gh_keywords = FALSE, + keys = list(references = NULL) + ) + + expect_length(parsed$repository, 1) + + expect_s3_class(parsed, "cff") + expect_snapshot(parsed) + expect_true(cff_validate(parsed, verbose = FALSE)) +}) + + +test_that("Parsing Bioconductor", { + desc_path <- system.file("examples/DESCRIPTION_bioconductor", + package = "cffr" + ) + + parsed <- cff_create(desc_path, + gh_keywords = FALSE, + keys = list(references = NULL) + ) + + expect_length(parsed$repository, 1) + + expect_s3_class(parsed, "cff") + expect_snapshot(parsed) + expect_true(cff_validate(parsed, verbose = FALSE)) +}) + +test_that("Parsing Posit Package Manager", { + desc_path <- system.file("examples/DESCRIPTION_posit_package_manager", + package = "cffr" + ) + + parsed <- cff_create(desc_path, + gh_keywords = FALSE, + keys = list(references = NULL) + ) + + expect_length(parsed$repository, 1) + expect_identical( + parsed$repository, + "https://CRAN.R-project.org/package=resmush" + ) + expect_s3_class(parsed, "cff") + expect_snapshot(parsed) + expect_true(cff_validate(parsed, verbose = FALSE)) +}) + +test_that("Search package on CRAN", { + basic_path <- system.file("examples/DESCRIPTION_basic", + package = "cffr" + ) + + tmp <- tempfile("DESCRIPTION_basic") + # Create a temporary file + file.copy(basic_path, tmp) + + newfile <- desc::desc_set("Package", "ggplot2", file = tmp) + + parsed <- cff_create(tmp, gh_keywords = FALSE) + expect_length(parsed$repository, 1) + expect_equal(clean_str(newfile$get("Package")), "ggplot2") + expect_equal(parsed$repository, "https://CRAN.R-project.org/package=ggplot2") + + + + expect_s3_class(parsed, "cff") + expect_snapshot(parsed) + expect_true(cff_validate(parsed, verbose = FALSE)) +}) + + +test_that("Search package on r-universe", { + skip_on_cran() + skip_if_offline() + + basic_path <- system.file("examples/DESCRIPTION_basic", + package = "cffr" + ) + + tmp <- tempfile("DESCRIPTION_basic") + # Create a temporary file + file.copy(basic_path, tmp) + + + # Get packages from my r-universe + dhh <- unlist(jsonlite::read_json( + "https://dieghernan.r-universe.dev/packages" + ))[1] + + + newpack <- desc::desc(tmp) + + oldtitle <- clean_str(newpack$get("Package")) + + newtitle <- desc::desc_set("Package", dhh, file = tmp) + + expect_false(oldtitle == clean_str(newtitle$get("Package"))) + + + # Configure to search on r-universe + newrepos <- c( + dieghernan = "https://dieghernan.r-universe.dev", + CRAN = "https://cloud.r-project.org" + ) + + runiverse <- as.data.frame(available.packages( + repos = newrepos + )) + + expect_equal( + search_on_repos(dhh, runiverse), + "https://dieghernan.r-universe.dev/" + ) + + + # Search now ggplot2, should be canonical url + + expect_equal( + search_on_repos("ggplot2", runiverse, newrepos), + "https://CRAN.R-project.org/package=ggplot2" + ) +}) + + +test_that("Validate keywords", { + desc_path <- system.file("examples/DESCRIPTION_basic", + package = "cffr" + ) + + tmp <- tempfile("DESCRIPTION_keyword") + + copy <- file.copy(desc_path, tmp) + + cffobj <- cff_create(tmp) + expect_null(cffobj$keywords) + + expect_true(cff_validate(cffobj, verbose = FALSE)) + + # Add keywords + silent <- desc::desc_set("X-schema.org-keywords", + "keyword1, keyword1, keyword3", + file = tmp + ) + cffobj2 <- cff_create(tmp) + expect_length(cffobj2$keywords, 2) + expect_equal(cffobj2$keywords, c("keyword1", "keyword3")) + expect_true(cff_validate(cffobj2, verbose = FALSE)) + + # Single keyword + silent <- desc::desc_set("X-schema.org-keywords", + "keyword1, keyword1", + file = tmp + ) + cffobj3 <- cff_create(tmp) + expect_length(cffobj3$keywords, 2) + expect_equal(cffobj3$keywords, c("keyword1", "r-package")) + expect_true(cff_validate(cffobj3, verbose = FALSE)) + + # NULL case keyword + silent <- desc::desc_set("X-schema.org-keywords", + "r-package", + file = tmp + ) + cffobj4 <- cff_create(tmp) + expect_null(cffobj4$keywords) + expect_true(cff_validate(cffobj4, verbose = FALSE)) +}) + + +test_that("Parse keywords from GH", { + skip_on_cran() + skip_if_offline() + skip_if( + nchar(Sys.getenv("GITHUB_TOKEN")) == 0, + "No GITHUB_TOKEN environment variable found" + ) + + desc_path <- system.file("examples/DESCRIPTION_basic", + package = "cffr" + ) + + tmp <- tempfile("DESCRIPTION_keyword_gh") + + copy <- file.copy(desc_path, tmp) + + cffobj <- cff_create(tmp) + expect_null(cffobj$keywords) + + expect_true(cff_validate(cffobj, verbose = FALSE)) + + # A site with no topics + silent <- desc::desc_set("BugReports", + "https://github.com/dieghernan/cfftest/issues", + file = tmp + ) + + cffobjnokeys <- cff_create(tmp) + expect_true(cff_validate(cffobjnokeys, verbose = FALSE)) + expect_null(cffobjnokeys$keywords) + + # Add keywords from url + silent <- desc::desc_set("URL", + "https://github.com/ropensci/cffr", + file = tmp + ) + + silent <- desc::desc_set("BugReports", + "https://github.com/ropensci/cffr/issues", + file = tmp + ) + + cffobj1 <- cff_create(tmp) + expect_true(cff_validate(cffobj1, verbose = FALSE)) + expect_false(is.null(cffobj1$keywords)) + + # Concatenate keywords of both sources + + # Add keywords + silent <- desc::desc_set("X-schema.org-keywords", + "keyword1", + file = tmp + ) + + cffobj2 <- cff_create(tmp) + expect_true(cff_validate(cffobj2, verbose = FALSE)) + + expect_true(length(cffobj2$keywords) > length(cffobj1$keywords)) +}) diff --git a/tests/testthat/test-cff_description.R b/tests/testthat/test-cff_description.R deleted file mode 100644 index 2a6f8f1d..00000000 --- a/tests/testthat/test-cff_description.R +++ /dev/null @@ -1,375 +0,0 @@ -test_that("Parse date", { - desc_path <- system.file("examples/DESCRIPTION_rgeos", package = "cffr") - - parsed <- cff_create(desc_path, - gh_keywords = FALSE, - keys = list(references = NULL) - ) - - expect_false(is.null(parsed$`date-released`)) - - expect_s3_class(parsed, "cff") - expect_snapshot(parsed) - expect_true(cff_validate(parsed, verbose = FALSE)) -}) - -test_that("Parse date in another format", { - desc_path <- system.file("examples/DESCRIPTION_basicdate", package = "cffr") - - parsed <- cff_create(desc_path, - gh_keywords = FALSE, - keys = list(references = NULL) - ) - - expect_false(is.null(parsed$`date-released`)) - - expect_s3_class(parsed, "cff") - expect_snapshot(parsed) - expect_true(cff_validate(parsed, verbose = FALSE)) -}) - - -test_that("No date parsed in DESCRIPTION without it", { - desc_path <- system.file("examples/DESCRIPTION_basic", package = "cffr") - - parsed <- cff_create(desc_path, - keys = list(references = NULL) - ) - - expect_true(is.null(parsed$`date-released`)) - - expect_s3_class(parsed, "cff") - expect_true(cff_validate(parsed, verbose = FALSE)) -}) - -test_that("Parsing many urls", { - desc_path <- system.file("examples/DESCRIPTION_many_urls", package = "cffr") - - parsed <- cff_create(desc_path, - gh_keywords = FALSE, - keys = list(references = NULL) - ) - - expect_length(parsed$`repository-code`, 1) - expect_length(parsed$url, 1) - expect_length(parsed$identifiers, 3) - expect_s3_class(parsed, "cff") - expect_snapshot(parsed) - expect_true(cff_validate(parsed, verbose = FALSE)) -}) - - -test_that("Parsing Gitlab", { - desc_path <- system.file("examples/DESCRIPTION_gitlab", package = "cffr") - - parsed <- cff_create(desc_path, - keys = list(references = NULL) - ) - - expect_length(parsed$`repository-code`, 1) - expect_length(parsed$url, 1) - expect_length(parsed$identifiers, 0) - expect_s3_class(parsed, "cff") - expect_snapshot(parsed) - expect_true(cff_validate(parsed, verbose = FALSE)) -}) - -test_that("Parsing many persons", { - desc_path <- system.file("examples/DESCRIPTION_many_persons", - package = "cffr" - ) - - parsed <- cff_create(desc_path, - gh_keywords = FALSE, - keys = list(references = NULL) - ) - - - expect_length(parsed$authors, 4) - - - authors <- unlist(parsed$authors) - - - expect_length(grep("erro", authors), 0) - names <- unlist(lapply(parsed$authors, names)) - - expect_s3_class(parsed, "cff") - expect_snapshot(parsed) - expect_true(cff_validate(parsed, verbose = FALSE)) -}) - - -test_that("Parsing wrong urls", { - desc_path <- system.file("examples/DESCRIPTION_wrong_urls", package = "cffr") - - parsed <- cff_create(desc_path, - gh_keywords = FALSE, - keys = list(references = NULL) - ) - - expect_null(parsed$`repository-code`) - expect_length(parsed$url, 1) - expect_length(parsed$identifiers, 2) - - expect_s3_class(parsed, "cff") - expect_snapshot(parsed) - expect_true(cff_validate(parsed, verbose = FALSE)) -}) - - - -test_that("Parsing two maintainers", { - desc_path <- system.file("examples/DESCRIPTION_twomaintainers", - package = "cffr" - ) - - parsed <- cff_create(desc_path, - gh_keywords = FALSE, - keys = list(references = NULL) - ) - - expect_length(parsed$authors, 3) - expect_length(parsed$contact, 2) - - expect_s3_class(parsed, "cff") - expect_snapshot(parsed) - expect_true(cff_validate(parsed, verbose = FALSE)) -}) - -test_that("Parsing r-universe", { - desc_path <- system.file("examples/DESCRIPTION_r_universe", - package = "cffr" - ) - - parsed <- cff_create(desc_path, - gh_keywords = FALSE, - keys = list(references = NULL) - ) - - expect_length(parsed$repository, 1) - - expect_s3_class(parsed, "cff") - expect_snapshot(parsed) - expect_true(cff_validate(parsed, verbose = FALSE)) -}) - - -test_that("Parsing Bioconductor", { - desc_path <- system.file("examples/DESCRIPTION_bioconductor", - package = "cffr" - ) - - parsed <- cff_create(desc_path, - gh_keywords = FALSE, - keys = list(references = NULL) - ) - - expect_length(parsed$repository, 1) - - expect_s3_class(parsed, "cff") - expect_snapshot(parsed) - expect_true(cff_validate(parsed, verbose = FALSE)) -}) - -test_that("Parsing Posit Package Manager", { - desc_path <- system.file("examples/DESCRIPTION_posit_package_manager", - package = "cffr" - ) - - parsed <- cff_create(desc_path, - gh_keywords = FALSE, - keys = list(references = NULL) - ) - - expect_length(parsed$repository, 1) - expect_identical( - parsed$repository, - "https://CRAN.R-project.org/package=resmush" - ) - expect_s3_class(parsed, "cff") - expect_snapshot(parsed) - expect_true(cff_validate(parsed, verbose = FALSE)) -}) - -test_that("Search package on CRAN", { - basic_path <- system.file("examples/DESCRIPTION_basic", - package = "cffr" - ) - - tmp <- tempfile("DESCRIPTION_basic") - # Create a temporary file - file.copy(basic_path, tmp) - - newfile <- desc::desc_set("Package", "ggplot2", file = tmp) - - parsed <- cff_create(tmp, gh_keywords = FALSE) - expect_length(parsed$repository, 1) - expect_equal(clean_str(newfile$get("Package")), "ggplot2") - expect_equal(parsed$repository, "https://CRAN.R-project.org/package=ggplot2") - - - - expect_s3_class(parsed, "cff") - expect_snapshot(parsed) - expect_true(cff_validate(parsed, verbose = FALSE)) -}) - - -test_that("Search package on r-universe", { - skip_on_cran() - skip_if_offline() - - basic_path <- system.file("examples/DESCRIPTION_basic", - package = "cffr" - ) - - tmp <- tempfile("DESCRIPTION_basic") - # Create a temporary file - file.copy(basic_path, tmp) - - - # Get packages from my r-universe - dhh <- unlist(jsonlite::read_json( - "https://dieghernan.r-universe.dev/packages" - ))[1] - - - newpack <- desc::desc(tmp) - - oldtitle <- clean_str(newpack$get("Package")) - - newtitle <- desc::desc_set("Package", dhh, file = tmp) - - expect_false(oldtitle == clean_str(newtitle$get("Package"))) - - - # Configure to search on r-universe - newrepos <- c( - dieghernan = "https://dieghernan.r-universe.dev", - CRAN = "https://cloud.r-project.org" - ) - - runiverse <- as.data.frame(available.packages( - repos = newrepos - )) - - expect_equal( - search_on_repos(dhh, runiverse), - "https://dieghernan.r-universe.dev/" - ) - - - # Search now ggplot2, should be canonical url - - expect_equal( - search_on_repos("ggplot2", runiverse, newrepos), - "https://CRAN.R-project.org/package=ggplot2" - ) -}) - - -test_that("Validate keywords", { - desc_path <- system.file("examples/DESCRIPTION_basic", - package = "cffr" - ) - - tmp <- tempfile("DESCRIPTION_keyword") - - copy <- file.copy(desc_path, tmp) - - cffobj <- cff_create(tmp) - expect_null(cffobj$keywords) - - expect_true(cff_validate(cffobj, verbose = FALSE)) - - # Add keywords - silent <- desc::desc_set("X-schema.org-keywords", - "keyword1, keyword1, keyword3", - file = tmp - ) - cffobj2 <- cff_create(tmp) - expect_length(cffobj2$keywords, 2) - expect_equal(cffobj2$keywords, c("keyword1", "keyword3")) - expect_true(cff_validate(cffobj2, verbose = FALSE)) - - # Single keyword - silent <- desc::desc_set("X-schema.org-keywords", - "keyword1, keyword1", - file = tmp - ) - cffobj3 <- cff_create(tmp) - expect_length(cffobj3$keywords, 2) - expect_equal(cffobj3$keywords, c("keyword1", "r-package")) - expect_true(cff_validate(cffobj3, verbose = FALSE)) - - # NULL case keyword - silent <- desc::desc_set("X-schema.org-keywords", - "r-package", - file = tmp - ) - cffobj4 <- cff_create(tmp) - expect_null(cffobj4$keywords) - expect_true(cff_validate(cffobj4, verbose = FALSE)) -}) - - -test_that("Parse keywords from GH", { - skip_on_cran() - skip_if_offline() - skip_if( - nchar(Sys.getenv("GITHUB_TOKEN")) == 0, - "No GITHUB_TOKEN environment variable found" - ) - - desc_path <- system.file("examples/DESCRIPTION_basic", - package = "cffr" - ) - - tmp <- tempfile("DESCRIPTION_keyword_gh") - - copy <- file.copy(desc_path, tmp) - - cffobj <- cff_create(tmp) - expect_null(cffobj$keywords) - - expect_true(cff_validate(cffobj, verbose = FALSE)) - - # A site with no topics - silent <- desc::desc_set("BugReports", - "https://github.com/dieghernan/cfftest/issues", - file = tmp - ) - - cffobjnokeys <- cff_create(tmp) - expect_true(cff_validate(cffobjnokeys, verbose = FALSE)) - expect_null(cffobjnokeys$keywords) - - # Add keywords from url - silent <- desc::desc_set("URL", - "https://github.com/ropensci/cffr", - file = tmp - ) - - silent <- desc::desc_set("BugReports", - "https://github.com/ropensci/cffr/issues", - file = tmp - ) - - cffobj1 <- cff_create(tmp) - expect_true(cff_validate(cffobj1, verbose = FALSE)) - expect_false(is.null(cffobj1$keywords)) - - # Concatenate keywords of both sources - - # Add keywords - silent <- desc::desc_set("X-schema.org-keywords", - "keyword1", - file = tmp - ) - - cffobj2 <- cff_create(tmp) - expect_true(cff_validate(cffobj2, verbose = FALSE)) - - expect_true(length(cffobj2$keywords) > length(cffobj1$keywords)) -}) diff --git a/tests/testthat/test-cff_parse_citation.R b/tests/testthat/test-cff_parse_citation.R deleted file mode 100644 index 096d1487..00000000 --- a/tests/testthat/test-cff_parse_citation.R +++ /dev/null @@ -1,215 +0,0 @@ -test_that("Test citations with installed packages", { - installed <- as.character(installed.packages()[, 1]) - inst <- c("base", "jsonlite", "rmarkdown") - for (i in seq_len(length(inst))) { - if (inst[i] %in% installed) { - desc <- cff_create(inst[i]) - expect_true(length(desc$`preferred-citation`) > 1) - expect_true(cff_validate(desc, verbose = FALSE)) - } - } -}) - -test_that("Test full with CITATION and (option = author)", { - # Needs an installed package - desc_path <- system.file("examples/DESCRIPTION_rgeos", package = "cffr") - cit_path <- system.file("examples/CITATION_auto", package = "cffr") - parsed <- parse_r_citation(desc_path, cit_path) - expect_s3_class(parsed, "bibentry") - - # Create cff - cffobj <- cff_create(desc_path, keys = list( - references = lapply(parsed, cff_parse_citation) - )) - - expect_s3_class(cffobj, "cff") - expect_snapshot(cffobj) - expect_true(cff_validate(cffobj, verbose = FALSE)) -}) - - -test_that("Parsed several citations", { - # Needs an installed package - desc_path <- system.file("examples/DESCRIPTION_rgeos", package = "cffr") - cit_path <- system.file("examples/CITATION_auto", package = "cffr") - parsed <- parse_r_citation(desc_path, cit_path) - expect_s3_class(parsed, "bibentry") - - # Create citation obj - citobj <- cff_parse_citation(parsed) - - expect_s3_class(citobj, "cff") - expect_snapshot(citobj) - expect_length(citobj, 3) -}) - - -test_that("Add wrong field to citation", { - bib <- bibentry( - bibtype = "Manual", - title = "favoritefood is not valid on cff schema", - author = "Jane Smith", - favoritefood = "bananas", - type = "I should be removed" - ) - - bibparsed <- cff_parse_citation(bib) - - expect_s3_class(bibparsed, "cff") - - cffobj <- cff_create(cff(), - keys = list( - references = list(bibparsed) - ) - ) - - expect_snapshot(cffobj) - expect_true(cff_validate(cffobj, verbose = FALSE)) -}) - -test_that("Fix wrong orcid", { - bib <- bibentry( - bibtype = "Manual", - title = "Wrong orcid fixed by cffr", - author = person("Jane", - "Smith", - comment = c( - ORCID = - "http://orcid.org/0000-0000-0000-306X" - ) - ) - ) - - bibparsed <- cff_parse_citation(bib) - - expect_s3_class(bibparsed, "cff") - - cffobj <- cff_create(cff(), - keys = list( - references = list(bibparsed) - ) - ) - - expect_snapshot(cffobj) - expect_true(cff_validate(cffobj, verbose = FALSE)) -}) - -test_that("Several identifiers and duplicates", { - bib <- bibentry( - bibtype = "Manual", - title = "A Language and Environment for Statistical Computing", - year = "2022", - year = "2023", - author = person("R Core Team"), - version = NULL, - error = "", - url = "https://www.R-project.org/", - url = "https://google.com/", - doi = "10.5281/zenodo.5366600", - doi = "10.5281/zenodo.5366601", - doi = "10.5281/zenodo.5366602", - identifiers = "a,b" - ) - - bibparsed <- cff_parse_citation(bib) - - expect_s3_class(bibparsed, "cff") - - cffobj <- cff_create(cff(), - keys = list( - references = list(bibparsed) - ) - ) - - expect_snapshot(cffobj) - expect_true(cff_validate(cffobj, verbose = FALSE)) -}) - -test_that("Test keywords and urls", { - bib <- bibentry( - bibtype = "Manual", - title = "A Language and Environment for Statistical Computing", - year = "2022", - author = person("R Core Team"), - url = "https://www.R-project.org/", - url = "https://google.com/", - keywords = "Some, random keywords, in, here, here" - ) - - bibparsed <- cff_parse_citation(bib) - - expect_s3_class(bibparsed, "cff") - - cffobj <- cff_create(cff(), - keys = list( - references = list(bibparsed) - ) - ) - - expect_snapshot(cffobj) - expect_true(cff_validate(cffobj, verbose = FALSE)) -}) - -test_that("Parse persons on CITATION", { - bib <- bibentry("Manual", - title = "A Language and Environment for Statistical Computing", - year = "2021", - author = person("R Core Team"), - contact = c(person("A", "name"), person("A contact")), - conference = person("A", "conference"), - "database-provider" = person("Database", "provider"), - editors = c(person("A", "editor"), person("{Ben and Jerry}")), - "editors-series" = "An {editor series} and Another", - "institution" = person("A", "institution"), - "address" = person("A", "location"), - "publisher" = person("A", "publisher"), - "recipients" = "A recipient", - "senders" = "{A Sender} and Another Sender", - "translators" = c( - person("Translator", "one"), - person("Translator", "two") - ) - ) - - bibparsed <- cff_parse_citation(bib) - expect_snapshot(bibparsed) - - cffobj <- cff_create(cff(), - keys = list(references = list(bibparsed)) - ) - - expect_true(cff_validate(cffobj, verbose = FALSE)) -}) - -test_that("Test inputs", { - bib <- c(1:5) - expect_null(cff_parse_citation(bib)) - - # Remove type - - bib <- bibentry("Book", - title = "Test", - author = "Billy Jean", - year = "2021", - publisher = "Random House", - type = "RANDOM" - ) - - - bibparsed <- cff_parse_citation(bib) - expect_snapshot(bibparsed) - - cffobj <- cff_create(cff(), - keys = list(references = list(bibparsed)) - ) - - expect_true(cff_validate(cffobj, verbose = FALSE)) -}) - -test_that("NULL bibs and others strange errors", { - bib <- 1 - expect_null(cff_parse_citation(bib)) - class(bib) <- "bibentry" - bib <- NULL - expect_null(cff_parse_citation(bib)) -}) diff --git a/tests/testthat/test-cff_parse_person.R b/tests/testthat/test-cff_parse_person.R deleted file mode 100644 index 2e169564..00000000 --- a/tests/testthat/test-cff_parse_person.R +++ /dev/null @@ -1,161 +0,0 @@ -test_that("NULL gives NULL", { - expect_null(cff_parse_person(NULL)) - expect_null(cff_parse_person(NA)) -}) - -test_that("Parse one person", { - p <- person("one", "person") - expect_snapshot(cff_parse_person(p)) -}) - -test_that("Parse several persons", { - p <- c( - person("one", "person"), person("another", "human"), - person("and one", "more") - ) - expect_snapshot(cff_parse_person(p)) -}) - - -test_that("Parse bibtex persons", { - s <- "Wright, III, Frank Edwin" - - expect_snapshot(cff_parse_person_bibtex(s)) - - s <- "A person and another and Another one" - - expect_snapshot(cff_parse_person_bibtex(s)) -}) - -test_that("Parse bibtex persons with masks", { - s <- "Elephant and Castle" - - expect_snapshot(cff_parse_person_bibtex(s)) - - s <- "{Elephant and Castle}" - - expect_snapshot(cff_parse_person_bibtex(s)) - - s <- "{Elephant and Castle} and this AND Ltd." - - expect_snapshot(cff_parse_person_bibtex(s)) - - s <- "{Elephant and Castle} and {this AND Ltd.}" - - expect_snapshot(cff_parse_person_bibtex(s)) -}) - - -test_that("Get same results with both", { - s <- "John Foo" - - r <- cff_parse_person(s) - b <- cff_parse_person_bibtex(s) - - expect_identical(r, b) - - ex2 <- "John Foo and Mary Li" - s2 <- cff_parse_person(ex2) - - b2 <- cff_parse_person_bibtex(ex2) - - expect_identical(s2, b2) - - s3 <- cff_parse_person( - c(person(family = "Entity"), person("A", "person")) - ) - - b3 <- cff_parse_person_bibtex("Entity and A person") - - expect_identical(s3, b3) - - s4 <- cff_parse_person(person(family = "A big fat company")) - b4 <- cff_parse_person_bibtex("{A big fat company}") - - expect_identical(s4, b4) -}) - -test_that("R Core Team", { - p <- cff_parse_person(person("R Core", "Team")) - - expect_equal(p$name, "R Core Team") - - p <- cff_parse_person("R Core Team") - - expect_equal(p$name, "R Core Team") -}) - -test_that("Bioconductor", { - # Several tastes of Bioconductor - bio <- person("Bioconductor Package Maintainer", - role = "cre", - email = "maintainer@bioconductor.org" - ) - p <- cff_parse_person(bio) - - expect_equal(p$name, "Bioconductor Package Maintainer") - - p <- cff_parse_person("Bioconductor Package Maintainer") - - expect_equal(p$name, "Bioconductor Package Maintainer") - - p <- cff_parse_person(person("The Bioconductor", "Package Maintainer")) - expect_equal(p$name, "The Bioconductor Package Maintainer") -}) - -test_that("Several emails, select first", { - pp <- person( - given = "John", - family = "Doe", - role = c("aut", "cre", "trl"), - email = c("first_mail@gmail.com", "second_mail@espol.edu.ec") - ) - - p <- cff_parse_person(pp) - - expect_equal(p$email, "first_mail@gmail.com") -}) - - -test_that("Several emails, select second if first no valid", { - pp <- person( - given = "John", - family = "Doe", - role = c("aut", "cre", "trl"), - email = c("first_mail_gmail.com", "second_mail@espol.edu.ec") - ) - - p <- cff_parse_person(pp) - - expect_equal(p$email, "second_mail@espol.edu.ec") -}) - - - -test_that("No valid emails", { - pp <- person( - given = "John", - family = "Doe", - role = c("aut", "cre", "trl"), - email = c("first_mail_gmail.com", "second_mail__espol.edu.ec") - ) - - p <- cff_parse_person(pp) - - expect_equal(p, cff_parse_person(person( - given = "John", - family = "Doe" - ))) - - pp2 <- person( - given = "John", - family = "Doe" - ) - - p2 <- cff_parse_person(pp2) - - expect_equal(p, cff_parse_person(person( - given = "John", - family = "Doe" - ))) -}) diff --git a/tests/testthat/test-cff_read.R b/tests/testthat/test-cff_read.R index 0c437b26..475a83dc 100644 --- a/tests/testthat/test-cff_read.R +++ b/tests/testthat/test-cff_read.R @@ -1,114 +1,194 @@ -test_that("Test errors on cff", { - expect_error(cff("abcde")) - nocff <- system.file("CITATION", - package = "cffR" - ) - expect_error(cff_create(nocff)) +test_that("Test errors on cff_read", { + expect_snapshot(cff_read(c("abcde", "b")), error = TRUE) + expect_snapshot(cff_read("abcde"), error = TRUE) + + f <- system.file("schema/schema.json", package = "cffr") + expect_error(cff_read(f), "Don't recognize the file type of") }) -test_that("Compare blank cff with skeleton", { - skeleton <- system.file("examples/CITATION_skeleton.cff", - package = "cffr" - ) +test_that("cff_read citation.cff", { + expect_snapshot(cff_read_cff_citation("a"), error = TRUE) - fromfile <- cff(skeleton) - fromfunction <- cff() - expect_true(all(unlist(fromfile) == unlist(fromfunction))) + f <- system.file("examples/CITATION_complete.cff", package = "cffr") + f1 <- cff_read(f) + expect_true(cff_validate(f1, verbose = FALSE)) + expect_s3_class(f1, c("cff", "list"), exact = TRUE) - # Validate - expect_true(cff_validate(fromfunction, verbose = FALSE)) + # With the alias + f2 <- cff_read_cff_citation(f) + expect_identical(f1, f2) }) -test_that("Walk trough full lifecycle", { - complete <- system.file("examples/CITATION_complete.cff", - package = "cffr" + +test_that("cff_read DESCRIPTION", { + expect_snapshot(cff_read_description("a"), error = TRUE) + + + f <- system.file("examples/DESCRIPTION_no_URL", package = "cffr") + + f1 <- cff_read(f, gh_keywords = FALSE) + expect_true(cff_validate(f1, verbose = FALSE)) + expect_s3_class(f1, c("cff", "list"), exact = TRUE) + + # With the alias + f2 <- cff_read_description(f, gh_keywords = FALSE) + expect_identical(f1, f2) + + + # Use other params + f1_1 <- cff_read(f, + gh_keywords = FALSE, cff_version = 3000, + authors_roles = c("aut", "cre", "ctb") ) - # Read - read <- cff_read(complete) - expect_s3_class(read, "cff") - expect_true(cff_validate(read, verbose = FALSE)) - expect_snapshot(print_snapshot("Read object", read)) + expect_equal(f1_1$`cff-version`, "3000") + + expect_gt(length(f1_1$authors), length(f1$authors)) + + f2_1 <- cff_read_description(f, + gh_keywords = FALSE, cff_version = 3000, + authors_roles = c("aut", "cre", "ctb") + ) + + expect_identical(f1_1, f2_1) +}) + + +test_that("cff_read bib", { + skip_if_not_installed("bibtex", "0.5.0") + + expect_snapshot(cff_read_bib("a"), error = TRUE) + + + f <- system.file("REFERENCES.bib", package = "cffr") + + f1 <- cff_read(f) + expect_s3_class(f1, c("cff_ref_list", "cff", "list"), exact = TRUE) + expect_gt(length(f1), 1) + + # Specific + f2 <- cff_read_bib(f) + expect_identical(f1, f2) + + + # With encodings + + f <- system.file("examples/example.bib", package = "cffr") + f1_2 <- cff_read(f) + expect_s3_class(f1_2, c("cff_ref_list", "cff", "list"), exact = TRUE) + expect_length(f1_2, 2) - # Modify - modify <- cff_create(read, keys = list(title = "A new title")) - expect_snapshot(print_snapshot("Modify object", modify)) - expect_true(all(unlist(read) == unlist(read))) - expect_true(length(read) == length(modify)) - expect_true(length((setdiff(names(read), names(modify)))) == 0) - expect_false(read$title == modify$title) + d <- f1_2[[2]] + expect_snapshot(d) + f2_2 <- cff_read_bib(f) + expect_identical(f1_2, f2_2) +}) + +test_that("cff_read citation messages", { + expect_snapshot(cff_read_citation("a"), error = TRUE) - # Write - tmp <- tempfile(fileext = ".cff") - cff_write(modify, outfile = tmp, validate = FALSE, verbose = FALSE) - stopifnotexists(tmp) - stopifnotcff(tmp) + f <- system.file("examples/CITATION_basic", package = "cffr") + my_meta <- packageDescription("testthat") - # Validate - expect_true(cff_validate(tmp, verbose = FALSE)) + expect_snapshot(s <- cff_read(f, meta = "aa")) + expect_silent(s <- cff_read(f, meta = NULL)) + expect_silent(s <- cff_read(f, meta = my_meta)) - file.remove(tmp) + # Now try with a file that needs meta + f <- system.file("examples/CITATION_auto", package = "cffr") + + expect_message(s <- cff_read(f), "Trying with") + expect_s3_class(s, c("cff_ref_list", "cff", "list"), exact = TRUE) }) -test_that("Other convertes", { - a <- cff() - expect_s3_class(a, "cff") - a <- cff(a) - expect_s3_class(a, "cff") - a <- as.cff(a) - expect_true(is_cff(a)) - expect_s3_class(a, "cff") - - expect_message(noadd <- cff(address = "New York", version = 5)) - expect_true(is_cff(noadd)) - expect_false(is_cff(list(a = 1, b = 2))) - expect_true(is_cff(as.cff(list(a = 1, b = 2)))) +test_that("cff_read CITATION_basic", { + a_desc <- system.file("examples/DESCRIPTION_basic", package = "cffr") + my_meta <- desc_to_meta(a_desc) + + path <- system.file("examples/CITATION_basic", package = "cffr") + parsed <- cff_read(path, my_meta) + expect_s3_class(parsed, c("cff_ref_list", "cff", "list"), exact = TRUE) + expect_equal(length(parsed), 2) }) +test_that("cff_read CITATION with no encoding", { + desc_path <- system.file("examples/DESCRIPTION_no_encoding", package = "cffr") + cit_path <- system.file("examples/CITATION_basic", package = "cffr") -test_that("Recursive parsing", { - complete <- system.file("examples/CITATION_complete.cff", - package = "cffr" - ) + my_meta <- desc_to_meta(desc_path) + parsed <- cff_read_citation(cit_path, my_meta) + expect_s3_class(parsed, c("cff_ref_list", "cff", "list"), exact = TRUE) +}) + +test_that("cff_read CITATION_auto", { + # Needs an installed package + desc_path <- system.file("examples/DESCRIPTION_rgeos", package = "cffr") + cit_path <- system.file("examples/CITATION_auto", package = "cffr") + my_meta <- desc_to_meta(desc_path) - # Read - read <- cff(complete) + parsed <- cff_read(cit_path, my_meta) - # Test all levels - expect_s3_class(read, "cff") - expect_s3_class(read$authors, "cff") - expect_s3_class(read$authors[[1]], "cff") - expect_s3_class(read$references, "cff") - expect_s3_class(read$references[[1]]$authors, "cff") - expect_s3_class(read$references[[1]]$authors[[1]], "cff") + expect_equal(length(parsed), 3) }) +test_that("cff_read CITATION_rmarkdown", { + desc_path <- system.file("examples/DESCRIPTION_basic", package = "cffr") + cit_path <- system.file("examples/CITATION_rmarkdown", package = "cffr") + + my_meta <- desc_to_meta(desc_path) + parsed <- cff_read(cit_path, my_meta) + + expect_equal(length(parsed), 3) +}) + +test_that("cff_read_safe CITATION_basic", { + desc_path <- system.file("examples/DESCRIPTION_basic", package = "cffr") + cit_path <- system.file("examples/CITATION_basic", package = "cffr") + parsed <- cff_safe_read_citation(desc_path, cit_path) + + expect_s3_class(parsed, c("cff_ref_list", "cff", "list"), exact = TRUE) + expect_equal(length(parsed), 2) +}) + +test_that("cff_read_safe CITATION with no encoding", { + desc_path <- system.file("examples/DESCRIPTION_no_encoding", package = "cffr") + cit_path <- system.file("examples/CITATION_basic", package = "cffr") + + parsed <- cff_safe_read_citation(desc_path, cit_path) + + expect_s3_class(parsed, c("cff_ref_list", "cff", "list"), exact = TRUE) + expect_equal(length(parsed), 2) +}) + +test_that("cff_read_safe CITATION_auto", { + # Needs an installed package + desc_path <- system.file("examples/DESCRIPTION_rgeos", package = "cffr") + cit_path <- system.file("examples/CITATION_auto", package = "cffr") + parsed <- cff_safe_read_citation(desc_path, cit_path) + + expect_s3_class(parsed, c("cff_ref_list", "cff", "list"), exact = TRUE) + expect_equal(length(parsed), 3) +}) + +test_that("cff_read_safe CITATION_rmarkdown", { + desc_path <- system.file("examples/DESCRIPTION_basic", package = "cffr") + cit_path <- system.file("examples/CITATION_rmarkdown", package = "cffr") + + parsed <- cff_safe_read_citation(desc_path, cit_path) + + expect_s3_class(parsed, c("cff_ref_list", "cff", "list"), exact = TRUE) + expect_equal(length(parsed), 3) +}) -test_that("Fuzzy matching of keys on cff", { - expect_message(cff( - tittle = "a", - cff_version = "ar", - version = "200", - messange = "Fix my keys" - ), "messange: message") - - cffobj <- suppressMessages( - cff( - tittle = "a", - cff_version = "1.2.0", - version = "200", - anthor = list(list( - "family-names" = "a", - "given-names" = "b" - )), - messange = "Fix my keys" - ) - ) - expect_true(is_cff(cffobj)) - expect_true(cff_validate(cffobj, verbose = FALSE)) +test_that("cff_read_safe CITATION NULL", { + desc_path <- system.file("x", package = "cffr") + cit_path <- system.file("y", package = "cffr") - expect_snapshot(print_snapshot("Fuzzy keys", cffobj)) + expect_null(cff_safe_read_citation( + desc_path, + cit_path + )) }) diff --git a/tests/testthat/test-cff_from_bibtex.R b/tests/testthat/test-cff_read_bib_text.R similarity index 55% rename from tests/testthat/test-cff_from_bibtex.R rename to tests/testthat/test-cff_read_bib_text.R index f686b855..174fe4c9 100644 --- a/tests/testthat/test-cff_from_bibtex.R +++ b/tests/testthat/test-cff_read_bib_text.R @@ -1,36 +1,11 @@ -test_that("test errors", { - x <- c(1, 2, 3) - expect_error(cff_from_bibtex(x)) - - x <- cff() - expect_error(cff_from_bibtex(x)) -}) - -test_that("Read from file", { +test_that("Errors and messages", { skip_if_not_installed("bibtex", "0.5.0") - - x <- system.file("REFERENCES.bib", package = "cffr") - - list <- cff_from_bibtex(x) - - expect_s3_class(list, "cff") - expect_gt(length(list), 1) - - - # With encodings - - x2 <- system.file("examples/example.bib", package = "cffr") - fromfile <- cff_from_bibtex(x2) - expect_s3_class(fromfile, "cff") - expect_length(fromfile, 2) - - d <- fromfile[[2]] - - expect_snapshot(d) + a_cff <- cff() + expect_snapshot(cff_read_bib_text(a_cff), error = TRUE) + expect_snapshot(cff_read_bib_text("a bad line"), error = TRUE) }) - -test_that("From Bibtex entries", { +test_that("Read lines", { skip_if_not_installed("bibtex", "0.5.0") x <- c( @@ -52,10 +27,17 @@ test_that("From Bibtex entries", { }" ) - list <- cff_from_bibtex(x) + list <- cff_read_bib_text(x) expect_s3_class(list, "cff") expect_length(list, 2) expect_snapshot(list) + + # Create a Bibtex file with that lines + tmpbib <- tempfile(fileext = ".bib") + writeLines(x, tmpbib) + + expect_snapshot(fromfile <- cff_read_bib_text(tmpbib)) + expect_identical(fromfile, list) }) diff --git a/tests/testthat/test-cff_write.R b/tests/testthat/test-cff_write.R index 84adad4a..f27746cd 100644 --- a/tests/testthat/test-cff_write.R +++ b/tests/testthat/test-cff_write.R @@ -75,10 +75,9 @@ test_that("Add new keys", { message = "This overwrites fields", abstract = "New abstract", keywords = c("A", "new", "list", "of", "keywords"), - authors = list(cff_parse_person(person( - "Don", "Nadie", - comment = c(website = "error") - ))), + authors = as_cff_person( + person("Don", "Nadie", comment = c(website = "error")) + ), "date-released" = "1900-01-01", "error" = "This is an error" ) @@ -117,15 +116,14 @@ test_that("Append keys", { # It should be a list new_aut <- append( old_aut, - list(cff_parse_person(person( - "New", - "author", - comment = c( - "error" = 123, - website = "https://stackoverflow.com/", - country = "IT" + as_cff_person( + person("New", "author", + comment = c( + "error" = 123, website = "https://stackoverflow.com/", + country = "IT" + ) ) - ))) + ) ) tmp <- tempfile(fileext = ".cff") diff --git a/tests/testthat/test-write_bib.R b/tests/testthat/test-cff_write_misc.R similarity index 57% rename from tests/testthat/test-write_bib.R rename to tests/testthat/test-cff_write_misc.R index 8c52b7ef..53da829f 100644 --- a/tests/testthat/test-write_bib.R +++ b/tests/testthat/test-cff_write_misc.R @@ -1,14 +1,5 @@ -test_that("Try not writing", { - bib <- bibentry("Misc", - title = "My title", - author = "Fran Pérez" - ) - - expect_snapshot(write_bib(bib)) - - expect_snapshot(write_bib(bib, ascii = TRUE)) - - expect_error(write_bib(1)) +test_that("Errors", { + expect_snapshot(cff_write_bib(1:4), error = TRUE) }) test_that("Write", { @@ -18,7 +9,7 @@ test_that("Write", { ) file <- file.path(tempdir(), "noext") - expect_message(write_bib(bib, file, verbose = TRUE)) + expect_message(cff_write_bib(bib, file, verbose = TRUE)) # Fix extensions file <- paste0(file, ".bib") @@ -30,7 +21,7 @@ test_that("Write", { expect_false(file.exists(paste0(file, ".bk1"))) # Check now backup exists - write_bib(bib, file, append = TRUE) + cff_write_bib(bib, file, append = TRUE) expect_true(file.exists(paste0(file, ".bk1"))) file.remove(file) @@ -45,7 +36,7 @@ test_that("Write ASCII", { ) file <- file.path(tempdir(), "ascii.bib") - expect_silent(write_bib(bib, file, verbose = FALSE, ascii = TRUE)) + expect_silent(cff_write_bib(bib, file, verbose = FALSE, ascii = TRUE)) # Fix extensions expect_snapshot_file(file) @@ -57,22 +48,25 @@ test_that("Test append", { title = "My title", author = "Fran Herrero" ) + cf <- system.file("examples/DESCRIPTION_basic", package = "cffr") + + a_cff <- cff_read(cf) file <- file.path(tempdir(), "append.bib") - expect_silent(write_bib(bib, file, verbose = FALSE, append = FALSE)) + expect_silent(cff_write_bib(bib, file, verbose = FALSE, append = FALSE)) # Initial lines lines1 <- readLines(file) # Append bib2 <- bibentry("Misc", - key = "key2", - title = "Another title", + key = "key2", title = "Another title", author = "Ian Henderson" ) - write_bib(bib2, file, verbose = FALSE, append = TRUE) + cff_write_bib(bib2, file, verbose = FALSE, append = TRUE) + cff_write_bib(a_cff, file, verbose = FALSE, append = TRUE) expect_snapshot_file(file) lines2 <- readLines(file) @@ -83,7 +77,7 @@ test_that("Test append", { expect_gt(length(lines2), length(lines1)) # Overwrite - write_bib(bib2, file, verbose = FALSE, append = FALSE) + cff_write_bib(bib2, file, verbose = FALSE, append = FALSE) lines3 <- readLines(file) expect_false(all(lines1 == lines3[seq_len(length(lines1))])) @@ -102,7 +96,7 @@ test_that("Test dir creation", { dir <- dirname(file) expect_false(dir.exists(dir)) - expect_silent(write_bib(bib, file, verbose = FALSE)) + expect_silent(cff_write_bib(bib, file, verbose = FALSE)) expect_true(dir.exists(dir)) expect_true(file.exists(file)) @@ -113,10 +107,42 @@ test_that("Test dir creation", { file <- file.path(tempdir(), "nowiamverbose", "append.bib") dir <- dirname(file) expect_false(dir.exists(dir)) - expect_message(write_bib(bib, file, verbose = TRUE), "Creating directory") + expect_message(cff_write_bib(bib, file, verbose = TRUE), "Creating directory") expect_true(dir.exists(dir)) expect_true(file.exists(file)) unlink(dir, recursive = TRUE, force = TRUE) }) + +test_that("Errors citation", { + expect_snapshot(cff_write_citation(1:4), error = TRUE) +}) + +test_that("Write CITATION", { + f <- system.file("examples", package = "cffr") + thepath <- list.files(f, pattern = "DESCRIPTION_basicdate", full.names = TRUE) + f1 <- cff_read(thepath) + + bib <- bibentry("Misc", + title = "My title", + author = "Fran Pérez" + ) + + file <- file.path(tempdir(), "CITAT_ION") + expect_message(cff_write_citation(bib, file, verbose = TRUE)) + + # Check backup + expect_false(file.exists(paste0(file, ".bk1"))) + + # Check now backup exists and use cff + expect_silent(cff_write_citation(f1, file, + verbose = FALSE, + what = "all", append = TRUE + )) + + expect_snapshot_file(file) + + file.remove(file) + file.remove(paste0(file, ".bk1")) +}) diff --git a/tests/testthat/test-deprecated.R b/tests/testthat/test-deprecated.R index 7097e013..92b21978 100644 --- a/tests/testthat/test-deprecated.R +++ b/tests/testthat/test-deprecated.R @@ -1,8 +1,84 @@ test_that("cff_extract_to_bibtex", { a_cff <- cff_create("cffr") - current <- cff_to_bibentry(a_cff) + current <- as_bibentry(a_cff) expect_snapshot(old1 <- cff_extract_to_bibtex(a_cff)) expect_identical(current, old1) }) + +test_that("cff_to_bibtex", { + a_cff <- cff_create("cffr") + + current <- as_bibentry(a_cff) + expect_snapshot(old1 <- cff_to_bibtex(a_cff)) + + expect_identical(current, old1) +}) + +test_that("cff_from_bibtex", { + # From file + x2 <- system.file("examples/example.bib", package = "cffr") + expect_snapshot(ffile <- cff_from_bibtex(x2)) + expect_identical(ffile, cff_read_bib(x2)) + + # From lines + x <- "@book{einstein1921, + title = {Relativity: The Special and the General Theory}, + author = {Einstein, Albert}, + year = 1920, + publisher = {Henry Holt and Company}, + address = {London, United Kingdom}, + isbn = 9781587340925 + }" + + expect_snapshot(flines <- cff_from_bibtex(x)) + expect_identical(flines, cff_read_bib_text(x)) +}) + +test_that("write_bib", { + bib <- bibentry("Misc", + title = "My title", + author = "Fran Pérez" + ) + + tmp <- tempfile(fileext = ".bib") + expect_snapshot(write_bib(bib, tmp, verbose = FALSE)) + + expect_snapshot(cat(readLines(tmp), sep = "\n")) +}) + +test_that("write_citation", { + bib <- bibentry("Misc", + title = "My title", + author = "Fran Pérez" + ) + + tmp <- tempfile("CIT_ATION") + expect_snapshot(write_citation(bib, tmp, verbose = FALSE)) + + expect_snapshot(cat(readLines(tmp), sep = "\n")) +}) + + +test_that("cff_parse_person", { + p <- person("A", "person") + expect_snapshot(pend <- cff_parse_person(p)) + + expect_identical(pend, as_cff_person(p)) +}) + +test_that("cff_parse_person_bibtex", { + p <- "{Elephant and Castle}" + expect_snapshot(pend <- cff_parse_person_bibtex(p)) + + expect_identical(pend, as_cff_person(p)) +}) + + +test_that("cff_parse_citation", { + p <- citation("testthat") + expect_snapshot(pend <- cff_parse_citation(p)) + + expect_identical(pend, as_cff(p)) +}) diff --git a/tests/testthat/test-encoding.R b/tests/testthat/test-encoding.R index 050c3290..243f7b49 100644 --- a/tests/testthat/test-encoding.R +++ b/tests/testthat/test-encoding.R @@ -8,18 +8,14 @@ test_that("Creating cff from packages encoded in latin1", { expect_true(desc::desc(desc_path)$get("Encoding") == "latin1") # Parse citation - bib <- parse_r_citation(desc_path, cit_path) - expect_false("UTF-8" %in% Encoding(unlist(bib))) + bib <- cff_safe_read_citation(desc_path, cit_path) - # Parse to cff citation - bibparsed <- lapply(bib, cff_parse_citation) - - expect_true("UTF-8" %in% Encoding(unlist(bibparsed))) - expect_false("latin1" %in% Encoding(unlist(bibparsed))) + expect_true("UTF-8" %in% Encoding(unlist(bib))) + expect_false("latin1" %in% Encoding(unlist(bib))) # Create cff cffobj <- cff_create(desc_path, keys = list( - references = bibparsed + references = bib )) expect_s3_class(cffobj, "cff") diff --git a/tests/testthat/test-merge_desc_cit.R b/tests/testthat/test-merge_desc_cit.R index 54bb3113..545c5df7 100644 --- a/tests/testthat/test-merge_desc_cit.R +++ b/tests/testthat/test-merge_desc_cit.R @@ -8,11 +8,10 @@ test_that("Merge all DESCRIPTION files with CITATION_basic", { package = "cffr" ) for (i in seq_len(length(allfiles))) { - desc_parse <- cff_description(allfiles[i], gh_keywords = FALSE) - generate_cit <- parse_r_citation(allfiles[i], citpath) - parse_cit <- lapply(generate_cit, cff_parse_citation) - merged <- merge_desc_cit(desc_parse, parse_cit) - merged <- as.cff(merged) + desc_parse <- cff_read_description(allfiles[i], gh_keywords = FALSE) + generate_cit <- cff_safe_read_citation(allfiles[i], citpath) + merged <- merge_desc_cit(desc_parse, generate_cit) + merged <- as_cff(merged) expect_snapshot(merged) diff --git a/tests/testthat/test-mock-package.R b/tests/testthat/test-mock-package.R index 470cf02e..265f0ed7 100644 --- a/tests/testthat/test-mock-package.R +++ b/tests/testthat/test-mock-package.R @@ -24,7 +24,7 @@ test_that("Test in mock package", { ) - expect_silent(write_citation(cit, verbose = FALSE)) + expect_silent(cff_write_citation(cit, "./inst/CITATION", verbose = FALSE)) expect_true(file.exists("./inst/CITATION")) # Create Rbuildignore diff --git a/tests/testthat/test-parse_citation.R b/tests/testthat/test-parse_citation.R deleted file mode 100644 index 8ff06fea..00000000 --- a/tests/testthat/test-parse_citation.R +++ /dev/null @@ -1,77 +0,0 @@ -test_that("Parse CITATION_basic", { - desc_path <- system.file("examples/DESCRIPTION_basic", package = "cffr") - cit_path <- system.file("examples/CITATION_basic", package = "cffr") - parsed <- parse_r_citation(desc_path, cit_path) - - expect_s3_class(parsed, "citation") - expect_equal(length(parsed), 2) - - # Identical to - meta <- as.list(read.dcf(desc_path)[1, ]) - meta$Encoding <- "UTF-8" - - id <- utils::readCitationFile(cit_path, meta = meta) - - expect_identical(parsed, id) -}) - -test_that("Parse CITATION with no encoding", { - desc_path <- system.file("examples/DESCRIPTION_no_encoding", package = "cffr") - cit_path <- system.file("examples/CITATION_basic", package = "cffr") - - parsed <- parse_r_citation(desc_path, cit_path) - - expect_s3_class(parsed, "citation") - expect_equal(length(parsed), 2) - - # Identical to - meta <- as.list(read.dcf(desc_path)[1, ]) - id <- utils::readCitationFile(cit_path, meta = meta) - - expect_identical(parsed, id) -}) - -test_that("Parse CITATION_auto", { - # Needs an installed package - desc_path <- system.file("examples/DESCRIPTION_rgeos", package = "cffr") - cit_path <- system.file("examples/CITATION_auto", package = "cffr") - parsed <- parse_r_citation(desc_path, cit_path) - - expect_s3_class(parsed, "citation") - expect_equal(length(parsed), 3) - - # Identical to - meta <- as.list(read.dcf(desc_path)[1, ]) - id <- utils::readCitationFile(cit_path, meta = meta) - - expect_identical(parsed, id) -}) - -test_that("Parse CITATION_rmarkdown", { - desc_path <- system.file("examples/DESCRIPTION_basic", package = "cffr") - cit_path <- system.file("examples/CITATION_rmarkdown", package = "cffr") - - parsed <- parse_r_citation(desc_path, cit_path) - - expect_s3_class(parsed, "citation") - expect_equal(length(parsed), 3) - - # Identical to - meta <- as.list(read.dcf(desc_path)[1, ]) - meta$Encoding <- "UTF-8" - - id <- utils::readCitationFile(cit_path, meta = meta) - - expect_identical(parsed, id) -}) - - -test_that("Parse CITATION NULL", { - desc_path <- system.file("x", package = "cffr") - cit_path <- system.file("y", package = "cffr") - - expect_null(parse_r_citation( - desc_path, - cit_path - )) -}) diff --git a/tests/testthat/test-utils-persons.R b/tests/testthat/test-utils-persons.R index 39ab5710..17187dbb 100644 --- a/tests/testthat/test-utils-persons.R +++ b/tests/testthat/test-utils-persons.R @@ -1,132 +1,134 @@ -# Based on https://maverick.inria.fr/~Xavier.Decoret/resources/xdkbibtex/bibtex_summary.html +# Based on +# https://maverick.inria.fr/~Xavier.Decoret/resources/xdkbibtex/ >> +# bibtex_summary.html test_that("Test first von last", { x <- "AA BB" - res <- as_person_bibtex(x) + res <- create_person_from_txt(x) expect_true(is.list(res)) expect_snapshot(unlist(res)) x <- "AA" - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) x <- "AA bb" - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) x <- "aa" - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) x <- "AA bb CC" - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) x <- "AA bb CC dd EE" - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) x <- "AA {b}B cc dd" - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) x <- "AA \\BB{b} cc dd" - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) x <- "AA {bb} cc DD" - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) x <- "AA bb {cc} DD" - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) x <- "AA {bb} CC" - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) }) test_that("Testing with random names First von Last", { x <- "Jean de La Fontaine" - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) x <- "Diego {Hernandez Sanz}" - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) x <- "Juan Manuel Miramontes" - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) x <- "Juan Manuel {Miramontes Garcia}" - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) x <- "Juan Manuel van Halen" - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) x <- "Bosco {de la Cruz y Ochoa}" - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) }) test_that("Test von Last, First", { x <- "bb CC, AA" - res <- as_person_bibtex(x) + res <- create_person_from_txt(x) expect_true(is.list(res)) expect_snapshot(unlist(res)) x <- "bb CC, aa" - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) x <- "bb CC dd EE, AA" - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) x <- "bb, AA" - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) x <- "BB," - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) }) test_that("Test von Last, First with brackets, etc", { x <- "de Armas, Ana" - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) x <- "{de Armas}, Ana" - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) x <- "{de Armas, Aguero}, Ana" - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) x <- "{de Armas, Aguero}, Ana Maria" - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) }) test_that("Test von Last, Jr, First", { x <- "bb CC,XX, AA" - res <- as_person_bibtex(x) + res <- create_person_from_txt(x) expect_true(is.list(res)) expect_snapshot(unlist(res)) x <- "BB,, AA" - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) x <- "BB, AA," - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) }) test_that("Test von Last, Jr, First with masking", { x <- "Davis, Jr, Sammy" - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) x <- "{Davis, and}, {Jr, another}, Sammy" - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) }) test_that("Rest of cases", { x <- "David, and, Jr, another, Sammy" - res <- as_person_bibtex(x) + res <- create_person_from_txt(x) expect_true(is.list(res)) expect_length(res, 1) @@ -138,41 +140,41 @@ test_that("tames da beast", { # http://tug.ctan.org/info/bibtex/tamethebeast/ttb_en.pdf x <- "jean de la fontaine" - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) x <- "Jean de la fontaine " - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) x <- "Jean {de} la fontaine " - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) x <- "jean {de} {la} fontaine " - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) x <- "Jean {de} {la} fontaine " - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) x <- "Jean De La Fontaine " - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) x <- "jean De la Fontaine " - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) x <- "Jean de La Fontaine " - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) x <- "jean de la fontaine," - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) x <- "de la fontaine, Jean " - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) x <- "De La Fontaine, Jean" - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) x <- "De la Fontaine, Jean" - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) x <- "de La Fontaine, Jean" - expect_snapshot(unlist(as_person_bibtex(x))) + expect_snapshot(unlist(create_person_from_txt(x))) }) diff --git a/tests/testthat/test-write_citation.R b/tests/testthat/test-write_citation.R deleted file mode 100644 index 6189200d..00000000 --- a/tests/testthat/test-write_citation.R +++ /dev/null @@ -1,112 +0,0 @@ -test_that("Write", { - bib <- bibentry("Misc", - title = "My title", - author = "Fran Pérez" - ) - - file <- file.path(tempdir(), "noext") - expect_message(write_citation(bib, file, verbose = TRUE)) - - # Fix extensions - - expect_snapshot_file(file) - - # Check backup - expect_false(file.exists(paste0(file, ".bk1"))) - - # Check now backup exists - write_citation(bib, file, append = TRUE) - expect_true(file.exists(paste0(file, ".bk1"))) - - file.remove(file) - file.remove(paste0(file, ".bk1")) -}) - -test_that("Test append", { - bib <- bibentry("Misc", - title = "My title", - author = "Fran Herrero" - ) - - file <- file.path(tempdir(), "append") - expect_silent(write_citation(bib, file, verbose = FALSE, append = FALSE)) - - # Initial lines - lines1 <- readLines(file) - - # Append - bib2 <- bibentry("Misc", - key = "key2", - title = "Another title", - author = "Ian Henderson" - ) - - - write_citation(bib2, file, verbose = FALSE, append = TRUE) - expect_snapshot_file(file) - - lines2 <- readLines(file) - - # First lines identical, more lines on append - expect_true(all(lines1 == lines2[seq_len(length(lines1))])) - - expect_gt(length(lines2), length(lines1)) - - # Overwrite - write_citation(bib2, file, verbose = FALSE, append = FALSE) - lines3 <- readLines(file) - - expect_false(all(lines1 == lines3[seq_len(length(lines1))])) - expect_lt(length(lines3), length(lines2)) -}) - - -test_that("Test dir creation", { - bib <- bibentry("Misc", - title = "My title", - author = "Fran Herrero" - ) - - file <- file.path(tempdir(), "citdontexist", "append") - - dir <- dirname(file) - - expect_false(dir.exists(dir)) - expect_silent(write_citation(bib, file, verbose = FALSE)) - - expect_true(dir.exists(dir)) - expect_true(file.exists(file)) - - unlink(dir, recursive = TRUE, force = TRUE) - # With messages - file <- file.path(tempdir(), "citverbose", "append") - dir <- dirname(file) - expect_false(dir.exists(dir)) - expect_message( - write_citation(bib, file, verbose = TRUE), - "Creating directory" - ) - - expect_true(dir.exists(dir)) - expect_true(file.exists(file)) - - unlink(dir, recursive = TRUE, force = TRUE) -}) - - -test_that("Results can be parsed", { - file <- system.file("examples/CITATION_complete.cff", - package = "cffr" - ) - - tmp <- tempfile() - expect_silent(sil <- write_citation(file, tmp, verbose = FALSE)) - - expect_s3_class(sil, "bibentry") - - pp <- utils::readCitationFile(tmp, meta = list(Encoding = "UTF-8")) - - expect_s3_class(pp, "bibentry") - - expect_snapshot_output(toBibtex(pp)) -}) diff --git a/tests/testthat/test-bibtex-check-ruby.R b/tests/testthat/test-xtra-check-bibtex-ruby.R similarity index 84% rename from tests/testthat/test-bibtex-check-ruby.R rename to tests/testthat/test-xtra-check-bibtex-ruby.R index 6dd4f780..f49ceed3 100644 --- a/tests/testthat/test-bibtex-check-ruby.R +++ b/tests/testthat/test-xtra-check-bibtex-ruby.R @@ -1,5 +1,5 @@ # See ´ -# https://github.com/citation-file-format/ruby-cff/tree/main/test/files/formatted +# https://github.com/citation-file-format/ruby-cff/tree/main/test/files test_that("preferred-citation-book-missing", { @@ -7,7 +7,7 @@ test_that("preferred-citation-book-missing", { package = "cffr" ) - expect_warning(expect_error(cff_to_bibentry(x))) + expect_snapshot(as_bibentry(x)) }) test_that("preferred-citation-book", { @@ -15,7 +15,7 @@ test_that("preferred-citation-book", { package = "cffr" ) - bib <- cff_to_bibentry(x) + bib <- as_bibentry(x) expect_snapshot(toBibtex(bib)) }) @@ -24,7 +24,7 @@ test_that("preferred-citation-conference-paper-2", { package = "cffr" ) - bib <- cff_to_bibentry(x) + bib <- as_bibentry(x) expect_snapshot(toBibtex(bib)) }) @@ -33,7 +33,7 @@ test_that("preferred-citation-conference-paper-missing", { package = "cffr" ) - bib <- cff_to_bibentry(x) + bib <- as_bibentry(x) expect_snapshot(toBibtex(bib)) }) @@ -42,7 +42,7 @@ test_that("preferred-citation-conference-paper", { package = "cffr" ) - bib <- cff_to_bibentry(x) + bib <- as_bibentry(x) expect_snapshot(toBibtex(bib)) }) @@ -51,7 +51,7 @@ test_that("preferred-citation-manual", { package = "cffr" ) - bib <- cff_to_bibentry(x) + bib <- as_bibentry(x) expect_snapshot(toBibtex(bib)) }) @@ -60,7 +60,7 @@ test_that("preferred-citation-no-month", { package = "cffr" ) - bib <- cff_to_bibentry(x) + bib <- as_bibentry(x) expect_snapshot(toBibtex(bib)) }) @@ -69,7 +69,7 @@ test_that("preferred-citation-no-vol", { package = "cffr" ) - bib <- cff_to_bibentry(x) + bib <- as_bibentry(x) expect_snapshot(toBibtex(bib)) }) @@ -79,7 +79,7 @@ test_that("preferred-citation-pamphlet", { package = "cffr" ) - bib <- cff_to_bibentry(x) + bib <- as_bibentry(x) expect_snapshot(toBibtex(bib)) }) @@ -88,7 +88,7 @@ test_that("preferred-citation-report-no-institution", { package = "cffr" ) - bib <- cff_to_bibentry(x) + bib <- as_bibentry(x) expect_snapshot(toBibtex(bib)) }) @@ -97,7 +97,7 @@ test_that("preferred-citation-report", { package = "cffr" ) - bib <- cff_to_bibentry(x) + bib <- as_bibentry(x) expect_snapshot(toBibtex(bib)) }) @@ -107,7 +107,7 @@ test_that("preferred-citation-unpublished", { package = "cffr" ) - bib <- cff_to_bibentry(x) + bib <- as_bibentry(x) expect_snapshot(toBibtex(bib)) }) @@ -116,7 +116,7 @@ test_that("reprozip", { package = "cffr" ) - bib <- cff_to_bibentry(x) + bib <- as_bibentry(x) expect_snapshot(toBibtex(bib)) }) @@ -126,7 +126,7 @@ test_that("smith-et-al", { package = "cffr" ) - bib <- cff_to_bibentry(x) + bib <- as_bibentry(x) expect_snapshot(toBibtex(bib)) }) @@ -135,6 +135,6 @@ test_that("tidyverse-joss-paper", { package = "cffr" ) - bib <- cff_to_bibentry(x) + bib <- as_bibentry(x) expect_snapshot(toBibtex(bib)) }) diff --git a/tests/testthat/test_ci/test-full_cff.R b/tests/testthat/test_ci/test-full_cff.R index 453fe002..2da3ad32 100644 --- a/tests/testthat/test_ci/test-full_cff.R +++ b/tests/testthat/test_ci/test-full_cff.R @@ -2,6 +2,7 @@ # DEPRECATED: SEE ./tests/testthat/test_ci/test-new.R file instead # ---------------------------------------------------------------- +# skip lint # test_that("Test ALL installed packages", { # expect_snapshot_output(print_snapshot("Sessioninfo", sessionInfo())) diff --git a/vignettes/bibtex_cff.Rmd b/vignettes/bibtex_cff.Rmd index c86fdeb6..247e6ed7 100644 --- a/vignettes/bibtex_cff.Rmd +++ b/vignettes/bibtex_cff.Rmd @@ -4,9 +4,8 @@ subtitle: A potential crosswalk bibliography: REFERENCES.bib author: Diego Hernangómez description: >- - This article presents a crosswalk between BibTeX and Citation File Format - [@druskat_citation_2021], as it is performed by the cffr package - [@hernangomez2021]. + This article presents a crosswalk between BibTeX and Citation File Format, as + it is performed by the cffr package. abstract: >- This article introduces a crosswalk between **BibTeX** and the Citation File Format (CFF) [@druskat_citation_2021], as implemented by the **cffr** package @@ -130,11 +129,17 @@ The final results of the entry as a text string would be parsed as[^1]: entry ``` -Additionally, the **cffr** package [@hernangomez2021] incorporates a function -`cff_from_bibtex()` that can be used to read and transform **BibTeX** strings -into different formats: +Additionally, the **cffr** package [@hernangomez2021] incorporates the following +capabilities that can be used to read and transform **BibTeX** format into +different formats: -```{r cffbibread,comment="#>"} +- `cff_read_bib()` reads \*.bib files. +- `cff_read_bib_text()` can read **BibTeX** entries that are already stored in + a variable. +- A S3 method `toBibtex.cff()` that converts from `cff` objects to Bibtex + objects (see `utils::tpBibtex()`). + +```{r cffbibread, comment="#>"} string <- "@book{einstein1921, title = {Relativity: The Special and the General Theory}, author = {Einstein, A.}, @@ -145,16 +150,12 @@ string <- "@book{einstein1921, # To cff library(cffr) -cff_format <- cff_from_bibtex(string) +cff_format <- cff_read_bib_text(string) cff_format -# To citation R format and bibtex -citation_format <- cff_to_bibentry(cff_format) -class(citation_format) -citation_format - -toBibtex(citation_format) +# To BibTeX with S3 method +toBibtex(cff_format) ``` ## BibTeX Definitions @@ -571,13 +572,13 @@ bib <- "@article{article-full, pages = {73+}, note = {This is a full ARTICLE entry}}" -cff_from_bibtex(bib) +cff_read_bib_text(bib) ``` From [CFF]{.underline} to **BibTeX** ```{r echo=FALSE} -toBibtex(cff_to_bibentry(cff_from_bibtex(bib))) +toBibtex(cff_read_bib_text(bib)) ``` ### \@book / \@inbook {#book-inbook} @@ -653,13 +654,13 @@ bib <- "@book{book-full, edition = {Second} }" -cff_from_bibtex(bib) +cff_read_bib_text(bib) ``` From [CFF]{.underline} to **BibTeX** ```{r, echo=FALSE} -toBibtex(cff_to_bibentry(cff_from_bibtex(bib))) +toBibtex(cff_read_bib_text(bib)) ``` **Examples: \@inbook** @@ -703,13 +704,13 @@ bib <- "@inbook{inbook-full, chapter = {1.2} }" -cff_from_bibtex(bib) +cff_read_bib_text(bib) ``` From [CFF]{.underline} to **BibTeX** ```{r echo=FALSE,} -toBibtex(cff_to_bibentry(cff_from_bibtex(bib))) +toBibtex(cff_read_bib_text(bib)) ``` ### \@booklet {#booklet} @@ -762,13 +763,13 @@ bib <- "@booklet{booklet-full, howpublished = {Vernier Art Center} }" -cff_from_bibtex(bib) +cff_read_bib_text(bib) ``` From [CFF]{.underline} to **BibTeX** ```{r echo=FALSE, } -toBibtex(cff_to_bibentry(cff_from_bibtex(bib))) +toBibtex(cff_read_bib_text(bib)) ``` ### \@conference / \@inproceedings {#conf_inproc} @@ -833,13 +834,13 @@ bib <- "@inproceedings{inproceedings-full, organization = {The OX Association for Computing Machinery} }" -cff_from_bibtex(bib) +cff_read_bib_text(bib) ``` From [CFF]{.underline} to **BibTeX** ```{r echo=FALSE,} -toBibtex(cff_to_bibentry(cff_from_bibtex(bib))) +toBibtex(cff_read_bib_text(bib)) ``` ### \@incollection {#incol} @@ -914,13 +915,13 @@ bib <- "@incollection{incollection-full, edition = {Third} }" -cff_from_bibtex(bib) +cff_read_bib_text(bib) ``` From [CFF]{.underline} to **BibTeX** ```{r echo=FALSE,} -toBibtex(cff_to_bibentry(cff_from_bibtex(bib))) +toBibtex(cff_read_bib_text(bib)) ``` ### \@manual @@ -979,13 +980,13 @@ bib <- "@manual{manual-full, edition = {Silver} }" -cff_from_bibtex(bib) +cff_read_bib_text(bib) ``` From [CFF]{.underline} to **BibTeX** ```{r echo=FALSE,} -toBibtex(cff_to_bibentry(cff_from_bibtex(bib))) +toBibtex(cff_read_bib_text(bib)) ``` ### \@mastersthesis / \@phdthesis @@ -1048,13 +1049,13 @@ bib <- "@mastersthesis{mastersthesis-full, type = {Master's project} }" -cff_from_bibtex(bib) +cff_read_bib_text(bib) ``` From [CFF]{.underline} to **BibTeX** ```{r, echo=FALSE} -toBibtex(cff_to_bibentry(cff_from_bibtex(bib))) +toBibtex(cff_read_bib_text(bib)) ``` **Examples: \@phdthesis** @@ -1088,13 +1089,13 @@ bib <- "@phdthesis{phdthesis-full, type = {{PhD} Dissertation} }" -cff_from_bibtex(bib) +cff_read_bib_text(bib) ``` From [CFF]{.underline} to **BibTeX** ```{r echo=FALSE,} -toBibtex(cff_to_bibentry(cff_from_bibtex(bib))) +toBibtex(cff_read_bib_text(bib)) ``` ### \@misc @@ -1151,13 +1152,13 @@ bib <- "@misc{misc-full, howpublished = {Handed out at O'Hare} }" -cff_from_bibtex(bib) +cff_read_bib_text(bib) ``` From [CFF]{.underline} to **BibTeX** ```{r echo=FALSE,} -toBibtex(cff_to_bibentry(cff_from_bibtex(bib))) +toBibtex(cff_read_bib_text(bib)) ``` ### \@proceedings @@ -1225,13 +1226,13 @@ bib <- "@proceedings{proceedings-full, organization = {The OX Association for Computing Machinery} }" -cff_from_bibtex(bib) +cff_read_bib_text(bib) ``` From [CFF]{.underline} to **BibTeX** ```{r echo=FALSE,} -toBibtex(cff_to_bibentry(cff_from_bibtex(bib))) +toBibtex(cff_read_bib_text(bib)) ``` ### \@techreport @@ -1288,13 +1289,13 @@ bib <- "@techreport{techreport-full, type = {Wishful Research Result} }" -cff_from_bibtex(bib) +cff_read_bib_text(bib) ``` From [CFF]{.underline} to **BibTeX** ```{r echo=FALSE,} -toBibtex(cff_to_bibentry(cff_from_bibtex(bib))) +toBibtex(cff_read_bib_text(bib)) ``` ### \@unpublished @@ -1339,13 +1340,13 @@ bib <- "@unpublished{unpublished-minimal, note = {Talk at Fanstord University (this is a minimal UNPUBLISHED entry)} }" -cff_from_bibtex(bib) +cff_read_bib_text(bib) ``` From [CFF]{.underline} to **BibTeX** ```{r echo=FALSE,} -toBibtex(cff_to_bibentry(cff_from_bibtex(bib))) +toBibtex(cff_read_bib_text(bib)) ``` ## Appendix A: **\@inbook** in BibTeX and BibLaTeX {#appendix_inbook} @@ -1412,13 +1413,13 @@ bib <- "@inbook{inbook-biblatex, chapter = {4.5} }" -cff_from_bibtex(bib) +cff_read_bib_text(bib) ``` From [CFF]{.underline} to **BibTeX** ```{r echo=FALSE,} -toBibtex(cff_to_bibentry(cff_from_bibtex(bib))) +toBibtex(cff_read_bib_text(bib)) ``` ## Appendix B: [CFF key:type]{.underline} values {#appendix_cff_type} diff --git a/vignettes/cffr.Rmd b/vignettes/cffr.Rmd index 030c065a..bbed3bd7 100644 --- a/vignettes/cffr.Rmd +++ b/vignettes/cffr.Rmd @@ -35,7 +35,7 @@ information of the following files: [Citation File Format (CFF](https://citation-file-format.github.io/)) [@druskat_citation_2021] (v1.2.0) are plain text files with human- and -machine-readable citation information for software (and datasets). Code +machine-readable citation information for software (and data sets). Code developers can include them in their repositories to let others know how to correctly cite their software. @@ -73,6 +73,7 @@ cff_write() Under the hood, `cff_write()` performs the following tasks: - It extracts the metadata using `cff_create()`. +- Optionally modifies it with `cff_modify()`. - Writes a `CITATION.cff` file using `yaml::write_yaml()`. - Validates the result using `cff_validate()`. @@ -89,10 +90,7 @@ would add or modify contents of it. ### Adding new fields ```{r newfields} -newobject <- cff_create(cff()) - -# For modifying your auto-generated object, run this line instead: -# newoobject <- cff_create() +newobject <- cff() newobject ``` @@ -106,20 +104,18 @@ cff_schema_keys() ``` In this case, we are going to add `url`, `version` and `repository`. We would -also overwrite the `title` key. We just need to create a list and pass it to the -`keys` argument of `cff_create()`: +also overwrite the `title` key. We just need to add those parameters to +`cff_modify()`: ```{r modify} -newkeys <- list( - "url" = "https://ropensci.org/", - "version" = "0.0.1", - "repository" = "https://github.com/ropensci/cffr", +modobject <- cff_modify(newobject, + url = "https://ropensci.org/", + version = "0.0.1", + repository = "https://github.com/ropensci/cffr", # If the field is already present, it would be overridden title = "Modifying a 'cff' object" ) -modobject <- cff_create(newobject, keys = newkeys) - modobject # Validate against the schema @@ -127,11 +123,11 @@ modobject cff_validate(modobject) ``` -### Parsing persons and citations +### Persons and references -**cffr** provides two functions that parse `person` objects and `bibentry` -objects (See `?person` and `?bibentry`). These objects are included in the -**utils** package and are a core part of the metadata of any **R** package. +**cffr** provides two functions that convert `person` and `bibentry` objects +(see `?person` and `?bibentry`) according to the [Citation File Format +schema](https://github.com/citation-file-format/citation-file-format/blob/main/schema-guide.md). Following the previous example, we are going to add a new author first. For doing that, we need first to extract the current author of the package and @@ -157,31 +153,26 @@ chiquito <- person("Gregorio", chiquito -# Parse it -chiquito_parsed <- cff_parse_person(chiquito) +# To cff +chiquito_parsed <- as_cff_person(chiquito) chiquito_parsed # Append to previous authors -# Needs to be append as a list -newauthors <- c(modobject$authors, list(chiquito_parsed)) +newauthors <- c(modobject$authors, chiquito_parsed) newauthors -newauthorobject <- cff_create(modobject, keys = list(authors = newauthors)) +newauthorobject <- cff_modify(modobject, authors = newauthors) newauthorobject cff_validate(newauthorobject) ``` -Now, we may want to add `references` to our data. **cffr** supports two types of -references: - -- References created with `bibentry()` -- References extracted from packages using `citation()` - -On the following example, we would add two references, one of each type: +Now, we may want to add `references` to our data. On the following example, we +would add two references, one created with `bibentry()` and another with +`citation()`: ```{r parsingcits} # Valid reference keys @@ -189,11 +180,7 @@ On the following example, we would add two references, one of each type: cff_schema_definitions_refs() # Auto parsed from another R package -base_r <- cff_parse_citation(citation("base")) - -base_r - -# Create with bibentry +base_r <- citation("base") bib <- bibentry("Book", title = "This is a book", @@ -202,24 +189,23 @@ bib <- bibentry("Book", publisher = "McGraw Hill", volume = 2 ) -bib -# Now parse it +refs <- c(base_r, bib) -bookparsed <- cff_parse_citation(bib) +refs -bookparsed -``` +# Now to cff -Now the process is similar to the example with `person`: we append both -references (as lists) and add them to our object: +refs_cff <- as_cff(refs) -```{r references} -refkeys <- list(references = c(list(base_r), list(bookparsed))) +refs_cff +``` -refkeys +Now the process is similar to the example with `person`: we just modify our +`cff` object: -finalobject <- cff_create(newauthorobject, keys = refkeys) +```{r references} +finalobject <- cff_modify(newauthorobject, references = refs_cff) finalobject @@ -236,13 +222,13 @@ tmp <- tempfile(fileext = ".cff") see_res <- cff_write(finalobject, outfile = tmp) -see_res +cat(readLines(tmp), sep = "\n") ``` -And finally we can read our created `CITATION.cff` file using `cff()`: +And finally we can read our created `CITATION.cff` file using `cff_read()`: ```{r read} -reading <- cff(tmp) +reading <- cff_read(tmp) reading ``` @@ -258,7 +244,7 @@ allkeys <- list( # If the field is already present, it would be overridden title = "Modifying a 'cff' object", authors = newauthors, - references = c(list(base_r), list(bookparsed)) + references = refs_cff ) tmp2 <- tempfile(fileext = ".cff") @@ -268,4 +254,10 @@ res <- cff_write(cff(), outfile = tmp2, keys = allkeys) res ``` +```{r include=FALSE} +# Clean temps +unlink(tmp) +unlink(tmp2) +``` + ## References diff --git a/vignettes/crosswalk.Rmd b/vignettes/crosswalk.Rmd index e1cb1741..cf0bdbd8 100644 --- a/vignettes/crosswalk.Rmd +++ b/vignettes/crosswalk.Rmd @@ -1,8 +1,9 @@ --- title: "From R to CFF" subtitle: "Crosswalk" -description: > - A comprehenshive description of the internal mappings performed by `cffr`. +description: >- + A comprehensive description of the internal mappings performed by + the cffr package. author: Diego Hernangómez bibliography: REFERENCES.bib link-citations: yes @@ -82,7 +83,7 @@ knitr::kable(df, escape = FALSE) ### abstract -This key is extracted from the "Description" field of the DESCRIPTION file. +This key is extracted from the `"Description"` field of the `DESCRIPTION` file.
@@ -110,9 +111,9 @@ cat(pkg$get("Description")) ### authors -This key is parsed from the "Authors" or "Authors\@R" field of the DESCRIPTION -file. By default persons with the role "aut" or "cre" are considered, however -this can be modified via the `authors_roles` parameter. +This key is parsed from the `"Authors"` or `"Authors@R"` field of the +`DESCRIPTION` file. By default persons with the role `"aut"` or `"cre"` are +considered, however this can be modified via the `authors_roles` parameter.
@@ -169,7 +170,7 @@ v1.2.0](https://github.com/citation-file-format/citation-file-format/blob/main/s > - **description**: The commit hash or revision number of the software > version. > -> - **usage**:

+> - **usage**: > > ``` yaml > commit: 1ff847d81f29c45a3a1a5ce73d38e45c2f319bba @@ -181,8 +182,9 @@ v1.2.0](https://github.com/citation-file-format/citation-file-format/blob/main/s ### contact -This key is parsed from the "Authors" or "Authors\@R" field of the DESCRIPTION -file. Only persons with the role "cre" (i.e, the maintainer(s)) are considered. +This key is parsed from the `"Authors"` or `"Authors@R"` field of the +`DESCRIPTION` file. Only persons with the role `"cre"` (i.e, the maintainer(s)) +are considered.
@@ -203,14 +205,12 @@ pkg$get_author() ### date-released -This key is extracted following this logic: +This key is extracted from the `DESCRIPTION` file following this logic: -- "Date" field or, - -- If not present, from "Date/Publication". This is present on packages built - on CRAN and Bioconductor. Or, - -- If not present, from "Packaged", that is present on packages built by the +- `"Date"` field or, +- If not present, from `"Date/Publication"`. This is present on packages built + on **CRAN** and **Bioconductor**. or, +- If not present, from `"Packaged"`, that is present on packages built by the [r-universe](https://r-universe.dev/search/).
@@ -260,7 +260,7 @@ cat(cff_create(tmp)$`date-released`) ### doi {#doi} -This key is parsed from the "doi" field of the +This key is parsed from the `"doi"` field of the [preferred-citation](#preferred-citation) object.
@@ -283,12 +283,12 @@ cat(cff_doi$`preferred-citation`$doi) This key includes all the possible identifiers of the package: -- From the DESCRIPTION field, it includes all the urls not included in +- From the `DESCRIPTION` field, it includes all the urls not included in [url](#url) or [repository-code](#repository-code). -- From the CITATION file, it includes all the dois not included in [doi](#doi) - and the identifiers (if any) not included in the "identifiers" key of - [preferred-citation](#preferred-citation). +- From the `CITATION` file, it includes all the dois not included in + [doi](#doi) and the identifiers (if any) not included in the `"identifiers"` + key of [preferred-citation](#preferred-citation).
@@ -314,8 +314,8 @@ cff_create(file)$identifiers ### keywords -This key is extracted from the DESCRIPTION file. The keywords should appear in -the DESCRIPTION as: +This key is extracted from the `DESCRIPTION` file. The keywords should appear in +the `DESCRIPTION` as: ``` ... @@ -385,7 +385,7 @@ jsonval$`repository-code` ### license -This key is extracted from the "License" field of the DESCRIPTION file. +This key is extracted from the `"License"` field of the `DESCRIPTION` file.
@@ -415,14 +415,18 @@ v1.2.0](https://github.com/citation-file-format/citation-file-format/blob/main/s > dataset is licensed (only for non-standard licenses not included in the > [SPDX License > List](https://github.com/citation-file-format/citation-file-format/blob/main/schema-guide.md#definitionslicense-enum)). -> - **usage**:

-> `yaml license-url: "https://obscure-licenses.com?id=1234"` +> +> - **usage**: +> +> ``` yaml +> license-url: "https://obscure-licenses.com?id=1234" +> ``` [Back to summary](#summary). ### message -This key is extracted from the DESCRIPTION field, specifically as: +This key is extracted from the `DESCRIPTION` field, specifically as: ```{r eval=FALSE} msg <- paste0( @@ -446,9 +450,9 @@ cat(cff_create("jsonlite")$message) ### preferred-citation {#preferred-citation} -This key is extracted from the CITATION file. If several references are -provided, it would select the first citation as the "preferred-citation" and the -rest of them as [references](#references). +This key is extracted from the `CITATION` file. If several references are +provided, it would select the first citation as the `"preferred-citation"` and +the rest of them as [references](#references).
@@ -468,11 +472,11 @@ citation("rmarkdown")[1] ### references {#references} -This key is extracted from the CITATION file if several references are provided. -The first citation is considered as the -[preferred-citation](#preferred-citation) and the rest of them as "references". -It also extracts the package dependencies and adds those to this fields using -`citation(auto = TRUE)` on each dependency. +This key is extracted from the `CITATION` file if several references are +provided. The first citation is considered as the +[preferred-citation](#preferred-citation) and the rest of them as +`"references"`. It also extracts the package dependencies and adds those to this +fields using `citation(auto = TRUE)` on each dependency.
@@ -492,20 +496,20 @@ citation("rmarkdown")[-1] ### repository -This key is extracted from the "Repository" field of the DESCRIPTION file. +This key is extracted from the `"Repository"` field of the `DESCRIPTION` file. Usually, this field is auto-populated when a package is hosted on a repo (like -CRAN or the [r-universe](https://r-universe.dev/)). For packages without this -field on the DESCRIPTION (that is the typical case for an in-development +**CRAN** or the [r-universe](https://r-universe.dev/)). For packages without +this field on the `DESCRIPTION` (that is the typical case for an in-development package), **cffr** would try to search the package on any of the default repositories specified on `options("repos")`. In the case of [Bioconductor](https://bioconductor.org/) packages, those are identified if a ["biocViews"](https://contributions.bioconductor.org/description.html#biocviews) -is present on the DESCRIPTION file. +is present on the `DESCRIPTION` file. -If **cffr** detects that the package is available on CRAN, it would return the -canonical url form of the package (i.e. +If **cffr** detects that the package is available on **CRAN**, it would return +the canonical url form of the package (i.e. ).
@@ -547,33 +551,6 @@ file.copy(norepo, tmp) desc::desc_set("Package", "ggplot2", file = tmp) cat(cff_create(tmp)[["repository"]]) - -# Show what happens if another repo is set - -# Save original config -orig_options <- options() -getOption("repos") - - -# Set new repos -options(repos = c( - tidyverse = "https://tidyverse.r-universe.dev", - CRAN = "https://cloud.r-project.org" -)) - -# Load again the library -# Repos are evaluated on load -unloadNamespace("cffr") -library(cffr) - - -cat(cff_create(tmp)[["repository"]]) - -# Now it is the tidyverse repo, due to our new config! - -# Reset original config -options(orig_options) -getOption("repos") ```
@@ -589,7 +566,7 @@ v1.2.0](https://github.com/citation-file-format/citation-file-format/blob/main/s > - **description**: The URL of the work in a build artifact/binary repository > (when the work is software). > -> - **usage**:

+> - **usage**: > > ``` yaml > repository-artifact: "https://search.maven.org/artifact/org.corpus-tools/cff-maven-plugin/0.4.0/maven-plugin" @@ -599,9 +576,9 @@ v1.2.0](https://github.com/citation-file-format/citation-file-format/blob/main/s ### repository-code {#repository-code} -This key is extracted from the "BugReports" or "URL" fields on the DESCRIPTION -file. **cffr** tries to identify the url of the source on the following -repositories: +This key is extracted from the `"BugReports"` or `"URL"` fields on the +`DESCRIPTION` file. **cffr** tries to identify the url of the source on the +following repositories: - [GitHub](https://github.com/). - [GitLab](https://about.gitlab.com/). @@ -637,7 +614,7 @@ desc::desc(gitlab) ### title -This key is extracted from the "Description" field of the DESCRIPTION file. +This key is extracted from the `"Description"` field of the `DESCRIPTION` file. ```{r eval=FALSE} title <- paste0( @@ -663,16 +640,16 @@ cat(cff_create("testthat")$title) ### type -Fixed value equal to "software". The other possible value is "dataset". See the -description on the [Guide to CFF schema +Fixed value equal to `"software"`. The other possible value is `"dataset"`. See +the description on the [Guide to CFF schema v1.2.0](https://github.com/citation-file-format/citation-file-format/blob/main/schema-guide.md#type). [Back to summary](#summary). ### url {#url} -This key is extracted from the "BugReports" or "URL" fields on the DESCRIPTION -file. It corresponds to the first url that is different to +This key is extracted from the `"BugReports"` or `"URL"` fields on the +`DESCRIPTION` file. It corresponds to the first url that is different to [repository-code](#repository-code).
@@ -696,7 +673,7 @@ desc::desc(manyurls) ### version -This key is extracted from the "Version" field on the DESCRIPTION file. +This key is extracted from the `"Version"` field on the `DESCRIPTION` file. ```{r version} # Should be (>= 3.0.0) diff --git a/vignettes/tweet-1.png b/vignettes/tweet-1.png index 22dc92a4..da3d6dda 100644 Binary files a/vignettes/tweet-1.png and b/vignettes/tweet-1.png differ