Skip to content

Commit

Permalink
Allow for spaces in tags (surrounded by quotes) (#685)
Browse files Browse the repository at this point in the history
Co-authored-by: Bruno Tremblay <bruno.tremblay@lacapitale.com>
  • Loading branch information
Bruno Tremblay committed Dec 29, 2020
1 parent 49f5fcd commit ec55bd0
Show file tree
Hide file tree
Showing 7 changed files with 36 additions and 12 deletions.
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ plumber 1.0.0.9999 Development version
* Guess OpenApi response content type from serializer (@meztez #684)

* Passing `edit = TRUE` to `plumb_api()` will open the API source file (#699)
* Allow for spaces in `@apiTag` and `@tag` when tag is surrended by single or double quotes (#685)

* OpenAPI Specification can be set using a file path. (@meztez #696)

Expand Down
6 changes: 3 additions & 3 deletions R/plumb-block.R
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ plumbBlock <- function(lineNum, file, envir = parent.frame()){
parsers[[parser_alias]] <- arg_list
}

responseMat <- stri_match(line, regex="^#['\\*]\\s*@response\\s+(\\w+)\\s+(\\S.+)\\s*$")
responseMat <- stri_match(line, regex="^#['\\*]\\s*@response\\s+(\\w+)\\s+(\\S.*)\\s*$")
if (!is.na(responseMat[1,1])){
resp <- list()
resp[[responseMat[1,2]]] <- list(description=responseMat[1,3])
Expand All @@ -217,9 +217,9 @@ plumbBlock <- function(lineNum, file, envir = parent.frame()){
params[[name]] <- list(desc=paramMat[1,6], type=apiType, required=required, isArray=isArray)
}

tagMat <- stri_match(line, regex="^#['\\*]\\s*@tag\\s+(\\S.+)\\s*")
tagMat <- stri_match(line, regex="^#['\\*]\\s*@tag\\s+(\"[^\"]+\"|'[^']+'|\\S+)\\s*")
if (!is.na(tagMat[1,1])){
t <- stri_trim_both(tagMat[1,2])
t <- stri_trim_both(tagMat[1,2], pattern = "[[\\P{Wspace}]-[\"']]")
if (is.na(t) || t == ""){
stopOnLine(lineNum, line, "No tag specified.")
}
Expand Down
4 changes: 2 additions & 2 deletions R/plumb-globals.R
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ plumbOneGlobal <- function(fields, argument, envir = parent.frame()){
fields$info$version <- def
},
apiTag={
tagMat <- stri_match(def, regex="^\\s*(\\w+)\\s+(\\S.+)\\s*$")
name <- tagMat[1,2]
tagMat <- stri_match(def, regex="^\\s*(\"[^\"]+\"|'[^']+'|\\S+)\\s+(\\S.*)\\s*$")
name <- stri_trim_both(tagMat[1,2], pattern = "[[\\P{Wspace}]-[\"']]")
description <- tagMat[1,3]
if(!is.null(fields$tags) && name %in% unlist(lapply(fields$tags, "[[", "name"))) {
stop("Error: '", argument, "' - ","Duplicate tag definition specified.")
Expand Down
2 changes: 1 addition & 1 deletion man/serializers.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 9 additions & 3 deletions tests/testthat/test-globals.R
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,12 @@ test_that("plumbGlobals works", {
"#' @apiContact contact",
"#' @apiLicense license",
"#' @apiVersion version",
"#' @apiTag t d",
"#' @apiTag tag description",
"#' @apiTag tag2 description2",
"#' @apiTag tag3 description in part")
"#' @apiTag tag3 description in part",
"#' @apiTag 'tag4 space' spaces",
"#' @apiTag \"tag5 space\" spaces")

fields <- plumbGlobals(lines)

Expand All @@ -39,9 +42,12 @@ test_that("plumbGlobals works", {
license="license",
version="version"
),
tags=list(list(name="tag", description="description"),
tags=list(list(name="t", description="d"),
list(name="tag", description="description"),
list(name="tag2", description="description2"),
list(name="tag3", description="description in part"))
list(name="tag3", description="description in part"),
list(name="tag4 space", description="spaces"),
list(name="tag5 space", description="spaces"))
))

# Test contact and licence object
Expand Down
16 changes: 16 additions & 0 deletions tests/testthat/test-parse-block.R
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,22 @@ test_that("device serializers produce a structure", {
expect_s3_block("#' @serializer pdf", serializer_pdf)
})

test_that("Tags can contains space", {
lines <- c("#* @tag 'test space'",
"#* @tag \"test space2\"")
expect_equal(plumbBlock(length(lines), lines)$tags, c("test space", "test space2"))
})

test_that("single character tag and response", {
lines <- c(
"#' @tag a",
"#' @response 2 b",
"#' @response 4 b c")
b <- plumbBlock(length(lines), lines)
expect_equal(b$tags, "a")
expect_equal(b$responses, list(`2` = list(description = "b"), `4` = list(description = "b c")))
})

test_that("block respect original order of lines for comments, tags and responses", {
lines <- c(
"#' @tag aaa",
Expand Down
7 changes: 4 additions & 3 deletions vignettes/annotations.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Annotation | Argument | Description/References
`@apiContact` | `Contact object` | [Contact Object](http://spec.openapis.org/oas/v3.0.3#contact-object)
`@apiLicense` | `License object` | [License Object](http://spec.openapis.org/oas/v3.0.3#license-object)
`@apiVersion` | `Version` | [Info Object](http://spec.openapis.org/oas/v3.0.3#info-object)
`@apiTag` | `Tag` `Description` | Can be repeated to add multiple tags. [Tag Object](http://spec.openapis.org/oas/v3.0.3#tag-object)
`@apiTag` | `Tag` `Description` | Can be repeated to add multiple tags. Quote with " or ' to use non word character (like spaces) in `Tag`. [Tag Object](http://spec.openapis.org/oas/v3.0.3#tag-object)

##### Annotations example

Expand All @@ -40,6 +40,7 @@ Annotation | Argument | Description/References
#* @apiVersion 1.0.1
#* @apiTag pet Pets operations
#* @apiTag toy Toys operations
#* @apiTag "toy space" Toys operations
```

##### Equivalent programmatic usage
Expand All @@ -55,7 +56,7 @@ pr() %>%
license = list(name = "Apache 2.0", url = "https://www.apache.org/licenses/LICENSE-2.0.html"),
version = "1.0.1"
)
spec$tags <- list(list(name = "pet", description = "Pets operations"), list(name = "toy", description = "Toys operations"))
spec$tags <- list(list(name = "pet", description = "Pets operations"), list(name = "toy", description = "Toys operations"), list(name = "toy space", description = "Toys operations"))
spec
})
```
Expand All @@ -73,7 +74,7 @@ Annotation | Argument | Description/References
`@parser` | `Alias` `[Args list]` | Some parsers accept arguments. See [parsers reference](https://www.rplumber.io/reference/parsers.html). Can be repeated to allow multiple parsers on the same endpoint. Aliases : `r paste0("<code>", registered_parsers(), "</code>", collapse = ", ")` from [`registered_parsers()`](https://www.rplumber.io/reference/register_parser.html).
`@param` | `Name`[`:Type` `Description`] | Enclose `Type` between square brackets `[]` to indicate it is an array. Can be repeated to define different parameters.
`@response` | `Name` `Description` | Simple [Response object](http://spec.openapis.org/oas/v3.0.3#response-object). Can be repeated to define different responses.
`@tags` | `Tag` | Can be repeated to add multiple tags. [Tag field](http://spec.openapis.org/oas/v3.0.3#operation-object)
`@tags` | `Tag` | Can be repeated to add multiple tags. Quote with " or ' to use non word character (like spaces) in `Tag`. [Tag field](http://spec.openapis.org/oas/v3.0.3#operation-object)
`@preempt` | `Filter` | Specify that this endpoint has to execute before `Filter`. [Filters](./programmatic-usage.html#defining-filters)
None | `Comments` | Lines without annotation will be mapped to [Summary field](http://spec.openapis.org/oas/v3.0.3#fixed-fields-6).

Expand Down

0 comments on commit ec55bd0

Please sign in to comment.