Page not found
+The page you requested cannot be found (perhaps it was moved or renamed).
+You may want to try searching to find the page's new location, or use +the table of contents to find the page you are looking for.
+diff --git a/DESCRIPTION b/DESCRIPTION index 1d20477..bad2fbe 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -19,3 +19,6 @@ Suggests: VignetteBuilder: knitr URL: https://noclocks.github.io/noclocksR/ Config/testthat/edition: 3 +Depends: + R (>= 2.10) +LazyData: true diff --git a/dev/pkgdevt.R b/dev/pkgdevt.R index fff35d1..9f93f49 100644 --- a/dev/pkgdevt.R +++ b/dev/pkgdevt.R @@ -10,11 +10,24 @@ # libraries --------------------------------------------------------------- -library(devtools) -library(usethis) -library(roxygen2) - - +require(devtools) +require(usethis) +require(roxygen2) +require(testthat) +require(fusen) +require(lozen) +require(attachment) +require(gitdown) +require(testdown) + +# pak::pak(c("covr", "codemetar", "pkgdown", "pagedown", "bookdown", "rmarkdown")) +# pak::pak("ThinkR-open/lozen") +# pak::pak("ThinkR-open/fusen") +# pak::pak("ThinkR-open/gitdown") +# pak::pak("ThinkR-open/testdown") + +usethis::use_data_raw("gitignore_templates") +usethis::use_data_raw("client_demo_data") # initialize -------------------------------------------------------------- diff --git a/inst/auth0.yml b/inst/auth0.yml new file mode 100644 index 0000000..a74df17 --- /dev/null +++ b/inst/auth0.yml @@ -0,0 +1,7 @@ +name: myApp +remote_url: '' +auth0_config: + api_url: !expr paste0('https://', Sys.getenv('AUTH0_USER'), '.auth0.com') + credentials: + key: !expr Sys.getenv("AUTH0_KEY") + secret: !expr Sys.getenv("AUTH0_SECRET") diff --git a/inst/templates/markdown/coverage_report_explanation.md b/inst/templates/markdown/coverage_report_explanation.md new file mode 100644 index 0000000..2063c77 --- /dev/null +++ b/inst/templates/markdown/coverage_report_explanation.md @@ -0,0 +1,15 @@ +## Description of Coverage Report + +- Total coverage percentage, this is the total number of lines covered by a test divided by the total number of lines requiring testing. +- File = Name of the file, the code coverage is calculated per file. +- Lines = Number of lines in the file, corresponds to the number of lines inside the file. +- Relevant = Corresponds to the lines of code to be tested (i.e. the lines inside the function brackets with the brackets and comments removed). +- Covered = Number of lines covered by a test +- Missed = Number of lines not covered by a test +- Hits/Line = Corresponds to the average number of times specific lines are tested in the file. + + In other words, if I have an 11-lines file where (1) the first 6 lines are tested 4 times, (2) the seventh is tested 1 time, (3) the last 4 are tested 10 times. The calculation is then: ((6 * 4) + 1 + (10 * 4))/11 = 6. This gives the average number of times a line is tested, here 6. +- Coverage = corresponds to the percentage of lines covered by a test. Calculation: Covered / Relevant * 100, number of lines covered by a test divided by the number of lines requiring testing. +- If we go into detail by file, the color code is as follows: + - green line = line tested by at least one test (the x? corresponds to the number of times the line is tested) + - red line = line not covered by a test + - white line = lines not to be tested (comments, ...) diff --git a/pkgdown/assets/coverage/codecoverage_explanation.html b/pkgdown/assets/coverage/codecoverage_explanation.html new file mode 100644 index 0000000..8453663 --- /dev/null +++ b/pkgdown/assets/coverage/codecoverage_explanation.html @@ -0,0 +1,107 @@ + + +
+ + +1 | ++ | + + | +
2 | ++ |
+ #' @importFrom htmltools htmlDependency+ |
+
3 | ++ |
+ shiny_resume_deps <- function() {+ |
+
4 | +! | +
+ htmltools::htmlDependency(+ |
+
5 | +! | +
+ "shiny_resume",+ |
+
6 | +! | +
+ "5.0.6",+ |
+
7 | +! | +
+ src = system.file(+ |
+
8 | +! | +
+ "shiny/startbootstrap-resume-gh-pages/",+ |
+
9 | +! | +
+ package = "noclocksR"+ |
+
10 | ++ |
+ ),+ |
+
11 | +! | +
+ stylesheet = list.files(+ |
+
12 | +! | +
+ system.file(+ |
+
13 | +! | +
+ "shiny/startbootstrap-resume-gh-pages/",+ |
+
14 | +! | +
+ package = "noclocksR"+ |
+
15 | ++ |
+ ),+ |
+
16 | +! | +
+ pattern = "\\.css$",+ |
+
17 | +! | +
+ recursive = TRUE+ |
+
18 | ++ |
+ ),+ |
+
19 | +! | +
+ script = list.files(+ |
+
20 | +! | +
+ system.file(+ |
+
21 | +! | +
+ "shiny/startbootstrap-resume-gh-pages/",+ |
+
22 | +! | +
+ package = "noclocksR"+ |
+
23 | ++ |
+ ),+ |
+
24 | +! | +
+ pattern = "\\.js$",+ |
+
25 | +! | +
+ recursive = TRUE+ |
+
26 | ++ |
+ )+ |
+
27 | ++ |
+ )+ |
+
28 | ++ |
+ }+ |
+
29 | ++ | + + | +
30 | ++ |
+ #' @importFrom htmltools HTML+ |
+
31 | ++ |
+ shiny_resume_head <- function(+ |
+
32 | ++ |
+ title = "Shiny Resume"+ |
+
33 | ++ |
+ ) {+ |
+
34 | ++ | + + | +
35 | +! | +
+ htmltools::HTML(+ |
+
36 | +! | +
+ sprintf(+ |
+
37 | ++ |
+ '+ |
+
38 | +! | +
+ <head>+ |
+
39 | +! | +
+ <meta charset="utf-8">+ |
+
40 | +! | +
+ <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">+ |
+
41 | +! | +
+ <meta name="description" content="">+ |
+
42 | +! | +
+ <meta name="author" content="">+ |
+
43 | ++ | + + | +
44 | +! | +
+ <title>%s</title>+ |
+
45 | ++ | + + | +
46 | +! | +
+ <!-- Bootstrap core CSS -->+ |
+
47 | +! | +
+ <link href="resume-5.0.6/vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet">+ |
+
48 | ++ | + + | +
49 | +! | +
+ <!-- Custom fonts for this template -->+ |
+
50 | +! | +
+ <link href="https://fonts.googleapis.com/css?family=Saira+Extra+Condensed:500,700" rel="stylesheet">+ |
+
51 | +! | +
+ <link href="https://fonts.googleapis.com/css?family=Muli:400,400i,800,800i" rel="stylesheet">+ |
+
52 | +! | +
+ <link href="resume-5.0.6/vendor/fontawesome-free/css/all.min.css" rel="stylesheet">+ |
+
53 | ++ | + + | +
54 | +! | +
+ <!-- Custom styles for this template -->+ |
+
55 | +! | +
+ <link href="resume-5.0.6/css/resume.min.css" rel="stylesheet">+ |
+
56 | ++ | + + | +
57 | +! | +
+ </head>',+ |
+
58 | +! | +
+ title+ |
+
59 | ++ |
+ )+ |
+
60 | ++ |
+ )+ |
+
61 | ++ |
+ }+ |
+
62 | ++ | + + | +
63 | ++ |
+ #' @importFrom htmltools HTML+ |
+
64 | ++ |
+ shiny_resume_scripts <- function() {+ |
+
65 | +! | +
+ htmltools::HTML(+ |
+
66 | +! | +
+ ' <!-- Bootstrap core JavaScript -->+ |
+
67 | +! | +
+ <script src="resume-5.0.6/vendor/jquery/jquery.min.js"></script>+ |
+
68 | +! | +
+ <script src="resume-5.0.6/vendor/bootstrap/js/bootstrap.bundle.min.js"></script>+ |
+
69 | ++ | + + | +
70 | +! | +
+ <!-- Plugin JavaScript -->+ |
+
71 | +! | +
+ <script src="resume-5.0.6/vendor/jquery-easing/jquery.easing.min.js"></script>+ |
+
72 | ++ | + + | +
73 | +! | +
+ <!-- Custom scripts for this template -->+ |
+
74 | +! | +
+ <script src="resume-5.0.6/js/resume.min.js"></script>'+ |
+
75 | ++ |
+ )+ |
+
76 | ++ |
+ }+ |
+
77 | ++ | + + | +
78 | ++ |
+ #' Shiny Resume Body+ |
+
79 | ++ |
+ #'+ |
+
80 | ++ |
+ #' @description+ |
+
81 | ++ |
+ #' Produce the body of the shiny resume page.+ |
+
82 | ++ |
+ #'+ |
+
83 | ++ |
+ #' @param ... A series of [shiny_resume_section()] elements+ |
+
84 | ++ |
+ #'+ |
+
85 | ++ |
+ #' @return HTML via [htmltools::tagList()]+ |
+
86 | ++ |
+ #' @export+ |
+
87 | ++ |
+ #'+ |
+
88 | ++ |
+ #' @importFrom htmltools tagList tags+ |
+
89 | ++ |
+ shiny_resume_body <- function(...) {+ |
+
90 | +! | +
+ htmltools::tagList(+ |
+
91 | +! | +
+ htmltools::tags$div(+ |
+
92 | +! | +
+ class = "container-fluid p-0",+ |
+
93 | ++ |
+ ...,+ |
+
94 | +! | +
+ shiny_resume_scripts()+ |
+
95 | ++ |
+ )+ |
+
96 | ++ |
+ )+ |
+
97 | ++ |
+ }+ |
+
98 | ++ | + + | +
99 | ++ |
+ shiny_resume_section <- function(id, ...){+ |
+
100 | +! | +
+ htmltools::tagList(+ |
+
101 | +! | +
+ htmltools::tags$section(+ |
+
102 | +! | +
+ class = "resume-section p-3 p-lg-5 d-flex align-items-center",+ |
+
103 | +! | +
+ id = id,+ |
+
104 | +! | +
+ htmltools::tags$div(+ |
+
105 | +! | +
+ class = "w-100",+ |
+
106 | ++ |
+ ...+ |
+
107 | ++ |
+ )+ |
+
108 | ++ |
+ )+ |
+
109 | ++ |
+ )+ |
+
110 | ++ |
+ }+ |
+
111 | ++ | + + | +
112 | ++ | + + | +
113 | ++ |
+ #' @importFrom htmltools tags+ |
+
114 | ++ |
+ make_navbar <- function(nav) {+ |
+
115 | +! | +
+ if (is.null(names(nav))) {+ |
+
116 | +! | +
+ names(nav) <- nav+ |
+
117 | ++ |
+ }+ |
+
118 | ++ | + + | +
119 | +! | +
+ mapply(+ |
+
120 | +! | +
+ function(x, y) {+ |
+
121 | +! | +
+ htmltools::tags$li(+ |
+
122 | +! | +
+ class = "nav-item",+ |
+
123 | +! | +
+ htmltools::tags$a(+ |
+
124 | +! | +
+ class = "nav-link js-scroll-trigger",+ |
+
125 | +! | +
+ href = sprintf("#%s", x),+ |
+
126 | +! | +
+ y+ |
+
127 | ++ |
+ )+ |
+
128 | ++ |
+ )+ |
+
129 | ++ |
+ },+ |
+
130 | +! | +
+ names(nav),+ |
+
131 | +! | +
+ nav,+ |
+
132 | +! | +
+ SIMPLIFY = FALSE+ |
+
133 | ++ |
+ )+ |
+
134 | ++ |
+ }+ |
+
135 | ++ | + + | +
136 | ++ | + + | +
137 | ++ |
+ #' Shiny Resume Navigation Bar+ |
+
138 | ++ |
+ #'+ |
+
139 | ++ |
+ #' @description+ |
+
140 | ++ |
+ #' Produce a navigation bar for a shiny resume+ |
+
141 | ++ |
+ #'+ |
+
142 | ++ |
+ #' @param refs Named list with names being IDs and elements being text displayed.+ |
+
143 | ++ |
+ #' @param image Image to place in navbar+ |
+
144 | ++ |
+ #' @param color Color of the sidebar+ |
+
145 | ++ |
+ #'+ |
+
146 | ++ |
+ #' @return HTML via [htmltools::tagList()]+ |
+
147 | ++ |
+ #' @export+ |
+
148 | ++ |
+ #'+ |
+
149 | ++ |
+ #' @importFrom htmltools tags tagList+ |
+
150 | ++ |
+ shiny_resume_navbar <- function(+ |
+
151 | ++ |
+ refs = c("a" = "A"),+ |
+
152 | ++ |
+ image = "img/profile.jpg",+ |
+
153 | ++ |
+ color = "#bd5d38"+ |
+
154 | ++ |
+ ) {+ |
+
155 | +! | +
+ htmltools::tagList(+ |
+
156 | +! | +
+ htmltools::tags$style(+ |
+
157 | +! | +
+ sprintf(".navbar { background-color: %s!important;}", color)+ |
+
158 | ++ |
+ ),+ |
+
159 | +! | +
+ htmltools::tags$nav(+ |
+
160 | +! | +
+ class = "navbar navbar-expand-lg navbar-dark bg-primary fixed-top",+ |
+
161 | +! | +
+ id = "sideNav",+ |
+
162 | +! | +
+ htmltools::tags$a(+ |
+
163 | +! | +
+ class = "navbar-brand js-scroll-trigger",+ |
+
164 | +! | +
+ href = "#page-top",+ |
+
165 | +! | +
+ htmltools::tags$span(+ |
+
166 | +! | +
+ class = "d-block d-lg-none", "nav_title"+ |
+
167 | ++ |
+ ),+ |
+
168 | +! | +
+ htmltools::tags$span(+ |
+
169 | +! | +
+ class = "d-none d-lg-block",+ |
+
170 | +! | +
+ tags$img(+ |
+
171 | +! | +
+ class = "img-fluid img-profile rounded-circle mx-auto mb-2",+ |
+
172 | +! | +
+ src = image,+ |
+
173 | +! | +
+ alt = NA+ |
+
174 | ++ |
+ )+ |
+
175 | ++ |
+ )+ |
+
176 | ++ |
+ ),+ |
+
177 | +! | +
+ htmltools::tags$button(+ |
+
178 | +! | +
+ class = "navbar-toggler",+ |
+
179 | +! | +
+ type = "button",+ |
+
180 | +! | +
+ "data-toggle" = "collapse",+ |
+
181 | +! | +
+ "data-target" = "#navbarSupportedContent",+ |
+
182 | +! | +
+ "aria-controls" = "navbarSupportedContent",+ |
+
183 | +! | +
+ "aria-expanded" = "false",+ |
+
184 | +! | +
+ "aria-label" = "Toggle navigation",+ |
+
185 | +! | +
+ htmltools::tags$span(class = "navbar-toggler-icon")+ |
+
186 | ++ |
+ ),+ |
+
187 | +! | +
+ htmltools::tags$div(+ |
+
188 | +! | +
+ class = "collapse navbar-collapse",+ |
+
189 | +! | +
+ id = "navbarSupportedContent",+ |
+
190 | +! | +
+ htmltools::tags$ul(+ |
+
191 | +! | +
+ class = "navbar-nav",+ |
+
192 | +! | +
+ make_navbar(refs)+ |
+
193 | ++ |
+ )+ |
+
194 | ++ |
+ )+ |
+
195 | ++ |
+ )+ |
+
196 | ++ |
+ )+ |
+
197 | ++ |
+ }+ |
+
198 | ++ | + + | +
199 | ++ | + + | +
200 | ++ |
+ #' Shiny Resume Page+ |
+
201 | ++ |
+ #'+ |
+
202 | ++ |
+ #' @description+ |
+
203 | ++ |
+ #' Shiny App with Bootstrap Resume Template+ |
+
204 | ++ |
+ #'+ |
+
205 | ++ |
+ #' @param app_title Title to use for the app+ |
+
206 | ++ |
+ #' @param nav Navbar, constructed with [shiny_resume_navbar()]+ |
+
207 | ++ |
+ #' @param body Body, constructed with [shiny_resume_body()] & [shiny_resume_section()]+ |
+
208 | ++ |
+ #'+ |
+
209 | ++ |
+ #' @return HTML via [htmltools::tagList()]+ |
+
210 | ++ |
+ #' @export+ |
+
211 | ++ |
+ #'+ |
+
212 | ++ |
+ #' @importFrom htmltools tagList tags+ |
+
213 | ++ |
+ shiny_resume_page <- function(+ |
+
214 | ++ |
+ app_title,+ |
+
215 | ++ |
+ nav,+ |
+
216 | ++ |
+ body+ |
+
217 | ++ |
+ ) {+ |
+
218 | ++ | + + | +
219 | +! | +
+ htmltools::tagList(+ |
+
220 | +! | +
+ htmltools::tags$html(+ |
+
221 | +! | +
+ shiny_resume_deps(),+ |
+
222 | +! | +
+ shiny_resume_head(title = app_title),+ |
+
223 | +! | +
+ htmltools::tags$body(+ |
+
224 | +! | +
+ id = "page-top",+ |
+
225 | +! | +
+ nav,+ |
+
226 | +! | +
+ body+ |
+
227 | ++ |
+ )+ |
+
228 | ++ |
+ )+ |
+
229 | ++ |
+ )+ |
+
230 | ++ |
+ }+ |
+
231 | ++ | + + | +
1 | ++ |
+ git_config_get <- function(key) {+ |
+
2 | ++ | + + | +
3 | +! | +
+ git_config <- gert::git_config_global()+ |
+
4 | ++ | + + | +
5 | +! | +
+ keys <- unique(gitconfig$name)+ |
+
6 | ++ | + + | +
7 | +! | +
+ if (!key %in% keys) {+ |
+
8 | +! | +
+ warning(glue::glue(+ |
+
9 | +! | +
+ "The key '{key}' is not in your git config. Please set it before proceeding."+ |
+
10 | ++ |
+ ))+ |
+
11 | +! | +
+ return(NULL)+ |
+
12 | ++ |
+ }+ |
+
13 | ++ | + + | +
14 | +! | +
+ git_config |>+ |
+
15 | +! | +
+ dplyr::filter(+ |
+
16 | +! | +
+ level %in% c("global", "xdg"),+ |
+
17 | +! | +
+ name == key+ |
+
18 | ++ |
+ ) |>+ |
+
19 | +! | +
+ dplyr::pull(value) |>+ |
+
20 | +! | +
+ unique()+ |
+
21 | ++ |
+ }+ |
+
22 | ++ | + + | +
23 | ++ | + + | +
24 | ++ |
+ assert_git_config <- function() {+ |
+
25 | ++ | + + | +
26 | +! | +
+ gitconfig <- gert::git_config_global()+ |
+
27 | ++ | + + | +
28 | +! | +
+ if (is.null(gitconfig)) {+ |
+
29 | +! | +
+ stop("Please set your git config before proceeding.")+ |
+
30 | ++ |
+ }+ |
+
31 | ++ | + + | +
32 | +! | +
+ user_name <- git_config_get("user.name")+ |
+
33 | +! | +
+ user_email <- git_config_get("user.email")+ |
+
34 | +! | +
+ default_branch <- git_config_get("init.defaultbranch")+ |
+
35 | +! | +
+ signing_key <- git_config_get("user.signingkey")+ |
+
36 | ++ | + + | +
37 | +! | +
+ if (is.null(user_name) | is.null(user_email) | is.null(default_branch) | is.null(signing_key)) {+ |
+
38 | +! | +
+ stop("Please set your git config before proceeding.")+ |
+
39 | ++ |
+ }+ |
+
40 | ++ |
+ }+ |
+
41 | ++ | + + | +
1 | ++ |
+ #' No Clocks `pkgdown`+ |
+
2 | ++ |
+ #'+ |
+
3 | ++ |
+ #' @description+ |
+
4 | ++ |
+ #' Build a [pkgdown::pkgdown()] site with additional options to include+ |
+
5 | ++ |
+ #' extra reports.+ |
+
6 | ++ |
+ #'+ |
+
7 | ++ |
+ #' The reports that can be included are:+ |
+
8 | ++ |
+ #' - Test Results Report via [testdown::testdown()]+ |
+
9 | ++ |
+ #' - Test Coverage Results via [covrpage::covrpage()]+ |
+
10 | ++ |
+ #' - Git Reports via [gitdown::gitdown()]+ |
+
11 | ++ |
+ #'+ |
+
12 | ++ |
+ #' @param pkg (character) Path to the package in development+ |
+
13 | ++ |
+ #' @param pkgdown_path (character) Relative path inside the package to store+ |
+
14 | ++ |
+ #' the final `pkgdown` site+ |
+
15 | ++ |
+ #' @param assets_path (character) Relative path within the package to store+ |
+
16 | ++ |
+ #' the `pkgdown` assets+ |
+
17 | ++ |
+ #' @param reports (character) Vector of reports to be produced. Must be a subset+ |
+
18 | ++ |
+ #' of `c("testdown","gitdown", "coverage")`. The default is+ |
+
19 | ++ |
+ #' `c("coverage", "testdown", "gitdown")`.+ |
+
20 | ++ |
+ #' @param git_branch_ref (character) Git branch to use. `main' by default+ |
+
21 | ++ |
+ #' @param overwrite_assets (logical) Whether the assets directory should be+ |
+
22 | ++ |
+ #' overwritten. Default is `TRUE`.+ |
+
23 | ++ |
+ #'+ |
+
24 | ++ |
+ #' @importFrom fs dir_create file_move+ |
+
25 | ++ |
+ #' @importFrom pkgdown build_site+ |
+
26 | ++ |
+ #'+ |
+
27 | ++ |
+ #' @return None Generate a pkgdown with test and coverage reports+ |
+
28 | ++ |
+ #' @export+ |
+
29 | ++ |
+ #' @examples+ |
+
30 | ++ |
+ #' \dontrun{+ |
+
31 | ++ |
+ #' # build_pkgdown_with_reports(+ |
+
32 | ++ |
+ #' # pkg = ".",+ |
+
33 | ++ |
+ #' # pkgdown_path = "public",+ |
+
34 | ++ |
+ #' # assets_path = "pkgdown/assets",+ |
+
35 | ++ |
+ #' # reports = c("testdown","coverage")+ |
+
36 | ++ |
+ #' }+ |
+
37 | ++ |
+ build_pkgdown_with_reports <- function(+ |
+
38 | ++ |
+ pkg = ".",+ |
+
39 | ++ |
+ pkgdown_path = "public",+ |
+
40 | ++ |
+ assets_path = "pkgdown/assets",+ |
+
41 | ++ |
+ reports = c("coverage", "testdown", "gitdown"),+ |
+
42 | ++ |
+ git_branch_ref = "main",+ |
+
43 | ++ |
+ overwrite_assets = TRUE+ |
+
44 | ++ |
+ ) {+ |
+
45 | ++ |
+ # Selected reports+ |
+
46 | +! | +
+ reports <- match.arg(+ |
+
47 | +! | +
+ arg = reports,+ |
+
48 | +! | +
+ several.ok = TRUE+ |
+
49 | ++ |
+ )+ |
+
50 | ++ | + + | +
51 | ++ |
+ # clear assets dir if needed+ |
+
52 | +! | +
+ if (isTRUE(overwrite_assets)) {+ |
+
53 | +! | +
+ unlink(file.path(pkg, assets_path), recursive = TRUE)+ |
+
54 | ++ |
+ }+ |
+
55 | ++ | + + | +
56 | ++ |
+ # initialize navbar report+ |
+
57 | +! | +
+ menu <- list()+ |
+
58 | +! | +
+ if (length(reports) != 0) {+ |
+
59 | +! | +
+ dir_create(file.path(pkg, assets_path))+ |
+
60 | ++ |
+ }+ |
+
61 | ++ | + + | +
62 | ++ |
+ # generate covr report in a tmp folder and move it to assets path+ |
+
63 | +! | +
+ if (isTRUE("coverage" %in% reports)) {+ |
+
64 | +! | +
+ if (!requireNamespace("covr", quietly = TRUE)) {+ |
+
65 | +! | +
+ stop(+ |
+
66 | +! | +
+ "{covr} needs to be installed"+ |
+
67 | ++ |
+ )+ |
+
68 | ++ |
+ }+ |
+
69 | +! | +
+ if (!requireNamespace("DT", quietly = TRUE)) {+ |
+
70 | +! | +
+ stop(+ |
+
71 | +! | +
+ "{DT} needs to be installed for"+ |
+
72 | ++ |
+ )+ |
+
73 | ++ |
+ }+ |
+
74 | +! | +
+ if (!requireNamespace("htmltools", quietly = TRUE)) {+ |
+
75 | +! | +
+ stop(+ |
+
76 | +! | +
+ "{htmltools} needs to be installed for"+ |
+
77 | ++ |
+ )+ |
+
78 | ++ |
+ }+ |
+
79 | +! | +
+ if (!requireNamespace("markdown", quietly = TRUE)) {+ |
+
80 | +! | +
+ stop(+ |
+
81 | +! | +
+ "{markdown} needs to be installed for"+ |
+
82 | ++ |
+ )+ |
+
83 | ++ |
+ }+ |
+
84 | +! | +
+ covr_pkg <- covr::package_coverage(path = pkg)+ |
+
85 | +! | +
+ covr::report(+ |
+
86 | +! | +
+ x = covr_pkg,+ |
+
87 | +! | +
+ file = file.path(assets_path, "coverage", "coverage.html"),+ |
+
88 | +! | +
+ browse = FALSE+ |
+
89 | ++ |
+ )+ |
+
90 | ++ | + + | +
91 | ++ |
+ # file_move(file.path(pkg, "coverage"), file.path(assets_path, "coverage"))+ |
+
92 | +! | +
+ menu[[length(menu) + 1]] <- list(text = "coverage", href = "coverage/coverage.html")+ |
+
93 | ++ |
+ # Add coverage explanation+ |
+
94 | +! | +
+ markdown::markdownToHTML(+ |
+
95 | +! | +
+ file = system.file(+ |
+
96 | +! | +
+ "package",+ |
+
97 | +! | +
+ "codecoverage_explanation.md",+ |
+
98 | +! | +
+ package = "lozen"+ |
+
99 | ++ |
+ ),+ |
+
100 | +! | +
+ output = file.path(assets_path, "coverage", "codecoverage_explanation.html")+ |
+
101 | ++ |
+ )+ |
+
102 | +! | +
+ menu[[length(menu) + 1]] <- list(+ |
+
103 | +! | +
+ text = "coverage explained",+ |
+
104 | +! | +
+ href = "coverage/codecoverage_explanation.html"+ |
+
105 | ++ |
+ )+ |
+
106 | ++ |
+ }+ |
+
107 | ++ | + + | +
108 | ++ |
+ # generate testdown report in assets path+ |
+
109 | +! | +
+ if (isTRUE("testdown" %in% reports)) {+ |
+
110 | +! | +
+ if (!requireNamespace("testdown", quietly = TRUE)) {+ |
+
111 | +! | +
+ stop(+ |
+
112 | +! | +
+ "{testdown} needs to be installed for",+ |
+
113 | +! | +
+ " `lozen::build_pkgdown_with_reports(reports = 'testdown')`",+ |
+
114 | +! | +
+ " to use `testdown::test_down()`."+ |
+
115 | ++ |
+ )+ |
+
116 | ++ |
+ }+ |
+
117 | ++ | + + | +
118 | +! | +
+ testdown::test_down(+ |
+
119 | +! | +
+ pkg = pkg,+ |
+
120 | +! | +
+ book_path = file.path(assets_path, "testdown"),+ |
+
121 | +! | +
+ open = FALSE+ |
+
122 | ++ |
+ )+ |
+
123 | +! | +
+ menu[[length(menu) + 1]] <- list(text = "testdown", href = "testdown/index.html")+ |
+
124 | ++ |
+ }+ |
+
125 | ++ | + + | +
126 | ++ |
+ # generate gitdown report in assets path+ |
+
127 | +! | +
+ if (isTRUE("gitdown" %in% reports)) {+ |
+
128 | +! | +
+ if (!requireNamespace("gitdown", quietly = TRUE)) {+ |
+
129 | +! | +
+ stop(+ |
+
130 | +! | +
+ "{gitdown} needs to be installed for",+ |
+
131 | +! | +
+ " `lozen::build_pkgdown_with_reports(reports = 'gitdown')`",+ |
+
132 | +! | +
+ " to use `gitdown::git_down()`."+ |
+
133 | ++ |
+ )+ |
+
134 | ++ |
+ }+ |
+
135 | ++ | + + | +
136 | +! | +
+ gitdown::git_down(+ |
+
137 | +! | +
+ repo = pkg,+ |
+
138 | +! | +
+ book_path = file.path(assets_path, "gitdown"),+ |
+
139 | +! | +
+ ref = git_branch_ref,+ |
+
140 | +! | +
+ open = FALSE+ |
+
141 | ++ |
+ )+ |
+
142 | +! | +
+ homepage <- file.path(+ |
+
143 | +! | +
+ "gitdown",+ |
+
144 | +! | +
+ list.files(+ |
+
145 | +! | +
+ pattern = "^gitbook-for",+ |
+
146 | +! | +
+ file.path(assets_path, "gitdown")+ |
+
147 | +! | +
+ )[1]+ |
+
148 | ++ |
+ )+ |
+
149 | +! | +
+ menu[[length(menu) + 1]] <- list(text = "gitdown", href = homepage)+ |
+
150 | ++ |
+ }+ |
+
151 | ++ | + + | +
152 | ++ |
+ # prepare yaml settings to add reports in navbar+ |
+
153 | +! | +
+ yaml_settings <- list(+ |
+
154 | +! | +
+ destination = pkgdown_path,+ |
+
155 | +! | +
+ template = list(+ |
+
156 | +! | +
+ assets = assets_path+ |
+
157 | ++ |
+ ),+ |
+
158 | +! | +
+ navbar = list(+ |
+
159 | +! | +
+ structure = list(+ |
+
160 | +! | +
+ left = c("intro", "reference", "articles", "tutorials", "news", "reports")+ |
+
161 | ++ |
+ ),+ |
+
162 | +! | +
+ components = list(+ |
+
163 | +! | +
+ reports = list(+ |
+
164 | +! | +
+ text = "Reports",+ |
+
165 | +! | +
+ menu = menu+ |
+
166 | ++ |
+ )+ |
+
167 | ++ |
+ )+ |
+
168 | ++ |
+ )+ |
+
169 | ++ |
+ )+ |
+
170 | ++ | + + | +
171 | ++ |
+ # build site without preview+ |
+
172 | +! | +
+ build_site(+ |
+
173 | +! | +
+ pkg = pkg,+ |
+
174 | +! | +
+ override = yaml_settings,+ |
+
175 | +! | +
+ preview = FALSE+ |
+
176 | ++ |
+ )+ |
+
177 | ++ |
+ }+ |
+
1 | ++ |
+ gitignore_includes <- c(+ |
+
2 | ++ |
+ "secrets",+ |
+
3 | ++ |
+ "windows",+ |
+
4 | ++ |
+ "r",+ |
+
5 | ++ |
+ "python",+ |
+
6 | ++ |
+ "node",+ |
+
7 | ++ |
+ "markdown"+ |
+
8 | ++ |
+ )+ |
+
9 | ++ | + + | +
10 | ++ | + + | +
11 | ++ | + + | +
12 | ++ |
+ get_gitignore <- function(template, as = c("list", "json")) {+ |
+
13 | ++ | + + | +
14 | +! | +
+ if (!template %in% gitignore_templates) {+ |
+
15 | +! | +
+ stop("Invalid gitignore template")+ |
+
16 | ++ |
+ }+ |
+
17 | ++ | + + | +
18 | +! | +
+ base_url <- "https://www.toptal.com/developers/gitignore/api/"+ |
+
19 | +! | +
+ url <- paste0(base_url, template)+ |
+
20 | +! | +
+ ignore <- httr::content(httr::GET(url), as = "text")+ |
+
21 | ++ | + + | +
22 | +! | +
+ if (as == "list") {+ |
+
23 | +! | +
+ ignore+ |
+
24 | +! | +
+ } else if (as == "json") {+ |
+
25 | +! | +
+ jsonlite::fromJSON(ignore)+ |
+
26 | ++ |
+ }+ |
+
27 | ++ |
+ }+ |
+
28 | ++ | + + | +
29 | ++ |
+ add_gitignore <- function(includes, path = getwd(), ...) {+ |
+
30 | ++ | + + | +
31 | +! | +
+ gitignore_file <- file.path(path, ".gitignore")+ |
+
32 | +! | +
+ if (!file.exists(gitignore_file)) {+ |
+
33 | +! | +
+ writeLines("", gitignore_file)+ |
+
34 | ++ |
+ }+ |
+
35 | ++ | + + | +
36 | +! | +
+ base_url <- "https://www.toptal.com/developers/gitignore/api/"+ |
+
37 | +! | +
+ ignores <- list+ |
+
38 | +! | +
+ i <- 0+ |
+
39 | ++ | + + | +
40 | +! | +
+ for (include in includes) {+ |
+
41 | +! | +
+ i <- i + 1+ |
+
42 | +! | +
+ url <- paste0(base_url, include)+ |
+
43 | +! | +
+ ignore <- httr::content(httr::GET(url), as = "text")+ |
+
44 | +! | +
+ ignores[[i]] <- ignore+ |
+
45 | +! | +
+ names(ignores[i]) <- include+ |
+
46 | ++ |
+ # writeLines(ignore, gitignore_file)+ |
+
47 | ++ |
+ }+ |
+
48 | ++ | + + | +
49 | +! | +
+ gitignore <- readLines(gitignore_file)+ |
+
50 | ++ |
+ # to_ignore <-+ |
+
51 | ++ | + + | +
52 | ++ |
+ }+ |
+
1 | ++ |
+ #' Query GraphQL Github API+ |
+
2 | ++ |
+ #'+ |
+
3 | ++ |
+ #' This function helps you retrieving the status of a project board within the organization+ |
+
4 | ++ |
+ #'+ |
+
5 | ++ |
+ #' @param board_url url of the github project board+ |
+
6 | ++ |
+ #' @param github_token access token to the graphql api+ |
+
7 | ++ |
+ #'+ |
+
8 | ++ |
+ #' @importFrom stringr str_extract+ |
+
9 | ++ |
+ #' @importFrom glue glue+ |
+
10 | ++ |
+ #' @importFrom gh gh_gql+ |
+
11 | ++ |
+ #' @importFrom purrr map_dfr map_chr+ |
+
12 | ++ |
+ #' @importFrom gitlabr multilist_to_tibble+ |
+
13 | ++ |
+ #' @importFrom tidyr unnest_wider+ |
+
14 | ++ |
+ #' @importFrom dplyr mutate select+ |
+
15 | ++ |
+ #'+ |
+
16 | ++ |
+ #' @return a tibble+ |
+
17 | ++ |
+ #'+ |
+
18 | ++ |
+ #' @export+ |
+
19 | ++ |
+ #' @examples+ |
+
20 | ++ |
+ #' \dontrun{+ |
+
21 | ++ |
+ #'+ |
+
22 | ++ |
+ #' # Example with board hosted in an organization github account+ |
+
23 | ++ |
+ #' board_url_organization <- "https://github.com/orgs/ThinkR-open/projects/4/"+ |
+
24 | ++ |
+ #' github_token <- Sys.getenv("GITHUB_PAT")+ |
+
25 | ++ |
+ #'+ |
+
26 | ++ |
+ #' graphql_to_tibble(+ |
+
27 | ++ |
+ #' board_url = board_url_organization,+ |
+
28 | ++ |
+ #' github_token = github_token+ |
+
29 | ++ |
+ #' )+ |
+
30 | ++ |
+ #'+ |
+
31 | ++ |
+ #'+ |
+
32 | ++ |
+ #' # Example with board hosted in a user github account+ |
+
33 | ++ |
+ #' board_url_user <- "https://github.com/users/the-thinkr/projects/1"+ |
+
34 | ++ |
+ #' github_token <- Sys.getenv("GITHUB_PAT")+ |
+
35 | ++ |
+ #'+ |
+
36 | ++ |
+ #' graphql_to_tibble(+ |
+
37 | ++ |
+ #' board_url = board_url_user,+ |
+
38 | ++ |
+ #' github_token = github_token+ |
+
39 | ++ |
+ #' )+ |
+
40 | ++ |
+ #' }+ |
+
41 | ++ |
+ graphql_to_tibble <- function(board_url, github_token = Sys.getenv("GITHUB_PAT")) {+ |
+
42 | +! | +
+ if (github_token == "") {+ |
+
43 | +! | +
+ stop("You must provide an access token to the Github Api (read:project scope is required)")+ |
+
44 | ++ |
+ }+ |
+
45 | ++ | + + | +
46 | ++ |
+ # extract organization and project number from board url to retrieve the node ID of the+ |
+
47 | ++ |
+ # project within the organization+ |
+
48 | +! | +
+ project_number <- str_extract(+ |
+
49 | +! | +
+ string = board_url,+ |
+
50 | +! | +
+ pattern = "(?<=projects/)[:digit:]{1,}"+ |
+
51 | ++ |
+ )+ |
+
52 | ++ | + + | +
53 | +! | +
+ organization_1 <-+ |
+
54 | +! | +
+ str_extract(string = board_url, pattern = "(?<=github.com/)[:graph:]{1,}(?=/projects/)")+ |
+
55 | +! | +
+ organization <- gsub("orgs/|users/", "", organization_1)+ |
+
56 | +! | +
+ if (grepl("^orgs/", organization_1)) {+ |
+
57 | +! | +
+ is_orgs_or_user <- "orgs"+ |
+
58 | +! | +
+ organization <- gsub("orgs/|users/", "", organization_1)+ |
+
59 | +! | +
+ req_project_id <- glue(+ |
+
60 | ++ |
+ '+ |
+
61 | +! | +
+ query{+ |
+
62 | +! | +
+ organization(login: "$_organization_$"){+ |
+
63 | +! | +
+ projectV2(number: $_project_number_$) {+ |
+
64 | +! | +
+ id+ |
+
65 | ++ |
+ }+ |
+
66 | ++ |
+ }+ |
+
67 | ++ |
+ }',+ |
+
68 | +! | +
+ .open = "$_",+ |
+
69 | +! | +
+ .close = "_$"+ |
+
70 | ++ |
+ )+ |
+
71 | +! | +
+ } else if (grepl("^users/", organization_1)) {+ |
+
72 | +! | +
+ is_orgs_or_user <- "users"+ |
+
73 | +! | +
+ organization <- gsub("orgs/|users/", "", organization_1)+ |
+
74 | +! | +
+ req_project_id <-+ |
+
75 | +! | +
+ req_project_id <- glue(+ |
+
76 | ++ |
+ '+ |
+
77 | +! | +
+ query{+ |
+
78 | +! | +
+ user(login: "$_organization_$"){+ |
+
79 | +! | +
+ projectV2(number: $_project_number_$) {+ |
+
80 | +! | +
+ id+ |
+
81 | ++ |
+ }+ |
+
82 | ++ |
+ }+ |
+
83 | ++ |
+ }',+ |
+
84 | +! | +
+ .open = "$_",+ |
+
85 | +! | +
+ .close = "_$"+ |
+
86 | ++ |
+ )+ |
+
87 | ++ |
+ }+ |
+
88 | ++ | + + | +
89 | +! | +
+ project_id <- gh_gql(req_project_id, .token = github_token) %>%+ |
+
90 | +! | +
+ unlist()+ |
+
91 | ++ | + + | +
92 | ++ | + + | +
93 | ++ |
+ # check whether the provided token has the right scope+ |
+
94 | +! | +
+ if ("errors.message" %in% names(project_id)) {+ |
+
95 | +! | +
+ stop(project_id["errors.message"])+ |
+
96 | ++ |
+ }+ |
+
97 | ++ | + + | +
98 | ++ | + + | +
99 | ++ |
+ # get project board status+ |
+
100 | +! | +
+ req_board_infos <- glue(+ |
+
101 | +! | +
+ 'query{+ |
+
102 | +! | +
+ node(id: "$_project_id_$") {+ |
+
103 | +! | +
+ ... on ProjectV2 {+ |
+
104 | +! | +
+ items(first: 100) {+ |
+
105 | +! | +
+ nodes{+ |
+
106 | +! | +
+ id+ |
+
107 | +! | +
+ fieldValues(first: 100) {+ |
+
108 | +! | +
+ nodes{+ |
+
109 | +! | +
+ ... on ProjectV2ItemFieldSingleSelectValue {+ |
+
110 | +! | +
+ name+ |
+
111 | +! | +
+ field {+ |
+
112 | +! | +
+ ... on ProjectV2FieldCommon {+ |
+
113 | +! | +
+ name+ |
+
114 | ++ |
+ }+ |
+
115 | ++ |
+ }+ |
+
116 | ++ |
+ }+ |
+
117 | ++ |
+ }+ |
+
118 | ++ |
+ }+ |
+
119 | +! | +
+ content{+ |
+
120 | +! | +
+ ...on Issue {+ |
+
121 | +! | +
+ title+ |
+
122 | +! | +
+ url+ |
+
123 | +! | +
+ number+ |
+
124 | +! | +
+ state+ |
+
125 | +! | +
+ createdAt+ |
+
126 | +! | +
+ updatedAt+ |
+
127 | +! | +
+ closedAt+ |
+
128 | ++ |
+ }+ |
+
129 | ++ |
+ }+ |
+
130 | ++ |
+ }+ |
+
131 | ++ |
+ }+ |
+
132 | ++ |
+ }+ |
+
133 | ++ |
+ }+ |
+
134 | ++ |
+ }',+ |
+
135 | +! | +
+ .open = "$_",+ |
+
136 | +! | +
+ .close = "_$"+ |
+
137 | ++ |
+ )+ |
+
138 | ++ | + + | +
139 | +! | +
+ board_infos <- gh_gql(+ |
+
140 | +! | +
+ req_board_infos,+ |
+
141 | +! | +
+ .token = github_token+ |
+
142 | ++ |
+ )+ |
+
143 | ++ | + + | +
144 | +! | +
+ board_infos <- board_infos$data$node$items$nodes+ |
+
145 | ++ | + + | +
146 | ++ | + + | +
147 | ++ |
+ # export to tibble+ |
+
148 | +! | +
+ board_tbl <- map_dfr(board_infos, function(issue) {+ |
+
149 | +! | +
+ multilist_to_tibble(issue) %>%+ |
+
150 | +! | +
+ unnest_wider(content) %>%+ |
+
151 | +! | +
+ mutate(board_column = unlist(fieldValues[[1]])[1]) %>%+ |
+
152 | +! | +
+ select(-fieldValues)+ |
+
153 | ++ |
+ })+ |
+
154 | ++ | + + | +
155 | +! | +
+ return(board_tbl)+ |
+
156 | ++ |
+ }+ |
+
The page you requested cannot be found (perhaps it was moved or renamed).
+You may want to try searching to find the page's new location, or use +the table of contents to find the page you are looking for.
+