pkgdown/0000755000176200001440000000000015103035714011722 5ustar liggesuserspkgdown/tests/0000755000176200001440000000000015102677747013105 5ustar liggesuserspkgdown/tests/testthat/0000755000176200001440000000000015103035714014724 5ustar liggesuserspkgdown/tests/testthat/test-highlight.R0000644000176200001440000000352214770274305020007 0ustar liggesuserstest_that("highlight_examples captures dependencies", { withr::defer(try(file_delete(test_path("Rplot001.png")), TRUE)) dummy_dep <- htmltools::htmlDependency("dummy", "1.0.0", "dummy.js") widget <- htmlwidgets::createWidget("test", list(), dependencies = dummy_dep) out <- highlight_examples("widget", env = environment()) # htmlwidgets always get dependency on htmlwidgets.js expect_equal(attr(out, "dependencies")[-1], list(dummy_dep)) }) test_that("highlight_examples runs and hides DONTSHOW calls()", { out <- highlight_examples("DONTSHOW(x <- 1)\nx") expect_snapshot(cat(strip_html_tags(out))) }) test_that("highlight_text & highlight_examples include sourceCode div", { withr::defer(try(file_delete(test_path("Rplot001.png")), TRUE)) html <- xml2::read_html(highlight_examples("a + a", "x")) expect_equal(xpath_attr(html, "./body/div", "class"), "sourceCode") html <- xml2::read_html(highlight_text("a + a")) expect_equal(xpath_attr(html, "./body/div", "class"), "sourceCode") }) test_that("pre() can produce needed range of outputs", { expect_snapshot({ cat(pre("x")) cat(pre("x", r_code = TRUE)) }) }) test_that("tweak_highlight_other() renders generic code blocks for roxygen2 >= 7.2.0", { html <- xml2::read_html( '
1+1\n
' ) div <- xml2::xml_find_first(html, "//div") tweak_highlight_other(div) expect_equal(xpath_text(div, "pre/code"), "1+1") }) test_that("tweak_highlight_other() renders nested code blocks for roxygen2 >= 7.2.0", { html <- xml2::read_html(dedent( "

    blablabla

    ```{r results='asis'}
    lalala
    ```

    
" )) div <- xml2::xml_find_first(html, "//div") tweak_highlight_other(div) expect_snapshot(cat(xpath_text(div, "pre/code"))) }) pkgdown/tests/testthat/test-tweak-tags.R0000644000176200001440000002060715075440722020107 0ustar liggesusers# tables ------------------------------------------------------------- test_that("tables get additional table class", { html <- xml2::read_html( "
" ) tweak_tables(html) expect_equal( xpath_attr(html, ".//table", "class"), c("table", "table a", "table b") ) }) test_that("except in the argument list", { html <- xml2::read_html( "
" ) tweak_tables(html) expect_equal(xpath_attr(html, ".//table", "class"), "ref-arguments") }) # anchors ------------------------------------------------------------- test_that("ids move from div to headings", { html <- xml2::read_xml( '

abc

abc

abc

abc

abc
abc
' ) tweak_anchors(html) expect_equal( xpath_attr(html, ".//h1|//h2|//h3|//h4|//h5|//h6", "id"), as.character(1:6) ) expect_equal(xpath_attr(html, ".//div", "id"), rep(NA_character_, 6)) }) test_that("must be in div with section an class and id", { html <- xml2::read_xml( '

abc

abc

abc

' ) tweak_anchors(html) expect_equal(xpath_attr(html, ".//h1", "id"), rep(NA_character_, 3)) }) test_that("anchor html added to headings", { html <- xml2::read_xml( '

abc

' ) tweak_anchors(html) expect_snapshot_output(xpath_xml(html, ".//h1")) }) test_that("deduplicates ids", { html <- xml2::read_xml( '

abc

abc

abc

' ) tweak_anchors(html) expect_equal(xpath_attr(html, ".//h1", "id"), c("x", "x-1", "x-2")) }) test_that("can process multiple header levels", { html <- xml2::read_xml( '

abc

abc

abc

abc

' ) tweak_anchors(html) expect_equal(xpath_attr(html, ".//a", "href"), c("#1", "#2", "#3", "#4")) }) test_that("can handle multiple header", { html <- xml2::read_xml( '

one

two

' ) tweak_anchors(html) expect_equal(xpath_attr(html, ".//div", "id"), NA_character_) expect_equal(xpath_attr(html, ".//h1", "id"), c("x", "x-1")) expect_equal(xpath_attr(html, ".//h1/a", "href"), c("#x", "#x-1")) }) test_that("anchors don't get additional newline", { html <- xml2::read_xml( '

abc

' ) tweak_anchors(html) expect_equal(xpath_text(html, ".//h1"), "abc") }) test_that("empty headings are skipped", { html <- xml2::read_xml( '

' ) tweak_anchors(html) expect_equal(xpath_length(html, ".//h1/a"), 0) }) test_that("docs with no headings are left unchanged", { html <- xml2::read_xml('
Nothing
') tweak_anchors(html) expect_equal(as.character(xpath_xml(html, ".")), '
Nothing
') }) # links ----------------------------------------------------------------- test_that("local md links are replaced with html", { html <- xml2::read_html( ' ' ) tweak_link_md(html) expect_equal( xpath_attr(html, "//a", "href"), c("local.html", "local.html#fragment", "http://remote.com/remote.md") ) }) test_that("tweak_link_external() add the external-link class if needed", { html <- xml2::read_html( ' ' ) pkg <- list(meta = list(url = "http://example.com")) tweak_link_external(html, pkg = pkg) expect_equal( xpath_attr(html, "//a", "class"), c(NA, "external-link", "external-link", "external-link thumbnail", NA) ) }) test_that("tweak_link_absolute() fixes relative paths in common locations", { html <- xml2::read_html( ' ' ) pkg <- list(meta = list(url = "https://example.com")) tweak_link_absolute(html, pkg) expect_equal(xpath_attr(html, "//a", "href"), "https://example.com/a") expect_equal(xpath_attr(html, "//link", "href"), "https://example.com/link") expect_equal(xpath_attr(html, "//img", "src"), "https://example.com/img") }) test_that("tweak_link_absolute() leaves absolute paths alone", { html <- xml2::read_html('') pkg <- list(list(url = "https://example.com")) tweak_link_absolute(html, pkg) expect_equal(xpath_attr(html, "//a", "href"), "https://a.com") }) test_that("tweak_link_r6() correctly modifies link to inherited R6 classes", { skip_on_cran() # in case downlit url changes html <- xml2::read_html( " text text text " ) tweak_link_R6(html, "pkgdown") expect_equal( xpath_attr(html, "//a", "href"), c( "Animal.html#method-x", "leave-me.html", "https://downlit.r-lib.org/reference/autolink.html#method-x" ) ) }) test_that("tweak_img_src() updates img and source tags", { html <- xml2::read_html( ' ' ) tweak_img_src(html) expect_equal(xpath_attr(html, ".//img", "src"), "reference/figures/bar.png") expect_equal( xpath_attr(html, ".//source", "srcset"), "reference/figures/foo.png" ) }) test_that("tweak_img_src() doesn't modify absolute links", { html <- xml2::read_html( ' ' ) urls_before <- xpath_attr(html, ".//img", "src") tweak_img_src(html) expect_equal( xpath_attr(html, ".//img", "src"), urls_before ) }) test_that("trailing () moved inside links", { skip_if_no_pandoc("2.16") html <- xml2::read_html('build_site()') tweak_link_seealso(html) expect_equal(xpath_contents(html, ".//code"), "build_site()") }) # stripped divs etc ------------------------------------------------------- test_that("selectively remove hide- divs", { html <- xml2::read_xml( "
devel
release
all
" ) tweak_strip(html, in_dev = TRUE) expect_equal(xpath_text(html, ".//div"), "devel") html <- xml2::read_xml( "
devel
release
all
" ) tweak_strip(html, in_dev = FALSE) expect_equal(xpath_text(html, ".//div"), "release") }) # footnotes --------------------------------------------------------------- test_that("can process footnote with code", { skip_if_no_pandoc("2.17.1") pkg <- local_pkgdown_site() html <- markdown_to_html( pkg, " Hooray[^1] [^1]: Including code: ``` 1 + 2 + ``` And more text " ) tweak_footnotes(html) expect_equal(xpath_length(html, "//a[@class='footnote-back']"), 0) expect_equal(xpath_attr(html, ".//a", "class"), "footnote-ref") expect_equal(xpath_attr(html, ".//a", "tabindex"), "0") expect_snapshot(xpath_attr(html, ".//a", "data-bs-content")) }) pkgdown/tests/testthat/test-utils.R0000644000176200001440000000105015001744016017157 0ustar liggesuserstest_that("is_internal_link() works", { pkg = list(meta = list(url = "https://pkgdown.r-lib.org")) expect_false(is_internal_link("https://github.com", pkg = pkg)) expect_false(is_internal_link("http://github.com", pkg = pkg)) expect_true(is_internal_link("https://pkgdown.r-lib.org/articles", pkg = pkg)) expect_true(is_internal_link("reference/index.html", pkg = pkg)) expect_true( all.equal( is_internal_link( c("reference/index.html", "https://github.com"), pkg = pkg ), c(TRUE, FALSE) ) ) }) pkgdown/tests/testthat/test-topics-external.R0000644000176200001440000000056314633374223021161 0ustar liggesuserstest_that("can get info about external function", { expect_snapshot(str(ext_topics("base::mean"))) # and column names match pkg <- as_pkgdown(test_path("assets/reference")) expect_equal(names(ext_topics("base::mean")), names(pkg$topics)) }) test_that("fails if documentation not available", { expect_snapshot(ext_topics("base::doesntexist"), error = TRUE) }) pkgdown/tests/testthat/test-preview.R0000644000176200001440000000110714770274305017516 0ustar liggesuserstest_that("checks its inputs", { pkg <- local_pkgdown_site() expect_snapshot(error = TRUE, { preview_site(pkg, path = 1) preview_site(pkg, path = "foo") preview_site(pkg, preview = 1) }) }) test_that("local_path adds index.html if needed", { pkg <- local_pkgdown_site() file_create(path(pkg$dst_path, "test.html")) expect_equal( local_path(pkg, "test.html"), path(pkg$dst_path, "test.html") ) dir_create(path(pkg$dst_path, "reference")) expect_equal( local_path(pkg, "reference"), path(pkg$dst_path, "reference", "index.html") ) }) pkgdown/tests/testthat/test-tweak-homepage.R0000644000176200001440000000753514770274305020746 0ustar liggesuserstest_that("first header is wrapped in page-header div", { html <- xml2::read_html( '

First

Second

' ) tweak_homepage_html(html) expect_equal(xpath_attr(html, ".//div", "class"), "page-header") }) test_that("removes dummy page-header", { html <- xml2::read_html( '

Header

' ) tweak_homepage_html(html) expect_equal(xpath_text(html, ".//h1"), "Header") }) test_that("can remove first header", { html <- xml2::read_html( '

First

Second

' ) tweak_homepage_html(html, strip_header = TRUE) expect_equal(xpath_length(html, ".//div"), 0) }) test_that("can remove logo", { # Without link html <- xml2::read_html( '

First

' ) tweak_homepage_html(html, bs_version = 5, logo = "mylogo.png") expect_snapshot(xpath_xml(html, ".//div")) # With link html <- xml2::read_html( '

First

' ) tweak_homepage_html(html, bs_version = 5, logo = "mylogo.png") expect_snapshot(xpath_xml(html, ".//div")) }) # badges ------------------------------------------------------------------- test_that("can move badges to sidebar", { html <- xml2::read_html( '

Title

' ) tweak_sidebar_html(html) expect_snapshot(xpath_xml(html, ".//div")) }) test_that("remove badges even if no dev-status div", { html <- xml2::read_html( '

Title

' ) tweak_sidebar_html(html) expect_snapshot(html) }) test_that("remove dev-status & badges if badges suppress", { html <- xml2::read_html( '

Title

' ) tweak_sidebar_html(html, show_badges = FALSE) expect_equal(xpath_length(html, "//div"), 0) }) test_that("doesn't find badges when they don't exist", { expect_equal(badges_extract_text("

"), character()) expect_equal(badges_extract_text("

"), character()) # first paragraph contains non-image components expect_equal( badges_extract_text( '

altHi!

' ), character() ) }) test_that("finds single badge", { expect_equal( badges_extract_text('

'), '' ) }) test_that("finds badges in #badges div", { expect_equal( badges_extract_text( '

' ), '' ) # even if there's extra text expect_equal( badges_extract_text( '

Hi!

' ), '' ) }) test_that("can find badges in comments", { html <- '

blop

I am the first paragraph!

' expect_equal(badges_extract_text(html), '') # produced by usethis html <- '

blop

I am the first paragraph!

' expect_equal(badges_extract_text(html), '') }) test_that("ignores extraneous content", { html <- '

blop

I am the first paragraph!

a

B

' expect_equal(badges_extract_text(html), '') }) pkgdown/tests/testthat/test-build.R0000644000176200001440000000155315101160162017121 0ustar liggesuserstest_that("both versions of build_site have same arguments", { expect_equal(formals(build_site_local), formals(build_site_external)) }) test_that("build_site can be made unquiet", { skip_if_no_pandoc() # `quiet = FALSE` from build_site() should get passed to # build_articles(), which will include some rmarkdown build out in the # messages, including "pandoc", which won't be there normally pkg <- local_pkgdown_site(test_path("assets/figure")) output_unquiet <- suppressMessages( capture.output( build_site( pkg, quiet = FALSE, preview = FALSE ) ) ) expect_match(paste(output_unquiet, collapse = ""), "pandoc") output_quiet <- suppressMessages( capture.output( build_site( pkg, preview = FALSE ) ) ) expect_no_match(paste(output_quiet, collapse = ""), "pandoc") }) pkgdown/tests/testthat/test-rd-example.R0000644000176200001440000000571714770274305020106 0ustar liggesusers# run_examples() ----------------------------------------------------------- test_that("warns if unparseable", { expect_warning( run_examples("1 + \\dontrun{2 + }"), "Failed to parse" ) }) # as_example() ------------------------------------------------------------ test_that("dontrun{} wrapped in if(FALSE)", { expect_equal(rd2ex("\\dontrun{1}"), "if (FALSE) 1 # \\dontrun{}") expect_equal( rd2ex("\\dontrun{\n 1\n}"), c("if (FALSE) { # \\dontrun{", " 1", "} # }") ) # unless run_dont_run is true expect_equal(rd2ex("\\dontrun{1}", run_dont_run = TRUE), "1") expect_equal( rd2ex("\\dontrun{\n 1\n}", run_dont_run = TRUE), c("# \\dontrun{", " 1", "# }") ) }) test_that("block donttest{} gets a comment to preserve spacing", { expect_equal(rd2ex("\\donttest{1}"), "1") expect_equal( rd2ex("\\donttest{\n 1\n}"), c("# \\donttest{", " 1", "# }") ) }) test_that("dontshow{} becomes DONTSHOW", { expect_equal(rd2ex("\\dontshow{1}"), "DONTSHOW({1})") expect_equal(rd2ex("\\dontshow{\n 1\n}"), c("DONTSHOW({", " 1", "})")) }) test_that("testonly{} becomes TESTONLY", { expect_equal(rd2ex("\\testonly{1}"), "TESTONLY({1})") expect_equal(rd2ex("\\testonly{\n 1\n}"), c("TESTONLY({", " 1", "})")) }) test_that("handles nested tags", { expect_equal( rd2ex("if(TRUE {\n \\dontrun{\n 1 + 2\n }\n}"), c( "if(TRUE {", " if (FALSE) { # \\dontrun{", " 1 + 2", " } # }", "}" ) ) }) test_that("translate dots and ldots to ...", { expect_equal(rd2ex("\\ldots"), "...") expect_equal(rd2ex("\\dots"), "...") }) test_that("ignores out", { expect_equal(rd2ex("\\out{1 + 2}"), "1 + 2") }) test_that("extracts conditions from if", { expect_equal(rd2ex("\\if{html}{1 + 2}"), "1 + 2") expect_equal(rd2ex("\\if{latex}{1 + 2}"), "") expect_equal(rd2ex("\\ifelse{html}{1 + 2}{3 + 4}"), "1 + 2") expect_equal(rd2ex("\\ifelse{latex}{1 + 2}{3 + 4}"), "3 + 4") }) test_that("@examplesIf", { rd <- paste0( "\\dontshow{if (1 == 0) (if (getRversion() >= \"3.4\") withAutoprint else force)(\\{ # examplesIf}\n", "answer <- 43\n", "\\dontshow{\\}) # examplesIf}" ) exp <- c( "if (FALSE) { # 1 == 0", "answer <- 43", "}" ) expect_warning( expect_equal(rd2ex(rd), exp), "@examplesIf condition" ) rd2 <- paste0( "\\dontshow{if (TRUE) (if (getRversion() >= \"3.4\") withAutoprint else force)(\\{ # examplesIf}\n", "answer <- 43\n", "\\dontshow{\\}) # examplesIf}" ) exp2 <- c( "answer <- 43" ) expect_equal(rd2ex(rd2), exp2) cnd <- paste0(strrep("TRUE && ", 100), "FALSE") rd3 <- paste0( "\\dontshow{if (", cnd, ") (if (getRversion() >= \"3.4\") withAutoprint else force)(\\{ # examplesIf}\n", "answer <- 43\n", "\\dontshow{\\}) # examplesIf}" ) exp3 <- c( paste0("if (FALSE) { # ", cnd), "answer <- 43", "}" ) expect_snapshot( expect_equal(strtrim(rd2ex(rd3), 40), strtrim(exp3, 40)) ) }) pkgdown/tests/testthat/test-usage.R0000644000176200001440000001421314770274305017143 0ustar liggesusers# Reference -------------------------------------------------------------------- test_that("usage escapes special characters", { # parseable expect_equal(usage2text("# <"), "# <") #unparseable expect_equal(usage2text("<"), "<") }) test_that("usage re-renders non-syntactic calls", { expect_equal(usage2text("`<`(x, y)"), "x < y") expect_equal(usage2text("`[`(x, y)"), "x[y]") }) test_that("usage doesn't re-renders syntactic calls", { expect_equal(usage2text("foo(x , y) # hi"), "foo(x , y) # hi") multi_line <- "foo(\n x # x,\n y = 1 # y,\n)" expect_equal(usage2text(multi_line), multi_line) }) test_that("usage generates user facing code for S3/S4 infix/replacement methods", { expect_snapshot({ cat(usage2text("\\S3method{$}{indexed_frame}(x, name)")) cat(usage2text("\\method{[[}{indexed_frame}(x, i) <- value")) cat(usage2text("\\S4method{>=}{MyType,numeric}(e1, e2)")) }) }) test_that("S4 methods gets comment", { out <- rd2html("\\S4method{fun}{class}(x, y)") expect_equal(out[1], "# S4 method for class 'class'") expect_equal(out[2], "fun(x, y)") }) test_that("S3 methods gets comment", { out <- rd2html("\\S3method{fun}{class}(x, y)") expect_equal(out[1], "# S3 method for class 'class'") expect_equal(out[2], "fun(x, y)") out <- rd2html("\\method{fun}{class}(x, y)") expect_equal(out[1], "# S3 method for class 'class'") expect_equal(out[2], "fun(x, y)") }) test_that("Methods for class function work", { out <- rd2html("\\S3method{fun}{function}(x, y)") expect_equal(out[1], "# S3 method for class 'function'") expect_equal(out[2], "fun(x, y)") out <- rd2html("\\method{fun}{function}(x, y)") expect_equal(out[1], "# S3 method for class 'function'") expect_equal(out[2], "fun(x, y)") out <- rd2html("\\S4method{fun}{function,function}(x, y)") expect_equal(out[1], "# S4 method for class 'function,function'") expect_equal(out[2], "fun(x, y)") }) test_that("default methods get custom text", { out <- rd2html("\\S3method{fun}{default}(x, y)") expect_equal(out[1], "# Default S3 method") out <- rd2html("\\S4method{fun}{default}(x, y)") expect_equal(out[1], "# Default S4 method") }) test_that("non-syntactic functions get backquoted, not escaped", { out <- rd2html("\\S3method{<}{foo}(x, y)") expect_equal(out[[2]], "`<`(x, y)") out <- rd2html("\\S4method{bar<-}{foo}(x, y)") expect_equal(out[[2]], "`bar<-`(x, y)") }) # Reference index -------------------------------------------------------------- test_that("can parse data", { usage <- parse_usage("f")[[1]] expect_equal(usage, list(type = "data", name = "f")) usage <- parse_usage("data(f)")[[1]] expect_equal(usage, list(type = "data", name = "f")) }) test_that("can parse function/methods", { usage <- parse_usage("f(x)")[[1]] expect_equal(usage$type, "fun") expect_equal(usage$name, "f") usage <- parse_usage("\\method{f}{bar}(x)")[[1]] expect_equal(usage$type, "s3") expect_equal(usage$name, "f") expect_equal(usage$signature, "bar") usage <- parse_usage("\\S3method{f}{bar}(x)")[[1]] expect_equal(usage$type, "s3") expect_equal(usage$name, "f") expect_equal(usage$signature, "bar") usage <- parse_usage("\\S3method{f}{`foo bar`}(x)")[[1]] expect_equal(usage$type, "s3") expect_equal(usage$name, "f") expect_equal(usage$signature, "foo bar") usage <- parse_usage("\\S4method{f}{bar,baz}(x)")[[1]] expect_equal(usage$type, "s4") expect_equal(usage$name, "f") expect_equal(usage$signature, c("bar", "baz")) usage <- parse_usage("\\S4method{f}{NULL}(x)")[[1]] expect_equal(usage$type, "s4") expect_equal(usage$name, "f") expect_equal(usage$signature, c("NULL")) usage <- parse_usage("\\S4method{f}{function,function}(x, y)")[[1]] expect_equal(usage$type, "s4") expect_equal(usage$name, "f") expect_equal(usage$signature, c("function", "function")) usage <- parse_usage("\\S4method{f}{function,foo bar}(x, y)")[[1]] expect_equal(usage$type, "s4") expect_equal(usage$name, "f") expect_equal(usage$signature, c("function", "foo bar")) usage <- parse_usage("pkg::func()")[[1]] expect_equal(usage$type, "fun") expect_equal(usage$name, "func") usage <- parse_usage("pkg:::func()")[[1]] expect_equal(usage$type, "fun") expect_equal(usage$name, "func") }) test_that("can parse replacement functions", { usage <- parse_usage("f() <- value")[[1]] expect_true(usage$replacement) expect_equal(usage$name, "f<-") usage <- parse_usage("\\S3method{f}{bar}(x) <- value")[[1]] expect_true(usage$replacement) expect_equal(usage$name, "f<-") usage <- parse_usage("\\S4method{f}{bar,baz}(x) <- value")[[1]] expect_true(usage$replacement) expect_equal(usage$name, "f<-") }) test_that("can parse infix functions", { usage <- parse_usage("x \\%f\\% y")[[1]] expect_true(usage$infix) expect_equal(usage$name, "%f%") usage <- parse_usage("\\S3method{[}{bar}(x)")[[1]] expect_true(usage$infix) expect_equal(usage$name, "[") usage <- parse_usage("\\S4method{[}{bar,baz}(x)")[[1]] expect_true(usage$infix) expect_equal(usage$name, "[") }) test_that("can parse infix replacement functions", { usage <- parse_usage("\\S3method{[}{bar}(x) <- value")[[1]] expect_true(usage$infix) expect_true(usage$replacement) expect_equal(usage$name, "[<-") usage <- parse_usage("\\S4method{[}{bar,baz}(x) <- value")[[1]] expect_true(usage$infix) expect_true(usage$replacement) expect_equal(usage$name, "[<-") }) test_that("can parse multistatement usages", { usage <- parse_usage("f()\n%This is a comment\ng(\n\n)") expect_length(usage, 2) expect_equal(usage[[1]]$name, "f") expect_equal(usage[[2]]$name, "g") }) test_that("can parse dots", { usage <- parse_usage("f(\\dots)")[[1]] expect_equal(usage$name, "f") }) test_that("usage2text can parse symbols (#2727)", { expect_no_error(usage2text("viridisLite::viridis(21)")) }) # short_name -------------------------------------------------------------- test_that("infix functions left as", { expect_equal(short_name("%||%", "fun"), "`%||%`") }) test_that("function name and signature is escaped", { expect_equal(short_name("%<%", "fun"), "`%<%`") expect_equal(short_name("f", "S3", "<"), "f(<<>)") }) pkgdown/tests/testthat/test-rd-html.R0000644000176200001440000003067615074163153017415 0ustar liggesuserstest_that("special characters are escaped", { out <- rd2html("a & b") expect_equal(out, "a & b") }) test_that("converts Rd unicode shortcuts", { expect_snapshot(rd2html("``a -- b --- c''")) }) test_that("simple tags translated to known good values", { # Simple insertions expect_equal(rd2html("\\ldots"), "...") expect_equal(rd2html("\\dots"), "...") expect_equal(rd2html("\\R"), "R") expect_equal(rd2html("\\cr"), "
") "Macros" expect_equal(rd2html("\\newcommand{\\f}{'f'} \\f{}"), "'f'") expect_equal(rd2html("\\renewcommand{\\f}{'f'} \\f{}"), "'f'") }) test_that("comments converted to html", { expect_equal(rd2html("a\n%b\nc"), c("a", "", "c")) }) test_that("simple wrappers work as expected", { expect_equal(rd2html("\\strong{x}"), "x") expect_equal(rd2html("\\strong{\\emph{x}}"), "x") }) test_that("subsection generates h3", { expect_snapshot(cli::cat_line(rd2html("\\subsection{A}{B}"))) }) test_that("subsection generates h3", { expect_snapshot(cli::cat_line(rd2html( "\\subsection{A}{ p1 p2 }" ))) }) test_that("subsection generates generated anchor", { text <- c("", rd2html("\\subsection{A}{B}"), "") html <- xml2::read_xml(paste0(text, collapse = "\n")) tweak_anchors(html) expect_equal(xpath_attr(html, ".//h3", "id"), "a") expect_equal(xpath_attr(html, ".//a", "href"), "#a") }) test_that("nested subsection generates h4", { expect_snapshot(cli::cat_line(rd2html( "\\subsection{H3}{\\subsection{H4}{}}" ))) }) test_that("if generates html", { expect_equal(rd2html("\\if{html}{\\bold{a}}"), "a") expect_equal(rd2html("\\if{latex}{\\bold{a}}"), character()) }) test_that("ifelse generates html", { expect_equal(rd2html("\\ifelse{html}{\\bold{a}}{x}"), "a") expect_equal(rd2html("\\ifelse{latex}{x}{\\bold{a}}"), "a") }) test_that("out is for raw html", { expect_equal(rd2html("\\out{
}"), "
") }) test_that("support platform specific code", { os_specific <- function(command, os, output) { rd2html(paste0( "#", command, " ", os, "\n", output, "\n", "#endif" )) } expect_equal(os_specific("ifdef", "windows", "X"), character()) expect_equal(os_specific("ifdef", "unix", "X"), "X") expect_equal(os_specific("ifndef", "windows", "X"), "X") expect_equal(os_specific("ifndef", "unix", "X"), character()) }) # tables ------------------------------------------------------------------ test_that("tabular generates complete table html", { table <- "\\tabular{ll}{a \\tab b \\cr}" expectation <- c( "", "", "
ab
" ) expect_equal(rd2html(table), expectation) }) test_that("internal \\crs are stripped", { table <- "\\tabular{l}{a \\cr b \\cr c \\cr}" expectation <- c( "", "", "", "", "
a
b
c
" ) expect_equal(rd2html(table), expectation) }) test_that("can convert single row", { expect_equal( rd2html("\\tabular{lll}{A \\tab B \\tab C \\cr}")[[2]], "ABC" ) }) test_that("don't need internal whitespace", { expect_equal( rd2html("\\tabular{lll}{\\tab\\tab C\\cr}")[[2]], "C" ) expect_equal( rd2html("\\tabular{lll}{\\tab B \\tab\\cr}")[[2]], "B" ) expect_equal( rd2html("\\tabular{lll}{A\\tab\\tab\\cr}")[[2]], "A" ) expect_equal( rd2html("\\tabular{lll}{\\tab\\tab\\cr}")[[2]], "" ) }) test_that("can skip trailing \\cr", { expect_equal( rd2html("\\tabular{lll}{A \\tab B \\tab C}")[[2]], "ABC" ) }) test_that("code blocks in tables render (#978)", { expect_equal( rd2html('\\tabular{ll}{a \\tab \\code{b} \\cr foo \\tab bar}')[[2]], "ab" ) }) test_that("tables with tailing \n (#978)", { expect_equal( rd2html( ' \\tabular{ll}{ a \\tab \\cr foo \\tab bar } ' )[[2]], "a" ) }) # sexpr ------------------------------------------------------------------ test_that("code inside Sexpr is evaluated", { local_context_eval() expect_equal(rd2html("\\Sexpr{1 + 2}"), "3") }) test_that("can control \\Sexpr output", { local_context_eval() expect_equal(rd2html("\\Sexpr[results=hide]{1}"), character()) expect_equal(rd2html("\\Sexpr[results=text]{1}"), "1") expect_equal(rd2html("\\Sexpr[results=rd]{\"\\\\\\emph{x}\"}"), "x") expect_equal( rd2html("\\Sexpr[results=verbatim]{1 + 2}"), c("
", "[1] 3", "
") ) expect_equal( rd2html("\\Sexpr[results=verbatim]{cat(42)}"), c("
", "42", "
") ) expect_equal( rd2html("\\Sexpr[results=verbatim]{cat('42!\n'); 3}"), c("
", "42!", "[1] 3", "
") ) }) test_that("Sexpr can contain multiple expressions", { local_context_eval() expect_equal(rd2html("\\Sexpr{a <- 1; a}"), "1") }) test_that("Sexprs with multiple args are parsed", { local_context_eval() expect_equal(rd2html("\\Sexpr[results=hide,stage=build]{1}"), character()) }) test_that("Sexprs in file share environment", { local_context_eval() expect_equal(rd2html("\\Sexpr{x <- 1}\\Sexpr{x}"), c("1", "1")) local_context_eval() expect_snapshot(rd2html("\\Sexpr{x}"), error = TRUE) }) test_that("Sexprs run from package root", { local_context_eval(src_path = test_path("assets/reference")) # \packageTitle is built in macro that uses DESCRIPTION expect_equal( rd2html("\\packageTitle{testpackage}"), "A test package" ) }) # links ------------------------------------------------------------------- test_that("simple links generate ", { expect_equal( rd2html("\\href{http://bar.com}{BAR}"), "BAR" ) expect_equal( rd2html("\\email{foo@bar.com}"), "foo@bar.com" ) expect_equal( rd2html("\\url{http://bar.com}"), "http://bar.com" ) }) test_that("can convert cross links to online documentation url", { expect_equal( rd2html("\\link[base]{library}"), a("library", href = "https://rdrr.io/r/base/library.html") ) }) test_that("can convert cross links to the same package (#242)", { withr::local_options(list( "downlit.package" = "test", "downlit.topic_index" = c(x = "y", z = "z"), "downlit.rdname" = "z" )) expect_equal(rd2html("\\link{x}"), "x") expect_equal(rd2html("\\link[test]{x}"), "x") # but no self links expect_equal(rd2html("\\link[test]{z}"), "z") }) test_that("can parse local links with topic!=label", { withr::local_options(list( "downlit.topic_index" = c(x = "y") )) expect_equal(rd2html("\\link[=x]{z}"), "z") }) test_that("functions in other packages generates link to rdrr.io", { withr::local_options(list( "downlit.package" = "test", "downlit.topic_index" = c(x = "y", z = "z") )) expect_equal( rd2html("\\link[stats:acf]{xyz}"), a("xyz", downlit::href_topic("acf", "stats")) ) # Unless it's the current package expect_equal(rd2html("\\link[test:x]{xyz}"), "xyz") }) test_that("link to non-existing functions return label", { expect_equal(rd2html("\\link[xyzxyz:xyzxyz]{abc}"), "abc") expect_equal(rd2html("\\link[base:xyzxyz]{abc}"), "abc") }) test_that("code blocks autolinked to vignettes", { withr::local_options(list( "downlit.package" = "test", "downlit.article_index" = c("abc" = "abc.html") )) expect_equal( rd2html("\\code{vignette('abc')}"), "vignette('abc')" ) }) test_that("link to non-existing functions return label", { withr::local_options(list( "downlit.package" = "test", "downlit.topic_index" = c("TEST-class" = "test") )) expect_equal(rd2html("\\linkS4class{TEST}"), "TEST") }) test_that("bad specs throw errors", { expect_snapshot(error = TRUE, { rd2html("\\url{}") rd2html("\\url{a\nb}") rd2html("\\email{}") rd2html("\\linkS4class{}") }) }) # Paragraphs -------------------------------------------------------------- test_that("empty input gives empty output", { expect_equal(flatten_para(character()), character()) }) test_that("empty lines break paragraphs", { expect_equal( flatten_para(rd_text("a\nb\n\nc")), "

a\nb

\n

c

" ) }) test_that("indented empty lines break paragraphs", { expect_equal( flatten_para(rd_text("a\nb\n \nc")), "

a\nb

\n

c

" ) }) test_that("block tags break paragraphs", { out <- flatten_para(rd_text("a\n\\itemize{\\item b}\nc")) expect_equal(out, "

a

c

") }) test_that("inline tags + empty line breaks", { out <- flatten_para(rd_text("a\n\n\\code{b}")) expect_equal(out, "

a

\n

b

") }) test_that("single item can have multiple paragraphs", { out <- flatten_para(rd_text("\\itemize{\\item a\n\nb}")) expect_equal(out, "\n") }) test_that("nl after tag doesn't trigger paragraphs", { out <- flatten_para(rd_text("One \\code{}\nTwo")) expect_equal(out, "

One \nTwo

") }) test_that("cr generates line break", { out <- flatten_para(rd_text("a \\cr b")) expect_equal(out, "

a
b

") }) # lists ------------------------------------------------------------------- test_that("simple lists work", { expect_equal( rd2html("\\itemize{\\item a}"), c("") ) expect_equal( rd2html("\\enumerate{\\item a}"), c("
    ", "
  1. a

  2. ", "
") ) }) test_that("\\describe items can contain multiple paragraphs", { out <- rd2html( "\\describe{ \\item{Label 1}{Contents 1} \\item{Label 2}{Contents 2} }" ) expect_snapshot_output(cat(out, sep = "\n")) }) test_that("can add ids to descriptions", { out <- rd2html( "\\describe{ \\item{abc}{Contents 1} \\item{xyz}{Contents 2} }", id_prefix = "foo" ) expect_snapshot_output(cat(out, sep = "\n")) }) test_that("\\describe items can contain multiple paragraphs", { out <- rd2html( "\\describe{ \\item{Label}{ Paragraph 1 Paragraph 2 } }" ) expect_snapshot_output(cat(out, sep = "\n")) }) test_that("nested item with whitespace parsed correctly", { out <- rd2html( " \\describe{ \\item{Label}{ This text is indented in a way pkgdown doesn't like. }}" ) expect_snapshot_output(cat(out, sep = "\n")) }) # Verbatim ---------------------------------------------------------------- test_that("preformatted blocks aren't double escaped", { out <- flatten_para(rd_text("\\preformatted{\\%>\\%}")) expect_equal(out, "
%>%
\n") }) test_that("newlines are preserved in preformatted blocks", { out <- flatten_para(rd_text("\\preformatted{^\n\nb\n\nc}")) expect_equal(out, "
^\n\nb\n\nc
\n") }) test_that("spaces are preserved in preformatted blocks", { out <- flatten_para(rd_text("\\preformatted{^\n\n b\n\n c}")) expect_equal(out, "
^\n\n  b\n\n  c
\n") }) # Other ------------------------------------------------------------------- test_that("eqn", { out <- rd2html(" \\eqn{\\alpha}{alpha}") expect_equal(out, "\\(\\alpha\\)") out <- rd2html(" \\eqn{x}") expect_equal(out, "\\(x\\)") }) test_that("deqn", { out <- rd2html(" \\deqn{\\alpha}{alpha}") expect_equal(out, "$$\\alpha$$") out <- rd2html(" \\deqn{x}") expect_equal(out, "$$x$$") }) test_that("special", { out <- rd2html("\\special{( \\dots )}") expect_equal(out, "( ... )") }) # figures ----------------------------------------------------------------- test_that("figures are converted to img", { expect_equal(rd2html("\\figure{a}"), "") expect_equal(rd2html("\\figure{a}{b}"), "b") expect_equal( rd2html("\\figure{a}{options: height=1}"), "" ) }) test_that("figures with multilines alternative text can be parsed", { expect_equal( rd2html( "\\figure{a}{blabla blop}" ), "blabla blop" ) }) pkgdown/tests/testthat/test-pkgdown_print.R0000644000176200001440000000143214633374223020721 0ustar liggesuserstest_that("widgets and browseable html are kept as is", { widget <- htmlwidgets::createWidget("test", list()) expect_s3_class(pkgdown_print(widget), "htmlwidget") html <- htmltools::browsable(htmltools::div("foo")) expect_s3_class(pkgdown_print(html), "shiny.tag") }) test_that("htmlwidgets get sized", { local_context_eval(list(fig.width = 7, dpi = 100, fig.asp = 1)) widget <- htmlwidgets::createWidget("test", list()) value <- pkgdown_print(widget) expect_equal(value$width, 700) expect_equal(value$height, 700) }) test_that("respect htmlwidgets width", { local_context_eval(list(fig.width = 7, dpi = 100, fig.asp = 1)) widget <- htmlwidgets::createWidget("test", list(), width = "100px") value <- pkgdown_print(widget) expect_equal(value$width, "100px") }) pkgdown/tests/testthat/test-navbar-menu.R0000644000176200001440000000773515074163153020261 0ustar liggesuserstest_that("can construct menu with children", { menu <- menu_submenu( "Title", list( menu_heading("Heading"), menu_separator(), menu_link("Link", "https://example.com") ) ) expect_snapshot(cat(navbar_html(menu))) }) test_that("bad inputs give clear error", { submenu <- menu_submenu( "Title", list( menu_submenu("Heading", list(menu_heading("Hi"))) ) ) expect_snapshot(error = TRUE, { navbar_html(1) navbar_html(list(foo = 1)) navbar_html(submenu) }) }) test_that("can construct bullets", { expect_snapshot({ cat(navbar_html(menu_icon("fa-question", "https://example.com", "label"))) cat(navbar_html(menu_heading("Hi"))) cat(navbar_html(menu_link("Hi", "https://example.com"))) }) }) test_that("bullet class varies based on depth", { expect_equal( navbar_html(menu_separator(), menu_depth = 0), '' ) expect_equal( navbar_html(menu_separator(), menu_depth = 1), '
  • ' ) }) test_that("icons warn if no aria-label", { reset_message_verbosity("icon-aria-label") expect_snapshot({ . <- navbar_html(menu_icon("fa-question", "https://example.com", NULL)) }) }) test_that("icons extract base iconset class automatically", { expect_match( navbar_html(menu_icon("fa-question", "https://example.com", "label")), 'class="fa fa-question"', fixed = TRUE ) expect_match( navbar_html(menu_icon("fab fab-github", "https://example.com", "label")), 'class="fab fab-github"', fixed = TRUE ) }) test_that("can specify link target", { expect_match( navbar_html(menu_link("a", "b", target = "_blank")), 'target="_blank"', fixed = TRUE ) }) test_that("can specify class, id, and title", { expect_equal( navbar_html(menu_link("a", "#", class = "class")), '' ) expect_equal( navbar_html(menu_link("a", "#", id = "id")), '' ) expect_equal( navbar_html(menu_link("a", "#", title = "title")), '' ) }) test_that("can construct theme menu", { pkg <- local_pkgdown_site( meta = list(template = list(bootstrap = 5, `light-switch` = TRUE)) ) lightswitch <- navbar_components(pkg)$lightswitch expect_snapshot(cat(navbar_html(lightswitch))) }) test_that("simple components don't change without warning", { expect_snapshot({ cat(navbar_html(menu_heading("a"))) cat(navbar_html(menu_link("a", "b"))) cat(navbar_html(menu_separator())) cat(navbar_html(menu_search())) }) }) # Building blocks ----------------------------------------------------------- test_that("navbar_html_text() combines icons and text", { expect_equal(navbar_html_text(list(text = "a")), 'a') expect_equal( navbar_html_text(list(icon = "fas-github", `aria-label` = "github")), '' ) expect_equal( navbar_html_text(list( text = "a", icon = "fas-github", `aria-label` = "github" )), ' a' ) }) test_that("navbar_html_text() escapes text", { expect_equal(navbar_html_text(list(text = "<>")), '<>') }) test_that("named arguments become attributes", { expect_equal(html_tag("a"), '') expect_equal(html_tag("a", x = NULL), '') expect_equal(html_tag("a", x = NA), '') expect_equal(html_tag("a", x = 1), '') }) test_that("unnamed arguments become children", { expect_equal(html_tag("a", "b"), 'b') expect_equal(html_tag("a", "b", NULL), 'b') }) test_that("class components are pasted together", { expect_equal(html_tag("a", class = NULL), '') expect_equal(html_tag("a", class = "a"), '') expect_equal(html_tag("a", class = c("a", "b")), '') }) pkgdown/tests/testthat/test-topics.R0000644000176200001440000001545215100735002017326 0ustar liggesusersselect_topics_ <- function(topic, topics, check = TRUE) { pkg <- local_pkgdown_site() select_topics( topic, topics, check = check, error_path = "reference[1].contents", error_pkg = pkg ) } test_that("bad inputs give informative warnings", { topics <- tibble::tribble( ~name , ~alias , ~internal , ~concepts , "x" , c("x", "x1") , FALSE , character() , ) expect_snapshot(error = TRUE, { select_topics_("x + ", topics) select_topics_("y", topics) select_topics_("paste(1)", topics) select_topics_("starts_with", topics) select_topics_("1", topics) select_topics_("starts_with('y')", topics) }) }) test_that("selector functions validate their inputs", { topics <- tibble::tribble( ~name , ~alias , ~internal , ~concepts , "x" , c("x", "x1") , FALSE , character() , ) expect_snapshot(error = TRUE, { select_topics_("starts_with('x', 'y')", topics) select_topics_("starts_with(c('x', 'y'))", topics) }) }) test_that("empty input returns empty vector", { topics <- tibble::tribble( ~name , ~alias , ~internal , ~concepts , "x" , c("x", "x1") , FALSE , character() , ) expect_equal(select_topics(character(), topics), integer()) }) test_that("can select by name or alias", { topics <- tibble::tribble( ~name , ~alias , "x" , c("a1", "a2") , "a" , c("a3") , "a-b" , "b-a" , "c::d" , "d" , ) expect_equal(select_topics_("x", topics), 1) expect_equal(select_topics_("'x'", topics), 1) expect_equal(select_topics_("a1", topics), 1) expect_equal(select_topics_("a2", topics), 1) expect_equal(select_topics_("c::d", topics), 4) # Even if name is non-syntactic expect_equal(select_topics_("a-b", topics), 3) expect_equal(select_topics_("b-a", topics), 3) # Or missing expect_snapshot(error = TRUE, { select_topics_("a4", topics) select_topics_("c::a", topics) }) }) test_that("selection preserves original order", { topics <- tibble::tribble( ~name , ~alias , "x" , c("a1", "a2") , "a" , c("a3") , "b" , "b1" ) expect_equal(select_topics_(c("a", "b1", "x"), topics), c(2, 3, 1)) }) test_that("can select by name", { topics <- tibble::tribble( ~name , ~alias , ~internal , "a" , "a" , FALSE , "b1" , "b1" , FALSE , "b2" , "b2" , FALSE , "b3" , "b3" , TRUE , ) topics$alias <- as.list(topics$alias) expect_equal(select_topics_("starts_with('a')", topics), 1) expect_equal(select_topics_("ends_with('a')", topics), 1) expect_equal(select_topics_("contains('a')", topics), 1) expect_equal(select_topics_("matches('[a]')", topics), 1) # Match internal when requested expect_equal(select_topics_("starts_with('b')", topics), c(2, 3)) expect_equal(select_topics_("starts_with('b', internal = TRUE)", topics), 2:4) }) test_that("can select by presense or absence of concept", { topics <- tibble::tribble( ~name , ~alias , ~internal , ~concepts , "b1" , "b1" , FALSE , "a" , "b2" , "b2" , FALSE , c("a", "b") , "b3" , "b3" , FALSE , character() ) topics$alias <- as.list(topics$alias) expect_equal(select_topics_("has_concept('a')", topics), c(1, 2)) expect_equal(select_topics_("lacks_concept('b')", topics), c(1, 3)) expect_equal(select_topics_("lacks_concepts(c('a', 'b'))", topics), 3) }) test_that("can select by keyword", { topics <- tibble::tribble( ~name , ~alias , ~internal , ~keywords , "b1" , "b1" , FALSE , "a" , "b2" , "b2" , FALSE , c("a", "b") , ) topics$alias <- as.list(topics$alias) expect_equal(select_topics_("has_keyword('a')", topics), c(1, 2)) expect_equal(select_topics_("has_keyword('b')", topics), c(2)) expect_equal( select_topics_("has_keyword('c')", topics, check = FALSE), integer() ) }) test_that("can select by lifecycle", { topics <- tibble::tribble( ~name , ~alias , ~internal , ~keywords , ~lifecycle , "b1" , "b1" , FALSE , "a" , list("stable") , "b2" , "b2" , FALSE , c("a", "b") , NULL ) expect_equal(select_topics_("has_lifecycle('stable')", topics), 1) expect_equal( select_topics_("has_lifecycle('deprecated')", topics, check = FALSE), integer() ) }) test_that("can combine positive and negative selections", { topics <- tibble::tribble( ~name , ~alias , ~internal , "x" , c("a1", "a2") , FALSE , "a" , c("a3") , FALSE , "b" , "b1" , FALSE , "d" , "d" , TRUE , ) expect_equal(select_topics_("-x", topics), c(2, 3)) expect_equal(select_topics_(c("-x", "-a"), topics), 3) expect_equal(select_topics_(c("-x", "x"), topics), c(2, 3, 1)) expect_equal(select_topics_(c("a", "x", "-a"), topics), 1) expect_snapshot(select_topics_("c(a, -x)", topics), error = TRUE) }) test_that("an unmatched selection generates a warning", { topics <- tibble::tribble( ~name , ~alias , ~internal , "x" , c("a1", "a2") , FALSE , "a" , c("a3") , FALSE , "b" , "b1" , FALSE , "d" , "d" , TRUE , ) expect_snapshot( error = TRUE, select_topics_(c("a", "starts_with('unmatched')"), topics), ) }) test_that("uses funs or aliases", { pkg <- local_pkgdown_site() pkg$topics <- tibble::tribble( ~name , ~funs , ~alias , ~file_out , ~title , ~lifecycle , "x" , character() , c("x1", "x2") , "x.html" , "X" , NULL , "y" , c("y1", "y2") , "y3" , "y.html" , "Y" , NULL ) out <- section_topics(pkg, c("x", "y"), error_path = "reference[1].contents") expect_equal(out$aliases, list(c("x1", "x2"), c("y1", "y2"))) }) test_that("full topic selection process works", { pkg <- local_pkgdown_site(test_path("assets/reference")) # can mix local and remote out <- section_topics( pkg, c("a", "base::mean"), error_path = "reference[1].contents" ) expect_equal(unname(out$name), c("a", "base::mean")) # concepts and keywords work out <- section_topics( pkg, c("has_concept('graphics')", "has_keyword('foo')"), error_path = "reference[1].contents" ) expect_equal(unname(out$name), c("b", "a")) }) test_that("an unmatched selection with a matched selection does not select everything", { topics <- tibble::tribble( ~name , ~alias , ~internal , "x" , c("a1", "a2") , FALSE , "a" , c("a3") , FALSE , "b" , "b1" , FALSE , "d" , "d" , TRUE , ) expect_equal( select_topics_(c("a", "starts_with('unmatched')"), topics, check = FALSE), 2 ) expect_equal( select_topics_(c("starts_with('unmatched')", "a"), topics, check = FALSE), 2 ) }) pkgdown/tests/testthat/test-build-tutorials.R0000644000176200001440000000271214770274305021163 0ustar liggesuserstest_that("can autodetect tutorials", { pkg <- local_pkgdown_site() base_path <- "vignettes/tutorials/test-1" pkg <- pkg_add_file( pkg, path(base_path, "test-1.Rmd"), c( '---', 'title: "Tutorial"', 'output: learnr::tutorial', 'runtime: shiny_prerendered', '---' ) ) path <- path( base_path, "rsconnect/documents/test-1.Rmd/shinyapps.io/hadley/tutorial-test-1.dcf" ) pkg <- pkg_add_file( pkg, path, c( "name: tutorial-test-1", "title: tutorial-test-1", "hostUrl: https://api.shinyapps.io/v1", "when: 1521734722.72611", "url: https://hadley.shinyapps.io/tutorial-test-1/" ) ) out <- package_tutorials(pkg$src_path) expect_equal(out$name, "test-1") expect_equal(out$file_out, "tutorials/test-1.html") expect_equal(out$url, "https://hadley.shinyapps.io/tutorial-test-1/") # and aren't included in vignettes out <- package_vignettes(pkg$src_path) expect_equal(nrow(out), 0) }) test_that("can manually supply tutorials", { meta <- list( tutorials = list( list(name = "1-name", title = "1-title", url = "1-url"), list(name = "2-name", title = "2-title", url = "2-url") ) ) pkg <- local_pkgdown_site() out <- package_tutorials(pkg, meta) expect_equal(out$name, c("1-name", "2-name")) expect_equal( out$file_out, c("tutorials/1-name.html", "tutorials/2-name.html") ) expect_equal(out$url, c("1-url", "2-url")) }) pkgdown/tests/testthat/test-check.R0000644000176200001440000000413214770274305017113 0ustar liggesuserstest_that("sitrep complains about BS3", { pkg <- local_pkgdown_site( meta = list( template = list(bootstrap = 3), url = "https://example.com" ), desc = list(URL = "https://example.com") ) expect_snapshot(pkgdown_sitrep(pkg)) }) test_that("sitrep reports all problems", { pkg <- local_pkgdown_site( test_path("assets/reference"), list( reference = list( list(title = "Title", contents = c("a", "b", "c", "e")) ) ) ) expect_snapshot(pkgdown_sitrep(pkg)) }) test_that("checks fails on first problem", { pkg <- local_pkgdown_site( test_path("assets/reference"), list( reference = list( list(title = "Title", contents = c("a", "b", "c", "e")) ) ) ) expect_snapshot(check_pkgdown(pkg), error = TRUE) }) test_that("both inform if everything is ok", { pkg <- local_pkgdown_site( meta = list(url = "https://example.com"), desc = list(URL = "https://example.com") ) expect_snapshot({ pkgdown_sitrep(pkg) check_pkgdown(pkg) }) }) # check urls ------------------------------------------------------------------ test_that("check_urls reports problems", { # URL not in the pkgdown config pkg <- local_pkgdown_site() expect_snapshot(check_urls(pkg), error = TRUE) # URL only in the pkgdown config pkg <- local_pkgdown_site(meta = list(url = "https://testpackage.r-lib.org")) expect_snapshot(check_urls(pkg), error = TRUE) }) # check favicons -------------------------------------------------------------- test_that("check_favicons reports problems", { pkg <- local_pkgdown_site() # no logo no problems expect_no_error(check_favicons(pkg)) # logo but no favicons file_touch(path(pkg$src_path, "logo.svg")) expect_snapshot(check_favicons(pkg), error = TRUE) # logo and old favicons dir_create(path_favicons(pkg)) file_touch(path(path_favicons(pkg), "favicon.ico"), Sys.time() - 86400) expect_snapshot(check_favicons(pkg), error = TRUE) # logo and new favicons file_touch(path(path_favicons(pkg), "favicon.ico"), Sys.time() + 86400) expect_no_error(check_favicons(pkg)) }) pkgdown/tests/testthat/test-utils-fs.R0000644000176200001440000000106214633374223017601 0ustar liggesuserstest_that("missing template package yields custom error", { expect_snapshot(path_package_pkgdown("x", "missing", 3), error = TRUE) }) test_that("out_of_date works as expected", { temp1 <- file_create(withr::local_tempfile()) expect_true(out_of_date(temp1, "doesntexist")) expect_snapshot(out_of_date("doesntexist", temp1), error = TRUE) temp2 <- file_create(withr::local_tempfile()) file_touch(temp2, Sys.time() + 10) expect_true(out_of_date(temp2, temp1)) expect_false(out_of_date(temp1, temp2)) expect_false(out_of_date(temp1, temp1)) }) pkgdown/tests/testthat/test-theme.R0000644000176200001440000000220114634573316017136 0ustar liggesuserstest_that("check_bslib_theme() works", { pkg <- local_pkgdown_site() expect_equal(check_bslib_theme("default", pkg, bs_version = 4), "default") expect_equal(check_bslib_theme("lux", pkg, bs_version = 4), "lux") expect_snapshot(error = TRUE, { check_bslib_theme("paper", pkg, bs_version = 4) }) }) test_that("get_bslib_theme() works with template.bslib.preset", { pkg <- local_pkgdown_site( meta = list( template = list(bslib = list(preset = "shiny"), bootstrap = 5) ) ) expect_equal(get_bslib_theme(pkg), "shiny") expect_no_error(bs_theme(pkg)) pkg <- local_pkgdown_site( meta = list( template = list(bslib = list(preset = "lux"), bootstrap = 5) ) ) expect_equal(get_bslib_theme(pkg), "lux") expect_no_error(bs_theme(pkg)) }) test_that("validations yaml specification", { build_bslib_ <- function(...) { pkg <- local_pkgdown_site( meta = list(template = list(..., bootstrap = 5, `light-switch` = TRUE)) ) build_bslib(pkg) } expect_snapshot(error = TRUE, { build_bslib_(theme = 1) build_bslib_(theme = "fruit") build_bslib_(`theme-dark` = "fruit") }) }) pkgdown/tests/testthat/assets/0000755000176200001440000000000015102677747016247 5ustar liggesuserspkgdown/tests/testthat/assets/reference/0000755000176200001440000000000015103035714020164 5ustar liggesuserspkgdown/tests/testthat/assets/reference/R/0000755000176200001440000000000015074163153020373 5ustar liggesuserspkgdown/tests/testthat/assets/reference/R/funs.R0000644000176200001440000000070715074163153021475 0ustar liggesusers#' A #' @export #' @keywords foo #' @param a a letter #' @param b a a number #' @param c a logical a <- function(a, b, c) {} #' B #' @export #' @concept graphics b <- function() {} #' C #' @export c <- function() {} #' D #' @usage #' \special{?topic} #' @export `?` <- function() {} #' E #' @name e NULL #' F #' @keywords internal #' @examples #' testpackage:::f() f <- function() { runif(5L) } #' g <-> h #' @keywords internal g <- function() 1 pkgdown/tests/testthat/assets/reference/_pkgdown.yml0000644000176200001440000000005714633374223022531 0ustar liggesusersurl: http://test.org template: bootstrap: 5 pkgdown/tests/testthat/assets/reference/NAMESPACE0000644000176200001440000000013014151774277021415 0ustar liggesusers# Generated by roxygen2: do not edit by hand export("?") export(a) export(b) export(c) pkgdown/tests/testthat/assets/reference/man/0000755000176200001440000000000014633374223020747 5ustar liggesuserspkgdown/tests/testthat/assets/reference/man/a.Rd0000644000176200001440000000036314633374223021460 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/funs.R \name{a} \alias{a} \title{A} \usage{ a(a, b, c) } \arguments{ \item{a}{a letter} \item{b}{a a number} \item{c}{a logical} } \description{ A } \keyword{foo} pkgdown/tests/testthat/assets/reference/man/f.Rd0000644000176200001440000000030414633374223021460 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/funs.R \name{f} \alias{f} \title{F} \usage{ f() } \description{ F } \examples{ testpackage:::f() } \keyword{internal} pkgdown/tests/testthat/assets/reference/man/e.Rd0000644000176200001440000000020414633374223021456 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/funs.R \name{e} \alias{e} \title{E} \description{ E } pkgdown/tests/testthat/assets/reference/man/g.Rd0000644000176200001440000000026114633374223021463 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/funs.R \name{g} \alias{g} \title{g <-> h} \usage{ g() } \description{ g <-> h } \keyword{internal} pkgdown/tests/testthat/assets/reference/man/b.Rd0000644000176200001440000000024514633374223021460 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/funs.R \name{b} \alias{b} \title{B} \usage{ b() } \description{ B } \concept{graphics} pkgdown/tests/testthat/assets/reference/man/c.Rd0000644000176200001440000000022213635702026021451 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/funs.R \name{c} \alias{c} \title{C} \usage{ c() } \description{ C } pkgdown/tests/testthat/assets/reference/man/help.Rd0000644000176200001440000000023713731761074022172 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/funs.R \name{?} \alias{?} \title{D} \usage{ \special{?topic} } \description{ D } pkgdown/tests/testthat/assets/reference/DESCRIPTION0000644000176200001440000000021514633374223021700 0ustar liggesusersPackage: testpackage Version: 1.0.0 Title: A test package Description: A test package Authors@R: person("Hadley Wickham") RoxygenNote: 7.3.1 pkgdown/tests/testthat/assets/reference-pre-post/0000755000176200001440000000000015102677747021754 5ustar liggesuserspkgdown/tests/testthat/assets/reference-pre-post/pkgdown/0000755000176200001440000000000014131662734023414 5ustar liggesuserspkgdown/tests/testthat/assets/reference-pre-post/pkgdown/pre-reference.R0000644000176200001440000000000714131662734026256 0ustar liggesusersa <- 1 pkgdown/tests/testthat/assets/reference-pre-post/pkgdown/post-reference.R0000644000176200001440000000001314131662734026452 0ustar liggesusersa <- a + 1 pkgdown/tests/testthat/assets/reference-pre-post/DESCRIPTION0000644000176200001440000000044314131662734023452 0ustar liggesusersPackage: testpackage Version: 1.0.0 Title: A test package Description: A longer statement about the package. Authors@R: c( person("Hadley", "Wickham", , "hadley@rstudio.com", role = c("aut", "cre")), person("RStudio", role = c("cph", "fnd")) ) RoxygenNote: 6.1.1 Encoding: UTF-8 pkgdown/tests/testthat/assets/-find-assets.html0000644000176200001440000030003014633374223021415 0ustar liggesusers R Markdown Vignette with an Image

    R Markdown Vignette with an Image

    Hadley Wickham

    Some words, and then an image like this:

    The pkgdown logo

    pkgdown/tests/testthat/assets/reference-fail/0000755000176200001440000000000015102677747021116 5ustar liggesuserspkgdown/tests/testthat/assets/reference-fail/R/0000755000176200001440000000000015074163153021304 5ustar liggesuserspkgdown/tests/testthat/assets/reference-fail/R/f.R0000644000176200001440000000006415074163153021654 0ustar liggesusers#' Title #' #' \url{} #' @export f <- function() {} pkgdown/tests/testthat/assets/reference-fail/NAMESPACE0000644000176200001440000000007013671767227022334 0ustar liggesusers# Generated by roxygen2: do not edit by hand export(f) pkgdown/tests/testthat/assets/reference-fail/man/0000755000176200001440000000000013671767227021673 5ustar liggesuserspkgdown/tests/testthat/assets/reference-fail/man/f.Rd0000644000176200001440000000023713671767227022411 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/f.R \name{f} \alias{f} \title{Title} \usage{ f() } \description{ Title \url{} } pkgdown/tests/testthat/assets/reference-fail/DESCRIPTION0000644000176200001440000000044313671767227022627 0ustar liggesusersPackage: testpackage Version: 1.0.0 Title: A test package Description: A longer statement about the package. Authors@R: c( person("Hadley", "Wickham", , "hadley@rstudio.com", role = c("aut", "cre")), person("RStudio", role = c("cph", "fnd")) ) RoxygenNote: 6.1.1 Encoding: UTF-8 pkgdown/tests/testthat/assets/reference-selector/0000755000176200001440000000000014633374223022012 5ustar liggesuserspkgdown/tests/testthat/assets/reference-selector/R/0000755000176200001440000000000015074163153022211 5ustar liggesuserspkgdown/tests/testthat/assets/reference-selector/R/funs.R0000644000176200001440000000012315074163153023303 0ustar liggesusers#' matches #' @export matches <- function() {} #' A #' @export A <- function() {} pkgdown/tests/testthat/assets/reference-selector/_pkgdown.yml0000644000176200001440000000005714633374223024347 0ustar liggesusersurl: http://test.org template: bootstrap: 5 pkgdown/tests/testthat/assets/reference-selector/NAMESPACE0000644000176200001440000000011014633374223023221 0ustar liggesusers# Generated by roxygen2: do not edit by hand export(A) export(matches) pkgdown/tests/testthat/assets/reference-selector/NEWS.md0000644000176200001440000000006114633374223023105 0ustar liggesusers# mypackage ## mypackage foo ## mypackage bar pkgdown/tests/testthat/assets/reference-selector/man/0000755000176200001440000000000014633374223022565 5ustar liggesuserspkgdown/tests/testthat/assets/reference-selector/man/A.Rd0000644000176200001440000000022214633374223023230 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/funs.R \name{A} \alias{A} \title{A} \usage{ A() } \description{ A } pkgdown/tests/testthat/assets/reference-selector/man/matches.Rd0000644000176200001440000000026014633374223024476 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/funs.R \name{matches} \alias{matches} \title{matches} \usage{ matches() } \description{ matches } pkgdown/tests/testthat/assets/reference-selector/DESCRIPTION0000644000176200001440000000021514633374223023516 0ustar liggesusersPackage: testpackage Version: 1.0.0 Title: A test package Description: A test package Authors@R: person("Hadley Wickham") RoxygenNote: 7.3.1 pkgdown/tests/testthat/assets/reference-language/0000755000176200001440000000000014740246027021754 5ustar liggesuserspkgdown/tests/testthat/assets/reference-language/two/0000755000176200001440000000000014740246027022565 5ustar liggesuserspkgdown/tests/testthat/assets/reference-language/two/DESCRIPTION0000644000176200001440000000024114740246027024270 0ustar liggesusersPackage: testpackage Version: 1.0.0 Title: A test package Description: A test package Authors@R: person("Hadley Wickham") RoxygenNote: 7.3.1 Language: en-US, fr pkgdown/tests/testthat/assets/reference-language/one/0000755000176200001440000000000014740246027022535 5ustar liggesuserspkgdown/tests/testthat/assets/reference-language/one/DESCRIPTION0000644000176200001440000000023214740246027024240 0ustar liggesusersPackage: testpackage Version: 1.0.0 Title: A test package Description: A test package Authors@R: person("Hadley Wickham") RoxygenNote: 7.3.1 Language: fr pkgdown/tests/testthat/assets/reference-html-dep/0000755000176200001440000000000014633374223021704 5ustar liggesuserspkgdown/tests/testthat/assets/reference-html-dep/R/0000755000176200001440000000000014633374223022105 5ustar liggesuserspkgdown/tests/testthat/assets/reference-html-dep/R/funs.R0000644000176200001440000000040614633374223023203 0ustar liggesusers#' Example with HTML dependency #' #' @examples #' a() #' @export a <- function() { x <- htmltools::tagList( htmltools::p("hello"), rmarkdown::html_dependency_jquery(), rmarkdown::html_dependency_bootstrap("flatly") ) htmltools::browsable(x) } pkgdown/tests/testthat/assets/reference-html-dep/_pkgdown.yml0000644000176200001440000000005714633374223024241 0ustar liggesusersurl: http://test.org template: bootstrap: 5 pkgdown/tests/testthat/assets/reference-html-dep/NAMESPACE0000644000176200001440000000007014633374223023120 0ustar liggesusers# Generated by roxygen2: do not edit by hand export(a) pkgdown/tests/testthat/assets/reference-html-dep/man/0000755000176200001440000000000014633374223022457 5ustar liggesuserspkgdown/tests/testthat/assets/reference-html-dep/man/a.Rd0000644000176200001440000000033114633374223023163 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/funs.R \name{a} \alias{a} \title{Example with HTML dependency} \usage{ a() } \description{ Example with HTML dependency } \examples{ a() } pkgdown/tests/testthat/assets/reference-html-dep/DESCRIPTION0000644000176200001440000000021514633374223023410 0ustar liggesusersPackage: testpackage Version: 1.0.0 Title: A test package Description: A test package Authors@R: person("Hadley Wickham") RoxygenNote: 7.1.2 pkgdown/tests/testthat/assets/figure/0000755000176200001440000000000014633374223017517 5ustar liggesuserspkgdown/tests/testthat/assets/figure/_pkgdown.yml0000644000176200001440000000013614633374223022052 0ustar liggesuserstemplate: bootstrap: 5 figures: dev: "jpeg" fig.ext: "jpg" fig.width: 3 fig.asp: 1 pkgdown/tests/testthat/assets/figure/vignettes/0000755000176200001440000000000015101163306021514 5ustar liggesuserspkgdown/tests/testthat/assets/figure/vignettes/figures.Rmd0000644000176200001440000000014514633374223023637 0ustar liggesusers--- title: "Test: Figures" --- ```{r} #| fig-alt: A scatterplot of the numbers 1-10. plot(1:10) ``` pkgdown/tests/testthat/assets/figure/man/0000755000176200001440000000000014630120337020262 5ustar liggesuserspkgdown/tests/testthat/assets/figure/man/figure.Rd0000644000176200001440000000033714630120337022035 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/bacon.R \name{Figure} \alias{Figure} \title{Figure} \description{ Pulled pork is delicious } \examples{ plot(1:5) hist(1:3) } \keyword{internal} pkgdown/tests/testthat/assets/figure/DESCRIPTION0000644000176200001440000000042314630120337021214 0ustar liggesusersPackage: testpackage Version: 1.0.0 Title: A test package Description: A longer statement about the package. Authors@R: c( person("Hadley", "Wickham", , "hadley@rstudio.com", role = c("aut", "cre")), person("RStudio", role = c("cph", "fnd")) ) RoxygenNote: 6.0.1 pkgdown/tests/testthat/assets/llm.html0000644000176200001440000000110415100735002017666 0ustar liggesusers

    Heading

    Some text

    pkgdown/tests/testthat/assets/kitten.jpg0000644000176200001440000014335714633374223020253 0ustar liggesusersJFIFHHICC_PROFILE lcmsmntrRGB XYZ )9acspAPPL-lcms desc^cprt\ wtpthbkpt|rXYZgXYZbXYZrTRC@gTRC@bTRC@descc2textIXXYZ -XYZ 3XYZ o8XYZ bXYZ $curvck ?Q4!)2;FQw]kpz|i}0    ##*%%*525EE\    ##*%%*525EE\" ~TQPA 1 "oD@DA@A"" F EEcDD7 " " j PQȂEh" "Tb((QA D*""UU@* "FA@ 4TCv"9@F "*(""#QDD@ADQv Wyr]KD@QF(55j UCv {>{/V"+"A L]^~CXh4D݀(|B_FRJLO>m%|Ķ7=]?]UW]:cXe4AvK;6վ8Līy.2<#PG OWxWu =.7d%ov-yDwn~SyίN೭^lkQ Fpbf7C@Z;B4~[$> `_8noNײt9Y}o0FW=涨3'^hy[\Rv1m(0>{Aύy5 Wb *y3c58(WMWk؇o6=:/}Y hD7( =S)Ǥ(gЪ댧;XGIrdZO}1nA)$[=Wmg]Ӕk_`zkW3Q35ԾcZPPM ( /LM;͙uK2Ãfl\IQ1+.۾]=sɍb T7H{H7TA dql˰x"zvGwms[RݡKʮ*z~c<UE@V( sUعPzGPe'4c^hp= |[p~lkPTQ@TCt_Gc,r5V|FͬkY֎=Sy"M{.͞H(( nDQ`7\o=G7^f}ݤrƮd\}_V7" Uy+EcȖw)yqw,J؛$2#afMlz7ͭDP ((YO4 g1qZpϤ{u-ܻA-+KgA4T{hn];y#S>Q`tFSҺXg͎Dt8f oZ E@ (cs q:K)wYQ6MH-o8 y'>syZҽOK0FsWɍDh@ )踼߈.v|Ӧ~ut$㳾Tj/П}X}#&e$A;㕽~~h (H?(pWuUI&.: Ef';ovvwjO=cgZ5 2 +įHqU8Ӛu\#VHyk,OC{]Y3Vy ("F9f+i=Ns>|vG-iD_h$[\_NzI" 宊rgʹFu~&ISowQ?0rOouH;n3:<ƈTAjnPC=24͉Gz\;L-Μ۩km/ɾ/{o//&D@ "㬧+[H}\`y+vdj5nizM?1As}v{u4ؾO{=sMZAvA%'^b52EDDD{}c|8WQmHˠP??l?I ־BmEͨA"WkO&R _f,'5{n.r:n7[oZwџX:AшDApU k+A7yq*Ҹ0pj{5nɆmfƣ2;dvlcEA& A '0. (WqYhr<4c7ܻ:!m{?3~u^<@"""""5kDžlVG_ +>UxQ)W9%RS,,ws'|zL{s?1 $#Pby5w},! ^vSs(%QYNʉk7[ݛ[A~ٹ4IP5`B9C4[Cwei +)vE4X>3vsBa?F:Q/ E 1#5tIW:JvԯyZCsf%VbbNV[u~^MjpDDֱ Q5P(6CD?.h9.:IbĬ^|΢PV#Ʌfn?/v́~~^lA"cZT\(OBuڭ,ogDq֛:[E_g7Ec,Oq9b $cX5"/v1xȴ6#62Ghdz\:@lK Hw}V/<؈֌hA0"FF N۵2? IJ=? 'AN,=qY9mcԞFQ1D`6|0kp Uzt2J5-d;,\b]uzx3ͪo#Z (yR*6ˏԹ#v;㇗eY$i|bnKvm`0DDֱF#CM."}*LT:mm wo\E+]'鯡c:QF5b5w5Z7EˈpHm9*> dv7O?5Q{[{w@kX#zXK^Y3҆Cˉsv? 6@q"ͳbj"r7ɺ7<#KkQkZDS[ k2 jPuYœWYpVeyK_5{u%gj^`cAs:$]-`G`pSŭ( Ej5]znaK*s[`2g F#֠G9k w!>RlS gz|oU`QjU!F`ئZ[/6ڀ"5cZ:xnN1MePT8ő2V:Y?\Hc;_On /_wWHuսo k֠K AiG"K,[UqlZǩrw%*,]Զ^ש;w5-FcX֠Q^S\b{\tTP>2_:R?OYQJg%޾~Lb%" k#TWg$9,Y6U2qؿct;/Oiyd2)']Yx]-Gֳ-&"#cLm$nV%SMeYpt/֮M d`ɺvư{]4.@Dj#QmD`Cc23>@^쯛{}~M6ʒ{}l*!<};e"@@@TDy[\\OR 9mko8E&Vưuzz,>wM( yxch2AjhsZt _5ac{W·6fU =}WVM QPxj#I+J;Ec2*$n -hڽs]7736D`[=gn?D8+B[9%4^#u&Zzʥ<2k%l#AG=ZZΞ3?w іtq<]9WCV),hcDK*^+bǖﶙ9pDGq+X?WXoʝ/Tlk45 yMrc%TEL}7oڳYNa (sSʦv6Dzbz-~MUW"jZ9Nh/GmNv^Gm" =#GOrOXReqZ:m&un [Q)W{7 WiI'=ܝObs}}^F D+7q\?Zls/sOᇮ>k'/*믤g~x/6}VȻ\]ek+_Id2Kx>uӻ=s9vhQŒ>\i-:K7{iXRMT`sܠ+h5QA珍|yހ~|r]n -pW\9UAA"  *5g0HGGե5DWWEDA@Db"#婮-:ļeY* h  zUxADDA@Aj5v'  \ڀ@A #ִj"AUQ9U6"" AcZ""(5 Usթl mM1a& Mpq=6>0B]2V[|)$g ޾a[:Z} 3Xpz̵v=0g+YoPgW|vXԓMg+._#Wsmf%wO!48g+8;(ǃMmsՄ(K~O#Fn?Ͳ>o`4Vy%ޫ]9\ G껐Rl l2z,ݯU`!BX??Kp櫯 H `B'tSf~A۵NL1+.^s'E'&a#F}Wm<ҷjDsl,erJ%qRcc U5 hR+~t% L% 3>lج5cf@rlNZhӪB8Mʢ940J.qsh7 IEh Tޞaxq!s*5[Zim3䦚bS*UUP5ew*!e{)Wz@L< Elg(֑V@/7NͮKVRG ]˞jHfUn9\|Ɣ]9x.Wȭ.}s͸Ev֔%˧-`G䞫k_v5dzeǒztt:;il 9m͂c!EΣnD`!D)0"*V `1$ZĬb@"&"bbah$+3 @&, DWv"@_-k6_K~O[ \=gqx`{zM*rܶ :ϛ&ks{=߆~.]KO|Ã[>x{>_C=[~go?7G]<_og>w[?K+{9{oc2Vf#$,$)WG]4*-#&fBV1 q($D2!"P@#1 2$03A`BzX+0vcOm[qMhO)\7X-ђm}7ZCodݦFi]h`hKb&&32&2g;|s9#pngb2}r^-,쬸?^͠*\ꮟ핚Wz,_WwXg^f-zWE F$;eyF1,{1%.؍YuV-ϳabC EG"qLO cCRJ[J.,dLaZZ\m6Uk0H5?ySL II+zOʓ$G}C*J?jl鍫6ftc\PnfÇeP:.p#Vɒ. t*w4~qDZk(Њ~jV@Z@q֩-š|\XwύVGgOreuxw7墎ov ŭZN@'S9._M ;[9oi?"wmez<]"Zh(UU5aW©)*4Ɨ-€~#w>UE8 B&[rq%#eO $82qe*{o=M&L]Bß[\p,#AuN.v`%sjk ;/<(sL'ga[~ݓ>bJ >X7E(:vp' ƸRø#y.\ߡ0^Mcwe]4}RJ9V,W8J}T\0mP%u%Ai# 5G~&ԳຣZH'X A|ZHm /Khʻ)SG5ÓRvr}|jUo5dbϰsvٚ-gH@OeI5酟=wp/e;+4Wv7Wmy#;M gnQL'2捞1601|$Y2.oUXֲ&H#YB=;>&i M^ u'բ\gUJdO-z|ڹLD,H` T72y ]fKA6V龱o^ḫ퍒X*܏Z7CLdvwl3FҐA}\~}C?,!l^h4kׄrYAo_W+?3QMbOR>h0 ORp6ЕoEa]B&ڝ=DFU}- |ZN䣉 f*<اډ^Ll{K5ܮSR*~}"y#!⬮-\:3Z lR3uAiRl8T I]٨€+Sg0k~I**gkkw:1)/_ci"C,L"'mp>' Kl45q%Գ$Rho*Eu(+ |鶷:4T}C$f_n5䶮Ix"˘۳Xgfc-0!I~u򱶄HT,3&/۳4@Eq?>3dF]aQG>-SQ<+2_rECXG9J mqM NNW 6i"CVKE#2 c@\RxrZc=8}}__\V["9Α<)q&̖`DN0C,-YO$bR+f&=Jcr,ҕ8ȎЖm i}XCݥW!>#&J&q!idLˀ!\CYCȄgCS'}g"?q77@F/ЭLJ ",{g39 WUDOUc"N\6!0;Q\J_2ڕ+%`m5vzӍvLX 3<@ "J-3KE6VDerCw\17 PBQı<ܪc ~FqVθu>0 sNd[Y*l&M2UO;.32Y)%_W~)y%43s;fybh&r "$GO!hAZ߬.91Avai ٥gg fхjܻ q65|DAgf1]f-,!-,Nh^hvD:g<#^iVV! 9Zf> m)yd-ۈm8;)3q]E ݺmmk;]"n صCa t)b$<Ȓe+)ު%BK"kGXKFc?Έ_rt H l8 @agވ> ضl{T3`.}+]JYCIu#=Ö1败HK 0†fR0Be`K6JDsbӚ!6Q}#'7"}.5bu)5',0UI #xς:nލ]*5nbW; jnZb[‹Q܇ۅf1s<%ߟ\1bg2 hzgOE65Xz8T%#Wly"F!mOr3`1$vC}./צt˱XEjJuϢV7< ^'*eu\ŝ-ˆ,=s&*J6brC Y5 ")fc:=56,%<c cQ5l\,(J;eC"$v91"9ALNk0@dO 1\l+ciT(mI0v|pЭuUQ?J NçjSR`|$S"oanʢ"E ܥjB\N,N{$eM.$ض#YIR3,VSW^-hJe.e+΂߰aA܀?Ϝ`aU尙0~p}FIު^%*g@& s]¥@ذ5EZR7nï~̤֤֔>)E-d,[զPPO#iMEqN'-$66`bވ2$~_rBw99sy`H}e}hO"8,* P`תEFC[NGؙ7ĽevѻAjZz6ͺϛl\]uf$CYwoQYl,dѢ d2j hX;%LY,gެAfC)(j9s9sH aFNB¯%Xx8 VN ĕ >SD6W¶rޫ=A~c{kؖuA)de8-&6Q),lK+6PtݘA"WY;<Ƞ]׎K$YpZ{uOؘs9s9s.d8=m VdJ3R]eĭjnQ\g.4_)˔e.׹zR9`(M6M%+!WdXJ-A2:LJ$!A-DN_oSIg9s9sr8!T^/%Yؿ(zDCUWf#Rcń65a5\eSjEV]#>>BduU!gRFhzR1 0Cbd=c+Yc;PB8&>֥LTul> RZQQRLXapbU,x5[م$秊\J{FʷbeUf"&A*/]lk `0ؒ[2ԭP̤JTve,9s9s?ǜdd16![2X&?DOWn"}/6+Ȱ`,gܻybnVפb=kIr:SZ,E;3}h6卤a6 ]IFWWxZ )oH{x)ǜ2~IJ3 Ab%Vfu}bl7M&lkk6ا,DL ,^l5Wmt@ՊPCn"{Sal@ٙ'V^'NE?1͟4{>XfUSn*5f[ڙ Zr.U^\}r[ o^$  k^g#`J!C%!2omm, .?o&NK'-Aq6 "O2 ei#[skzԶ`O`$e QAqLm!׮)7f2uc,EX*nJn5`C+YBُ}ŝ~Sq0+TTe_oq6}y? g] $B<r#I@F)k.(hmWk1upKc$ aN]eA˝C6&uv w)ַjV"z&z Ky7f =ʐ1MΔAH&fbf y*ȏYrya̡ްv"+ nӚAOhqb|laţ)E MUdsr=d^|ًF@N[@Ƌ՚T&fNȚV":EIjڝbcM<ࢹIݷ01`0JnF!Rϱ2S^<|1wvy%RUZ#5? |~Pv,e XXCKc ܝ(7))a]Vq:Gȃw >lZ#\L?`,"g, 6jmVe5?fB :nƷvL il\s%X?RaV+ֻ8oh/&SյXu1,& L[FjaMd*pG5r-P)Uf$F%ɸJ-gs3+R9aLN2&mkeUqhI-B0{R,;Ckz6E R9u A{n@uۘUlOּ̫{"]YWH=UaA֮BukVkUaj`LS-Ef[hW`)ݷAINec9s(( arg]&\$,ӘbhEq BmeΗvkQZY׮":) eI;Vrj܆aP_g+VçK~6.ygq).ê-Y{Sm㓱^\nv(Z ǐwQ\s8̮2kzSq0Yb-b'*k_+5$Qg_ i XI=49's#K0Ĵ{ |q-%9&YG1{n9_T6O0xŴHC,*]bl*ܰy o"]TZ,,R/JN6WY&.gqz0SE:}8Ȍ8q&m7LZ`^>blyk9M";dHesX۞]0H- ~H޳363]snFeNױ Hhٸ%FMb 6&p䰒z6u\+R+` 2 s[p 3$  +eYi?+kˣKo%XMGnqr9LlA$8MCOcam ,`53fdS31,R}QK]\ su3 #]1WR'B*X2>AȰµͮrݙT=Q26<J!&P&Xʈ:S&7`>-ԛBq{& K3}:s>ʺab>j͆XJ'h9 a4Z0hC$qf3SeSݖ=,eϷ0 rɜE )ZK9|ƫPӁD#"FBc 2 sBXZCkOZL =U[?UXң\AV HMǗ{'uemyl#is\肈|dd&2*dxi G8ŞÌm~=zLWMCι83sM"ϛ6shfұ^U9``tz"bF{mc^qSiO+Dؽn9yOo|Z'fiOQig$bq?6-[υ\7vF7-wxV{5onC@Jڼ -e&+8hL}f+^1Xc!Q#:\Ƣmx;8PH2G$c=c,3Hޙ1XfN>kU+*^][)*1,* "8)ιx38qg\mH,yW-eK #jеOu]h*ڎW¬`xyk(xΛyJ<:mrR3?9o9s?ל99s9s9}sF!1A"Qa2qBP#R3br C$S`@cs?|[U荵wHp?R?of؜b0}UŦx]ęBׇǪc;KKswuuiD{Y6=Т۞5ePuWa2xm#.#CdkwV.$` :T6?n<u='qy>Iś+&jgx> pj3;vY* 'P;8 pas5"'Tkw7 A?GBLQcIɖm FC]tQ"z'puQxD"P`x/-[FiRS_+Ԩ&FF]f_k >v2~9D&*9,7ˊ|Ӎ;aq7ߌ&!UkUFKD v]y[ "mG4" )!E'eU]3꣼8˒"%$Zچ-v%Ibѧ|y;](Mq1qw皍΃M.q^3ztWLwֻm vgt |e&`|cCl&u} 0?izOx^ѡĵOy`3Nc}=OQ!8C;|\Cv#';P%QYZ.QNER߈X":?ě3$.Q|6itF㱟TTAٽ#0/5T,l@''tlV\)kz^ .BmidZrg6Q"Ph?RyBsT!ip"ӧȦ8'\&M%ߢ/P`ȻGȟo dsuDM}ߦB^zkC@kN5Ic@v9ivLu5^ r5Sp "hlW c>i+<;V7K;Eu ˿޳T_b2 e8G-qrt>E= 6=J{&Y#qA÷|4U@ʹwO7DNFqRiig `-r@^˲M 'rwϴaVRkir5Zdq<ԾV}ώă벸`&j4QI{!}!^tQݼy883(=a\AB&:jkL^To4^d7[](q2pFZ:TCsO¿52Y?xwX6NV0Od-glֈ/|HV~hU˧~'kc$Qhcߌi丨GݯNa&]A io ƢH jm>s .QNy\5VtE/i>:]2= !L|S]9mQv]3-Qiո9k4~ctj6b~Tz4y],8`5CSXq\|JYƎw'8F泩B'`dn:ƻNpts? j ԩw%>]K)?a##מ(UwO j׸|g>݀[v"CAqݜ6T鳊2KG"> s sXQhyE-Ĉ=9,(U> 9Ev txsFʘps٢IU#K+'Z"Ne ȣ#I!MR=9!p ' oPWАAsGBa"7Ħj t͊5jd$jyQ嶱D9N!:.]:v5MdOWju?a< N79 AF8'5[7~`]} '|7ڻPs{{O:z[? x.ha9쁕Μge={'KuA: Zz,"7\G*CvQ9փSZEƓiܶt cl8 cDgFz)8S\`]ZA꩜Ds2ַC & 3ISZ+6sx,ԬnUϭ.P-qtC-n̡%2g䎠G䁤 Ĕ׺M]τ|Tx m9yqLòmZ=PLAeLGDD@C Bfciy kG4G,=8=Ӂi73X=ISoL'*4ȩ&$ןScpMJD3zʤqkqa1N8]d3_h < o,b|P4#haѹdUi1|o+N Iԭ}W`+Vh~F8j|fҝ-to9,ynG1 E 6&ɝ6 G9Zk= X"3A13#6D=:E;G$ >(Ϩ[&m~?4k5qZ [FLy [Nd ''}cnw^tYdƫ!81 kyy+y[UINS`d պ`#泩_ܬUK%_g]Rk7^jtMiH ,4G[(T9tݕ a?Nk}!i aIK@eZdܕXBF=Θk[T:Q.#=r(tSu/'S}U :TϪya9!k3Ѫ\:Jwv֎n໨$&?u'GNt{KpVc@X>ȩM{;six:bI;ewר)1ȫ7vgb  ϒ9䋆:ss3þ2WD4 -sm-&:ye<#w n D.h'  z-wZ= y`-w44>)-MtX?&?>Xa%Rj1!9}5Uʎ`J>HnJ88ځs$GD{;vpK0U2 * G]Nuk?G N*&ZwwO%: +hn vaޑLm)"\rui@*C m@8Ժ0ot} exAW!̀x~H49)pOf;#uR<6"Dyu1ZceX5DVtGvce=#PUOc\wb0vXխcv`%PDÈ83 a+Z׀4}YɼX \pdd1=Cy8:c sZ$G3h}٤D:w~H"4h0jQ29'Qp;~Mq@  ؆`C}S=Qhs !H_ƧnI#Q1?NyE޻Xz0hѫ"h4Am`9pQc녒'&B?4x <¶ 't=ϔ9ܵuX@1!;ȉ%m8p1lOAU-E*F'bP>%U}I>klzm%8.DaqϚ9]&v7 'V4iac(mT!&_D1WY5_?WsƤ7椏\Aѱ?s=j"^xa>Z-eNܡ4 "z\'lP@ Z9oI7|̦FO0ާDy,2lݝM9m#KuEx' ,uh݂NuGHcHNy L0 8* ?Aˋ'S-#"ݑFi i[a!07Q֎dʹ NOQ(BwGǡ'ᶋxNe p1vȵp3yO[|HMww][o̦LW'y=dC}pV8ҿYc}hG]ᜋ~82 o7D>j#M ʕf<Be`: 4kCGieYY 2a kn!ٙJN?! -ZgY*{;P殘!bs-m'xPApR˄i|5V磀$S?E뇒Ɵ`߄803 Z2iWԦ`k Ha c sm )ҳ? I|^ꁸ8V各GL'6nVʍĂnIR فn$._5J?ADwS.*x'q'ZL~4UuKzv8"~iELb=C{1s=LDnOA:) #mG+Rk{%(ΫKA^!:8D[R"@# q77஦Vsj"AR6?ܰ~hّ Clqۚ}U₃\OQ!8>*V~hM;h>h+:4!K9D>KU dy~j GI3z D55KY&>Dhzv^D8j?eh;A%SHučmdn1n;|ƅ`:+Z!p_D{0pG~:;8OѐAʁ@'DF$JdcGN%)k" i_T)AK$y}J7E3\Ep3\ ~Ϸ|O8~s<܀yn3r j$e[(hܹ(?"CCFGn^s ,t"!4nfQ]Fx!|6La )w GwGkioi4馨Ō'uTܡb]$k0z( 9(zO-T(΋EM(TF9!E+e]1SgkUi|– 8~&a 5};9m;x'џ'uLX tOm7 k]CҜжGYpTvW9\5IM]>#U4_T}@T7:hW.aZ\cӒt}6'g- }6!v"wr+45htꃇ  ?f+(jRXZAEa -ܮ.=[F6ӪD,(~v" %Jx7V9v䬪lq͎}z!\ `ÓBn;tMez._BZq'nN gчt<ky:sW޴;Pp ^idB-PJ.:,dX%C3CĠ7o/] k?@k?$pxNɭh+ O3N.v~0$k6GMu8.#kT0 ?|dowIJ4lS{@0~@t;l3͇%کwZ-iڹէ֒>~ o4{$KڱAhu2ɏO$\<ܝ:!f`X#E ~J0b)\L*HX\Q)ZTx޾OE/U n:1>qAgxFmX$éG!%3>o>>>tOqʩ*xH0 AeL<*7sOnTjWu oOXjS .iF|3VSj4Kc`/h Kjm#1?T`߆~!~ŏty#/XeT|.?_UŢh걪S)iGۄs#g3: n50 WFct|_KD*i}-ӪP8]j_"e1i_A\tvDc#"E2sAHVf;?ҝWA)(͂8\A[ x|x{ k\x5-|ԏn$ X_; ۊ,/58Z@B C>2c|EJ;YWxm>6 ;PcFָq*.LnSs0rAUli]<˒sa!Fr>P$ƆSY]SkoSwIBs<KP,өO\5GQ?sZnGMS2ٝv?zH>[Nz-NUniY,%V @ۮ;K~}'n}=\m vq!@s+08x8h.* %xpZ`6%m"H5 hVΉn܊twy]QLMh8T]!۹! \u7TpkLftQ i&5xE? UPpޛA] :${ MAa.TeJ:DWemK\zDkb6HFE =y&i&p:d&=NFD޷;_B@ʼCP4Ih`)C 3W @)*e5=Pqo]nҦIG$\) Бh0N.O!rCza$i~Jw2L l:ZUsMhs]H,>u{m n^H5Mm[0Okݼ;6U{=jp{#:\Ҩ4A眅Tՠ*d{F8'57;xc1U@x]CHFoE+Vdp d5q - 5R{;Z:#eW4b& %I!R_j]xGJ?.$6@8 27֖5) 7&(?8XovL;Np"^b5OK" dQN ' |g wZ-UݚNeG#-Uic+^sxEԮ:Cm}G$Ca#MtsM Ntkٱ݈CI^*{#UT"r5k5(I\"J+U3ehЏ݁("n"WvLpK4k䩽xӞ[hپ)$j-'.jGsZ&n'L&xu͍Ahտw8p#L?P2A>X폒@pČnFR=kioG6tSHw\鹜+/Ć8dKTn\qi80s?|ƄgZ}ߢaCc`t+-ROEZZDP Bc ~(o<CW7(iXTpFo+9!^aWdGp@8d[m1Nse`uN]w:(Teg#"9/OAeJsBqu"Fmzwj1̬i [ts[A8j-wgg@]ibfy¸1VZ'Y2 Box!a&T-Z#O@fƜs6 T5 GFg`UJͱ<9UR^91ێ"0XM^A (hmZd@$j1#`8Bvr-hmv? 86p@HKE81w4a{HG1O0׶iy'6CZZXsJecQpQ\9  T8 ~%mlj:O5 &V !(Oz}Eʻ/Nj#4ELH(t'v`9]r 5r_o,.!7=`1D_~4uZ]t)\ *{/x0zS择8OV|tEz\Gn0SCSK/alƕS9M{U杜T۴}P p!4@!e4 e>R?4'AȎJH'}nv a6iQ.iDXU)fע 8_ɮ9d1ƪQXzmVw ʘ@2`,8,7V}P<%C7 `΋!)Ftjo9#Z߾ǪgG"N!;*h_1㎕[$M4~-Uk1kxsSDW'(?n8w-'y9;V\N=JnjtvӉVd!y)pioeV|Qy"ڲ҅% \71C % {Dj<逿֏oݎDTsYP`Gy P?'Tz.5q)!շklA4羈i3th}3]@iʸϯ5Z-8{Lo~Xh!Kͼ)~m?cZxi]a$s[l[{Nz.p捭\+OEdabUoZq貚3`3j?A8pSTO1*@&S{*F:r tkIXjƟ%W1[*-3jbƇBgpٸ%5 85cFr .Z} 喫Ki@8IQYV9 @:m a"ZzZ)!rN2G{ F-vҏ)M$2PcN]z.hcU$9J}Jcx ! 2D(K95LwYfFQū>%גsA әD1({-PV%h[hS#{5Ѕܼ\#p#et!2 `9ʨ)ԣR5Bp: 訢VO4Kϒ NN-kBˣgG>i U)\9P&©ih!?ѫφ$7Tg ծxH^!\ x'6w䆡 H j !`&42ri;(f6L=c s_S=Q($Ϛ`nzXщ$. mULP6?cQ- hO*x<($;G)Y)Zkg>EYQBLèRܷpӺ{ c)2!~9F;HɲUnkP?(?E- ݦ" aW[2¨~EsOTliObe*= $F5zU GDZtENkvEm8(HMnB/G+%`i)ĦϹ2ZQ8Zu” @ 082P:_o ӣCih5U^!QRSɻ.qBFŽKN$PkQs<;E8?hMq~F+䨔@ a9ϢpĎyp4h70 iS;8D pQ0zaX?gA#-5Hגo6Eahe0!> "D#D Z,Pvд] cdHU4J[:iП?![Uy9 NdǵHxSU>!Z KvPjC !zYDGN&4'?aM#Dz[ Y#Dž4Zj!>SFL  o2'( :1K +*[ P'%jA-v?c5GiZt(ۑ[5Q, C*ڇ1ݟcyg;Ear讥\4Rʒ9G2?0 kE/42g(P>)EJӋOV{*hui@GXY0ZcwB'uH{Td,KMnҿipS a7C⅒)kjqnr&JhMPq5$ ,k‰qD"CчJOTB6NrV>^Z-r$$IdZ[~K㓔9YZG%۱‡cslP nٜ8)nTgp ESl d|Hdt*"\=V\'CB h- XX &6QzqdثcEw=v \NJۂ$U;rM{ vVN@Do]ꅦ9eg5EM2 EDBl Q62ܠ+ Os钪S3.]p˓( vwD'Tq+<^V\J:j7š$9@2ؕáVQmHX٢삹vS.SMVįJ7eV\9!GiL++At[ n4"d|K>jXn>yz?fEhZ*A`즴87ݤD7)lmW[u3.<>W*!1AQaq 0@P?ǯ_ge,گ~L?RJ+~|ԩRW|W|T_D_ 5+COϊ*TRJ+TR|J*T_Lrj`ƅێ!\"qI*T*'¥J*T_Rnc|9(Dr1t^FÓ<˗寸 rPw(CQs\Ce~*WJ*TR|:~XdFٔWOʕN0~bMuU @T'qIsD1cM3%a'H0{-"+&g8`h0@Z-[-R_jЂC܁YgyE䢶) 846 @Jh11{%GUEXqvic*s:@hǓk$kULE/գ^awȽ]%)'d @JX`T / 0R4׉ZB/(eUe\5TXj2.ͪ1[ s02!V[{È6 +ia/Aĵub \+MB} އz`>}(5/y%g;#4?7 ӊkP \ $V{Ax/n׈j}#̴,) \bRHkG"k U^nRZ4>qFK)³B4؀Y@Pe_L⠝c!p߰Īb#AWzfUkϾ|AȀS4CGR^a^$2R咺4q|?0>kѮlQ6_JB֗쐲;*Cۆ MJ䰩cܤ,`0!#Z5ٕ$=%{U!X!Y!mDO5C/#$l kn q\-t3O-S^ЃT& <Gs'%&Nzfs Z8?i"XjyieuB̍6T[~ G]d2$lK~<@CuxɄ ՔxfnU 9kX[#qLZnf?d>7I@IAV36hY#{0yU(!:bSc;`:K{Sx@bqR mN4 WF.8Y*jy"5V0Mlr{1_IY >ڀ'gx LSq2ZУBV~,-=F@^ lhIG,!x?cEebpey] q`tkŖ@U^YF`Q3y,z)U+&=dAp#d1P{Q2l ib-XIt_`f*^WY)Gcϰ^A8.S7Zf1f=_WмӜ 4-c -W~̄RVڱz#@x1i5@wTJf-U腏0Ѷi,|t5-V/Y Z)~+=k54, * pbP8}O- ۟au$2*ĪH5q` 4)Tc (}aܢ %֫ fഅnGmnY",XTVE/\Jk*3bK{p¯&Q)n X i.<P0̐EW/VKR7bOd+I[9*(ZG{w}`d)#5e(%4vΉtBsruA[ wAhح*0qGeFglJp(%We׶h0q梣k' b!;<ADRѮ7XXt!B#]Q Xx*_4DFs.u+bQ%ucgJ穙Z,{m+VT(bc4 F0$Oy>01΀Sp":g,H56yȞ 2CO'~rϒXu ;(Jɭ'/iskODh:aj8wZ.OK x}V6b~e(q譮^콡 Јjwg/x#29l47^S4.:;NpJ4#d|ffDf.*5 6l^`  1~n_|˱E:Q+l7͊ԖxS!FIvkI1k) jneZ::ΏZ5 z25>|[r=KUWEi (d?K /ưy>e!ڥאJ-jP%# 7(r]*eP4Ah9`\! !pFJR}!+Zۦ9mGo+V8F & _ihYdzL$Ͽ;2=ăs4HY +X?i򨚅g<]f^J)e  >ma$tٚIH P]n KvAOh: @J=p*Dܲ9"LBB3XTiTL.c0H3fmZ6EXuܰq0[֍t}3`1j.G( eUTcN\1ꀸ:OF^X)t8 &U`4@_ba(*~ܿ*87ѕ]+Մ@WT~\fp1^!ո<S (F9{d#(0)lZμybBڌ[bղDfSPPUR]PBLjSDhsz]䦏,ѺaĪS釰=S:YTd%c v\,uw0cd|oPڃ!LX@<GAsPb(VbQOi6*8k,dշ!fLHN7/'Hm,P 䥟pd#{ ?5Uj!0`J[Ml yfb) L[*(UQbPh)|5EywSxR 2,AʣHt 8ZwRtT$!XRiߨl `x@[cX)V;J\+3ƪ t 8,_,c~l P)JnDһkP7+C:ctV$TcٿQy  Zq,$6)1n|@~Zqbl虅J^Ս)#8.k"I`⅄ ]ljjrU0)Bo(mw3L7edD/"eCw%ۆ#J`ňWDJX\{gf‚")4ėA7×lhU;`/F?Y@0Pū5p=CCwM~hxR[hot)1V* pVhy2vU}=Rw|&Lo [ #BoIJ٠ݎظ_fe :}hFjoEwFG p skt\Y|W0ֺZ<]FmU4{HzU[K@v&}A6D`|`cA^ۯ(o;rׅD/KIh4(О"78GC1o jhSQ&OΙ &tc9, ܨcbcLQv& !u7L =n`b뚁9ol])a g,MPeVy pX]!"!Q_d:Wf|q+xJmRb MmKbg PeEt%Y@[WPV PaG6E;Xc1+HQU[R"A"eTx/ `@V 2Z؄LMY:a´ڎKq5IF:Tr/L wQwAȸ`xGϝr.:Ϙcjny [ E<:Ǹǃ$™:ec9f_ڼK&ع\ D|?EŮǠ>[~Bv, 'nП))\h9~e vҀf[)zp%ԽP8QXXJa^~R;Xa%!Xame,]eEnGc JbF}&ӭ%$ñf@k'f(oֽϻ!#|.8]$)We)#` -r^vY bRg/G鎁N&۴rÛR؛`r"ʑ^_,LJ$Ox )ri{fP0FݿDNХotE[x1V*jߘ9}us+?%=~ecШ_jDw{E t=pLQ5i+RǁD9/Hl˚hf ꈴho'a^e2YJWCoyXL{"dGڨqMca9` s,CdcA0J6H𦖏ҶyEYalش 5eKfkelUY%S^Uq W~~ ezQ@8%]B;P729rĹ.|0ba\4{b gs8`/U .:ŀvBmYja8V#(l+<=ķ`' k>9Iחh|\IJ}TH<֝GaؘP[IǦSy'$eB- +ehtКjv) ꣡d>*e*ʚgM@mC+ɹXu v>"/bTHi)mw@Z+:@L?@ i@DKp}_Pۿ }FECQx:^/\ }Y5JVkBޗ -c0]t&*W_鍊% c dC|BI[6oq5Y F-*b|FO]8K+F 6a-orZY,-zb+[=%t%S&4_ǔaeX  T+7z'uDXZ'׸z];V0%K K(xqu%jS冫\k/%\MpqْO]}2Vp/`+F9 uEh~ [:0oVz$ L;+3iP ʼ^q%J ri"񺱍 `vQc' ze>bwľ̥oܼ"|bg/YA^ h hKhɉ%Iد_͜l(" ps |d,,/\GݪނXǓO,X-P:9/&~<a( w?ңR9i*˦X9{ccJz>) j+ה" vVhSPLS v>S." 8 q)28%Z_C`>mG %֍)ZT4]8M㘰̵ hȑl!cuqM=yP-v{>o,v p ø@Pyn;TpMk9sU&3|-?ʷ(@ADK!̪Z0 KS y& VbV--6<4y>a7CXD"uVฅQxD! !f)f'gFnEG MspPN _ea u|$i QFtj^ [c{MU4˖pV rb2A"D5_ZZeEŒ),в=~K=KY|#0UJP=D!h5 NLƒ8b;\x8r}{\@8pq)0&&ڱπ/CFusq\@[GhWC .s ay]A9Q- ť׷Fd5S}싀v.%ȯ6#@X5M|IW0[ ,ip#c`xqRs42t`({Ƣs Vqth-"я⬛ļTq ZbTFaykÄzaa$("Pb?U?_Zcj.ħ7TFJ+Lxl>^'%x ;C%Ψf[  WQ -$1Nn2{#)(LA1.eWh<0r~CzjFU6BJpS(z ]leZlRRlS0.Y⚎Lan3ʆl+el Lv3Zaśl͑sz4J aP6&/}CW]!WG2^`ut>2D –is^^y&HAzS \ۿEq6)P'SE8j qa7v f7S=%W Q@}BpwNJd(TǛdFBRa7XZ S Wqu)Od3'B®*Ij  # sܿRQ wș-r wz<$`6<'ᶌ0,oɀWp%@]!@l3M T$O#g|C+c~;U esI)N +Д§R.,~?j_g\.3rUѸ`Vm PN*0x "1)wp4+X0AwbI.1(%R3[ 10lGRmI*cQLjJ5_g\ 8EP ]Nj9Q8F-[ J#逡7a@MX8-AcrKtwij41ޠl ʹC"f PЌ0/q e3/l40R/_r<@?vոQn Ii{rnˀ{g8:fXBB|40W회OZ+ak^!{4hXm%IjyK- 5uɻ#MaLSqNV%ؠ'N"%Ff ̬5- "\^j"J2e2 {P4탇PXiG+1o4XByʌcHύCy.0'1ZIDPIb!)zN)v*)([">G E̳R?Vqfbn~ \` YkS,]5l-k˶ rzX0.19Y # M`h(k@1 D5Za_c?#,v)QNf[]0(/`lcB+93KVlLgA(z00#=ѭkgvXLt(/Hx|aʯ=ūeX{o}̔Efd1箆nHani*U~:l@FO_ޑ1z ͓ cRܢ2m sfZ0`_c"`j1D.809rࡶ2jqynad!JPhhB573/-]&,>&`>>N&&4x2Y`HH`0ƠBV pUܮҸFx.*c2*x($[9讔2L"'&pЭ8uA0[,jm"\1尿ZAR K|BKԮMԐ%~.\P <]JBuwIkrtED( O9F+6̨(3EJf 18MmZ4*i D!ۤ$#0p;@IgxUh9=33s2ﰐ8{DVh,4MH ^=ˑ"榊șoL4t m0?)~,D~$H'7/rH`5IUn?G4B#]{j/l]\Bw`e-1/C;%yh3gwl [uyMaup6^).pN^ C'{X282D^#}<QAHȮ5+Phᘄ0Fk(! kG!!6ۆ(^ N4"底A:8Xʂ#KPU$R7WX̑A 6{ca@-Ax?`RrzZ:*z==Y`@ށbcr J5eZ^GB Ő ѭ2?K9]+dE[)_>!yah*LaЬ>  @9 9 0b ]1Giчa2!&eI>KHdplR& 8\GO /_n.8%Hז`V޺d-}d/Jkczn%gWVHa?\C 8EѰp؜BL.V<1MzaױԢ%VвJG^A8mL\  &vHQM`3KϘLoc-4*w&Җ}W#)#20 eFP\wfLEa[ ZafQ3%DO7/4"1 vʴ *n $e#ce 8,XNhץuU2(t+ԙyBcutӑ#vmE5/ FY R ivøT?fSuEįdM60|\I3ae.KeԬy&V+isbJd &AW b1c -WY[03`NASiRn~UfD%*QP=3!T`={ uQhNX8d/y9% !A 0K[j1kDj <==*pĕ@ 3ټ Qc+/1W* BPAT>*' sPC?!ji&tRGFMAىQ+ zanNIIx,щR:ua$pab\ӓZ0Y[ SgK ^21Cَц#4dj8%P`=! ]XXƁ : EM.8Vx[(1?Ԓ"h;;Yg7+•7`Ԥ.eQflB,!vG2yk \~T_l"lLSs~qD(ȑ9k nC!d^$%TvMpዥp̭]f5Ŀ,!0ş*(-'TfpvlG\,7[X @-vm 7(}9%p1"V1O%߅ˠX,H*%1G 1"Mto~ĢƔbs*64%\bV4DcY6aQK(P- .cBJ}cHEȝtEg9yK F}^&QCs/ EtQ39nҔbz 0G$Xv&&n\\.j&J8|$DhbK**0"O`ei1Bj0p%˳{eקے+\$%ڷXh򚊍YC:`U@qCpQ#q9ʱ(X>>Ro(#VL+D3z<5Q%q I> c2bFcTG5}D\&cx+bsshRq/큚w2 Zؖ/Ln?$l@pY!1_Jq.GFk$Q`UPTflt@])CrΠH)oQRJ!cԩUb' @ $"3r%eX,ݑ7N5H3Y,l% ԈhJs dTD5uv# O=c@w]^ZNQ'3aWX*0F vmJNP0@~\4#^"U|^LJ_^U0F-`IhquTq:,2g*&RvY"azW <,, RpJ ?C4In )2$>H|oܸ?-8X\$F\ˑ:X;Yb)P xA|41/ Kڱjpd]⬐F@ET0lJ@*VR*L6@qGO(גV^J+Q'>H2TfWA=EUF@΍BG g: ekiHm?^UGV+dڤe\L/7;"v )*T_ޥ?2BA۞T,# kOs_GXP+#G7 J+~%6&e`4*AD p̚CTHu(@ qQʇ¶~+MϓYrr˗.\<%w.\.\.\.\X˗/.\r>_J%y\ZZ[1h2˗?/!1A 0@a"Qq2#BP?.Ye_ƾ|6YeY~,iYe_/ھ͚ID~1}G #(K2؊g'%rW,D d. p1jeVC_)*R?[-Zz"4-\T_9?4KQ*?Y2Fm~95c!v]W1813b vqiEϤbomVz2:=ei.JYBHݒ(^ʌ+&F$1! dR5yc?9A~c}W;U{fe噚invd[^'G@&Wsi>R8F!w:"i/W*Qj3N'&ISrMZ% Q(憞GJHj6bk>IfQ?-3I6M?j_"V]e'6&cJFm<;LMhhdDCE'\sfƙ4zˊH'#&Q{[}=S3Qۤ&H{YHOzENv?ie䒔"zY>ͅAyBn2bv)ms D䶿zv}JM6C-.3Ou&늤g`҃Qp=5ߓV,nW37+&F]2ͶOOF6f+d };>)#jr+t6HjFij%&mZ|0x0fQ{[/迳U%tzviYq>$yU2}c1_S9IF+ڳ}.)Yq+k5TĠ&Şf,U 3 3O!/,cWřԔ '2zN/&-KzFrK$Mu3w>YeGMZjfҢ1(1SY f6M2Xb"ZXiǿÁF\Q{#S\[mdp*jh)42`9_12U!cJ=lI$wlH|VY~ %$d1O m3+Bp3cmM6R'6h[ZN)"-͘frE쿆dL׸]YdhXvlUi$Ir&$h+_{Q1ߗ/'z7#re&Y /9Cd՚i~>{I8R$+&)q["id+mv;wbfr/⮹o䩍Q[*H&>I5I46_&USV[1I.L3K32N# .K|_d9;7#ctC&+go8IrFM3O߶4IS$](cۥD*uCHcTzx1MŘq Dpv5CIkII%E.l*E%ӿET;P"`eYeLqIG (ԈN b9$!!E~*1K2,DEQ*ĭ. DH|1Z(n$. oj4U&!};"H.fd&Чĉv7ծ%f(lkۘe>xculhl;eȟE4U$$푔sXؤ3w,OqB}T2VAНkY}-qe.!1A 0@"Qa2qB`?/]t]Wˮ?BܢzuAki4cu(N<ů}&GҒV*f,0!T̺X^C2N&Dzf~E=:G,S^`'?GE_َ8!bNŋ&Bm3Iw J䢶\ظcV%\L8B+bٶ(ƙ4woTD™DIu fPkɑMJbssH?_<ۤ(\YTݛ4d[vgIQ(+Ȯ3ѶfMS"+ɨJӦ&(P^3$N.<ˍSIQM5(Y3!E$g$Þm5XۊLMB䵑7iXбKO.In5˟V0($N)Rg&فܘFpBB4&IE;f=JY\j%wG,{Yo|mne:~? ry)O~_ũS[#ZbR_NϨmTO>+{4Mdェ"5X$k7.j1'%&iwCg㒓I0cPH&3ɸ$g',춣IA\#_}dO s|1_䋔/rEɪ)tQgcYOerU3zQTn(l줇}-*chKI1N- TH7BchB4>~ 0% B^mFE;ks$Vihnk)ǃ$j_ Zt'RC*$bHKCϑE"eh͌QE&E=hؕ&}&abl\rEwS"ѵy2I#O{茈MQvq!=d[bo5፶)}¤be2FXֆ"$2iGr>$ll:̑4QB+BE 9]^l[-L䡶įc[c$| DXB}DN}r->#rY.˲'u 2|(_g1ǢD5H=+G&D^,نJ6$Nt(,/8ք4!2D$鮫ً11Hd" 1FR&},WZ"s@-4%f;bآ,Lwća \ 6KJD#d"!fI;V*]eTc"o#ɋUC6ke"Rf6)Q6쮮H/݃c1Y6FԷe)tSHse[Fr Ǖ_'֌$2y7[ԓJIcLWTN/[+z!>fOk%4ENǝv7~WE\בLW^WJQEzpkgdown/tests/testthat/assets/articles-images/0000755000176200001440000000000015102677747021320 5ustar liggesuserspkgdown/tests/testthat/assets/articles-images/_pkgdown.yml0000644000176200001440000000013614633374223023642 0ustar liggesuserstemplate: bootstrap: 5 figures: dev: "jpeg" fig.ext: "jpg" fig.width: 3 fig.asp: 1 pkgdown/tests/testthat/assets/articles-images/vignettes/0000755000176200001440000000000015102677747023330 5ustar liggesuserspkgdown/tests/testthat/assets/articles-images/vignettes/another-kitten.jpg0000644000176200001440000011760614633374223026770 0ustar liggesusersJFIFHHICC_PROFILE lcmsmntrRGB XYZ )9acspAPPL-lcms desc^cprt\ wtpthbkpt|rXYZgXYZbXYZrTRC@gTRC@bTRC@descc2textIXXYZ -XYZ 3XYZ o8XYZ bXYZ $curvck ?Q4!)2;FQw]kpz|i}0    ##*%%*525EE\    ##*%%*525EE\" {{,hGIve#Grw*Wr1Hw"1.hc&"]R:4tR{Rܪ!R=w4bSʮF.T`&NtN,=+ܽȎsB#h \DknTh Z19d̔wƎI{W{!G91Ɗr#n^ww1_QU_Mk'̖wǎys\+Gq5ʮT%0ĮFSM.A#o>AH␎^甅!z )ܮ^F^hbWUA #Bΰ.A!H^kb)B+0ƍ-EU^j2_ůkB˰.AE|!Hr1gsA(X^j2^ܪtkFơ%Ms20ƐR8{9s{xbj+y⿻U=UxְmG˟>\0{9s{"ċr5*^Tht5،k.|EWAHꪎ1 )(!ĎzQ U^hTkՕaa2I8W#Qő$RrcÉ3Q/*/4ZjFjʟc2TŐR#׹œ"IwW41CKWs-ji5kZŕ>lRH1R<ɕ"IWs(qYʮUNe ]5%d&#YoIe:TG )$!TqJ"Ah#B #9UF׻k֤ d8Q_ ) G09G9ZA>W9~zw**)*!k8s yB^^Sʓ&Tz (cW{מUQǁYKEQ|o >|v )yɒr=zaB |;9^dx5TU5jr iM(T B]LR#X0aCb+ȶw;]-D6d $q,=j .\#A 1zuܬ ֺuR# !|.\'#sA 0؜{ǃUMEI ԭQie2\$ys8.xҿA'>Tr{ܭXP C/=Tv+g%ZYΕ-% fL&A@>q'/4+))%n/GΙ(|V3s4x.\'+=BDWp?UOCG>(tOMU]ek>\1I6|åDRJ6\{E z._ʋA2W"|L| i|q7eL({ bLse5%{枾/GdD l)dAfJgT hp BGyt=Z`!VSR՟Ϳ"}&ѴGk=F ,Jc:h(MUΙ*A9(Р=v?0Lzj1}沱{믞PzɖՒlAɑ0pUY.T# c[;گA~HD_~nՊk@lҦ%I$ϛ*IB=Р+UdJښ^ .7]miVGi5ôUGigEG6\#a@;:qFb!0tj/=&f/V+O|rG@C_],jw=qd24H­a/9=w=$H[};7K7[m̗6\<{}uu|dg/=ysE(YSIY⟛r>G`3WysWn8ߴ{hO"l*W=$&'5Tʊh w= o\}^)vwTLϟreSտf>.A3Q^}95}eE< >w{^]̦i>98/Z;OgGPiE{,ښjp1Ryϱ:1y%*jm?~k|SzuiI|m} ?ʟJ}c1,*{j1Bty_SUgEd|=|VNО<[~ko {ɃaraoqG88A4XqG!{sz:e}Hq ::Ϲcxd(5S\C{L^Xcyߝ 1igW"Qic}yŐc X5a`;9͖Lj)Y-.^WÝPJas;k/ٞ!$t@9;yȓXD΁khj,Fz&;KҚuA`}q̐5!…81!4Σs 0%dqQLӪO= Uf>Fg7Ky_:>,:Hǎ0HI2!T@Yq(4B玗/v*\~/>{ٗVfElL GAm#8Q;kKCfk8ޜ#cDR45I?Mgw- }Ag&\D`@a0Yg}w:fDGj5TVWVAesgѤUH.tFRà + fKA!Zʤ3#USg ێ_c;l9˜SSD&Xol=75vonj1W#@H51,e^h?G %L\6Hjv{SU龧0&"r5sA ,JK73 TOB=vIH|gH}^/|v6ǯyN׾c 1NG=#meFs]Ĺ% ze*O|Wӵ5N;cͥ~4l8B6"7y#@POGvst2 7J04+ko6KO1fl!86"5;]l0E(U}'V˿4YLR8jGyW:mkrcBx;#VVÅM JNzGy՝,n5lnJxJq/^F#0CB81j`>JKI=3-6W>\)v35ySeE|?7֟\֣0bD&0pbUƉOB_WMSGu!m%JAOAC $ƥ|[Q1` 15d(ubŋ-GUA~bހזR4<us;]s*LmZ"50l +jjcmZ{rcL<ۋ":AΔ4iya֞F5c1 $8HH@+)t6p͸79[g ly6rkFmmNkyh0lj *xlt'ѭ,UmiG`Gd)г82/#$Hc(*s:8vVjlVʼn|˫qhkYG]g6:լS4R1J ""r3Gΰ{B{[)g~sy&1j4tUU\C*Do#FƣXֵQyWjGY-LTt}&I힅6 Zgkia6YOȈkc@ךakp2-ytS{l}C .?AYAYVsIHo59kֵ`V7-E;PnZϻz~Cu/"D]EVvSLPDF"w#ZֵkG >lBJvuw=h weVQ܈kX0B#B1ap쿒Dbkuv7 O{?~~m].|@ϟƈF5c1G,8UTՙ 6tO/> « i6݅֟=;}f~vmpVCt )7FX h!G8q RFP-E͡eop u3s`sNDF5cZ1(q"Įng$K<{u}%SeSu]|医^o0qF:tהj#Q`ш1bć$Xbg98DLƵ(.~Gzn~Smj ;9ֵ`E0#4z }&CҲuWnBVF齰6H95a8uNDcFǏ]K1U3={W]f2[ kai/DM* ͤҹ0QW~rQ0xB#c;>C1JxFNj͵z?y6|0lb1 ?NFbDGB64Zh~asÃ_Z*ovz4[+ R\5N9`B " т4 *]֛IYMOQQNv5zݷ>m 6Q?IڈBB0@ -<83=>&\%꺊L#+uoW>ly?і`#b>h <`l!j՞1K[_YOUmUaڻP\Or*1" `1! L cXof9uUuTy<[ n?DLR9`C1 k0cC11x%zO+v:J:R2=>5y;Ix}ƴhF 6a&1򿝼I$]$HwQ4F2J#ǎX>FbB,#W^vO,QVRex}>=fŃ] hpFW1`b`Ǎ>Ee"n(Wy{[K) 8pkpF0"ȜNNFXb pE4z3.cL,~=uv绝ʤ{׃,85ՐOg_{GF2|:1j+&@>na)p$euIlaZ67w{ZS9F7NI@ `ԑU|U]vD})i$[5(PzɌQ6=z:Mw3̄! ͔eFӲXg0I \)7ߤ$;Idžj7 + %͊/I$J"S݀A͜ jRH`08uTLEQ%0`ˋ5i:wR*3e sroM]&zpX6eߢoGя?"2t sa\iӼDgq95g] #~&2e9\^]=ΏPT Mn,8 6S(/>eWz߼&xqf4Uw/'=j-:>r݁=]}We',|F1٧U 4ʾ~IקN9̷ֽLGLe#N˃yy)Uw?^:Vm3ژVלoՙWvytB Лߙ\(1:G-6>,=l aeS/QCwծS@Yeq>ݍt g'):eSmu@H)ګm1E0! ]6X@u7)ݰ',$)DH1=YMꀜ l*9a t;e] d 4mkCt;(d焍<3C˱猀n/@Ҥ x'LSw]*nrA[<9W7t,l$t3{sZ_W^3[k;zލevR|U]+{ɼڠg 36_O|gE:bL>~5O|ᶒt=1捶1ne͎Dcy{@]O֮1ʽSǞ6~<<K9nٓ!(OWsOuGF&]JG}'KUmɖ-MtoB"%Vպ\Fpr[4_W~Ky&]2m'z19Mol=m2-V ӽyMPJuNcIm+w5X˦G$tѦ6^96Sb@ yR {VJRۦecJLEyLSÖ)BtgDZP5^4E$mYܧL2ޢ0IV]hcc#p;;"*/|7L\^V۠uBg ˇۯNl*:phtȌ8Հ7Ml&Uλl$H\;R˗PUpP鎥:8hLMɣp mٚSd*C#<ǣ+}puJ 6R9@e#׳]scꠔuך$O5i,Q{9)T(wDD[mӠJTULӌ`!n 5/4qe 0(tߥeUVM>L#<]ʌǷRmAVOGL[qx'^z􁩇vQKmE'EyĒI>mW_O6yisRH4D[Ξz昤I !ZMջßMPL@ M*<8Ѿ4AUNz:eKB$ dٰ)u[m$20c֚D& 0@66>Igu#1B(gg`008#~Cpc(q aG/A08A8A z=6cCq0!P8pb`880`Apd\|o=6c0``p0!a8L?111qpzl>.  >.qcapc.>?bbb`= qllll?~'$qGW67`38cal|$1>b+c 0`08Ä6666Ȍr\ ?Abc 0`>... 0}Ol|%rL>>6qL$'}&&.)C. 0`> 38Q>qL%'> LLL\\ 0}F  =\lll|lo8&M~bbbb}\ b}Nl||l?6>I>q111q}6cCE \0zS0~8&K 1x 8. 0`̌T..... _CGqL&gf2c 1s$qqqqp`}l|||o8qL%1'1q}6c 0bfAS)c6>KL% @8} C&.)Rq F>1OH]...... dz0~$rl|a! MbI+N7axL5\\\\`{8Q8&McJso6Լ旖XaMph *Il>&"#Jhuzڹ+`pc}G2\$WvH Ws!>A[B$)L\\\0zl|||`~}c.L% -?y]v]㈰LRp1qVdҪV0`z8qÆ`,\ɒHkss45 ~(mk\!h_8T׍=9jk  =G6>>>6$̆S)|?^seo_gKw4%uZ8D?j2$Wz \Rp`A7z$X2LLm!洚%(n؅]RBI;Yp0I 8LR0`=ll|loK,X#J]fs5-A_e%%3چSjG^Uyiɉz8qI$݋;H IW + ; M񍷌EV,ɯ{sXM]SQ_mZs,!pWbXnݻr80ab\`a׸]i]-t-o5{Wȼsͼo5NZ}y=S!R7!sس3r8~ܳ D f`e&Lն7Uy!zYVYhnmOȬzĂP*'+ҹZy+Sh5zó^@ORO%Kn7:{ں; 6GK=nUÇ~I_O >D%W䓜`:d|ד5|_`O0Z _૊cqs7Mmso<{CO.D4hn귓D]\8p!I$Yd2Q(J%'' YTu*W FuC#HH3Ç9=נUa%2f^a.*tlݞզi 7/ot-bwŊ&]c2֫SeJ&Dĝ˳3;H\$Cg8+"JY*yF(ER^[7-ITԃoӥt1R -gz+,j>$>:=pT+VB0]\cḚeV۳:U{956fHj MU -]ۯ~n~Q%Ge`I%z>yԡB , b p2LتU45r$6$e&5lbiO)yʺ[PItr"ʲ%7$660`Ap`:*S u *n !Cl=tZ.MB]el֚0KtjּKaZݻOxNk *,[YY +נP tlPB3@u!6*>/Xca͖A&mV~jPCQMfoqf̀,c 0f (S@= +9WW^j+MiY: ѯZͅ[EWOj.%Ib)': AQsqʸi4r|R,vRD16(cZX wDbZu%:f 5#A=q^B zxd1)24Ζ^w04d5zZ7G|m|_Ox}uihl&CEfN=qUT(U0n6B} l#$2ZGゕ櫬|gvZ㥋OC)mF 2lYRdv$deǮ `>7 #G DYd%NIZYdT^GWNޞMfƪi}N2FIs^$^XcЯyz!aF1YQ&FʳxbjREMZ~x+TUO[S_JDruZ#IO|*P  0l(ѴF>$ ]MvT%m hR]^ LX(VJV2fK!Ϯ8q7!` 22eɄ*[+FiJZ4Q@uC0"""lF~\HV*T8bn{ JҴ+M#_+ѭIW۷`#Asd.J3íʹk׆ydjԾ Ԍ&+xUT.Gr n+m"pRz 7pasC8&IHy*d$*Q ։k[G*8*BݝmEnvK77Iqᖜj8p*AS DBdh%YdyXLH>Qp0` kn --`^MM`*AAd!u(=()2&Mu0('';UTTjնQMJζZ%H*C+)q` 2c3I,5`V!`Zxk#|Prp)Fr%g]oSoU5hQ C[kkH pQ&Lf?3*Q\՟qE}SE$:e)N%g]wOsQ5XQJ, *?bXɒE341؂ػ;y/ګNYv9ʙFƶk!-[:ۺky-^C[ *UR8FG$2L8EdXNAIKsOZH|nҎCsݗHJ'bgKvml]Ku ĘZ_Z64SA2A~g$2䤇3G"SQz[_Z-5UY'WF8s3rXnio8ND.jz*v  YYH gq L(j9jEv)Ak)\Ȗ93c̜V@Y#MS/:b%㾈  1&PєᑤY )Z ]m\2@Ն# ~eeGH]⵮x8ޛh 7slFAAR61|>38:LJ+$#ڳPl*4sI*nܮF͒;oY'mi44?5E^V:## VR#}669,pDoivf2KT=-|Dbb92Sars!U<]-RxOJ8AA*T69p;3V4XU-Yюxڰh]9uu+ L&YTeue -}˿/xo 8  AFH:ʍ (4z)g)vxV͈' ~`Ѭql&IU$C)k56>7<-AA2*A}|&Fvwpq/(e +yNmxR5UVDN&Yă9#̤`@&3/pA!ÄK㙙Y0E^c\eRMsne8C(F*!)'Y?~I8pÇlbĽ.0 j'bK(d ª ZCn) bX]pAKɖX/'?rc}gfig콹o˰[ڎVɌV -Ï$a۴&F%ĞLlG*L2EJfD86S DX+Ì^I,Mrmo׭z uVX.ÏF3nj@&Iݍgl6)ڭb9dU@b=6 e|.d1ٹw<הXyMQ U8\YRGbfk,bڵ`Ǖ,YF,d!גG=f$LrA=Ln2X( f-?Cߐ<}׫]؆Y2vE S$# K!Fy$Mjmf=/]ʲx7h10Z{N2%>N˳yy%fK>ݛO%!jԧce֨$^a Tbgkvdn;pZ&Eŧ{vͫO`N(2|Bޏ% ml5:cM-^[Rgx YZJR'kO5$f:5YjWdX=&Itf~oÇ6>J!v<1 AO4~KƩP>,<=RIb3ʓ켰O<ɱgW{PI,%fa( ݤ[g< d&Ia!bYGYY'%GuY3o q!eN%(׮ZixΗuV<3\;$9Ԭ@^T) %˷[݋ZYfirdIY^7y<<РNJx<,Xfvbŋ,Y'9lb(DD^5Ku%yH&aקku=y<9xk*  yGF8}A`)qio`֡jW]B|vov|+—W=gA5 +%:JCV  ½:tS>b1Fc(P I%;R-#ÉUY\UPN:bםi՝GoD|y|v= z|M:tקVR&x¤!qqqqz(Ta05WԞђMmw=o]:/+>:tө^zסRJh6Hep0`qqq^zt1|&X4:ZBN:uׯxԎzשRJ*JCX088^8g^8ԩuuuR R]]$XdӆÍ0#8Fx^8838AVWFGGI")ÍF!1A"Qa 2q#0@BPRb3CSr$`4p? %ș?`c^>KEe~iIua7M`}^e=6F`ҩPT/`ZQ:LveĦUj'_ya62ďs>c=")V6\+4qY|LBZ[=;89yN.9tU= ʊ-2bRi*vE&k޻)!K %@%lhx3G )_mDg_P'g 8 Cd* nzۭ1UldyψB|*Ji&h>#eubPL ˮNe{# l\u ovEM`TZjpKdS9 ʺZZ󛂤[j·Nܤ_.&]@-k+Uыx{O u}ԏ{-KHwv.ŌZ}L6 ,Pk5RPQ?Ke"8`D)]wXn#)݉h/_$B!Uc5],*KbNLn* ۘFuN?ؙDFu~ҠhĊ5QB9uWnU*QaUd'=HwU}%I<Q)OoSif+7hYWu*ᨾG}9zh6ޟi*S=zf6}zVDG"X^7^!$1!cc1BLW̠P\.GIxlA-[b\FGb ۘ( <hgC6N*~֙ *;R^!oȹ4B@!FFPAi%} vJH|+T GSePW'֖j8_CzJմ=>=*b>r37+UUzyE;Ys򴨌n #f^[^&"-MX7 `h=ø!Cc*Ppso8) [,5 p\A|ӨNb}WC1 Gbu7[MWevT]o%)󷨚NUf# ݥS{Aj3)vn }WHMZhf-J(*'Oij FŶe, L m M&G@D Ŗ8׆[OscBT\ F?l*u {d,jfWSTr `Kq5mBU^HDMQJ}y_1(j;8VFNi?ߕv{;2JPdyR]WeV[{6Su:"jEڌa A ̀z@jILN P BEzAm>dC,y:e 0 ZDÄd1X~[MAq|>vosu R=3,Ӥ{m,J7K=FJ p]]rjjoLTt ځ* *i0*۪q+vf=iM:tW#4FnZHoS2XK2:^oT5N#+oD6c~ZTCNr C(uFJy Ii,/J)1VV;~1E} JB>PbWb $߬eh.9h R b0%JZVɼ6JN VO3X^ԚoiHSѽa֙}9ڶ ۃ{4L*.A`h)jPB.u_5ݛhթA*x>bi[[IZ=@]wR P.,=|J(ƣ5fi 01PPlhvXӪWG(M&|;Ŏ>th\Qy1iHFaoѿSw,*/\1c Vo$[pDyߥMFn13]/djay>F{m2&zEesP8&# ĸ62ܟÌpqҨJgR'#fOBco>fi补uj |=@> zhQ:d*_Y+K5:o˷tԩOf=D`^[X3#=#l܎~PkP.Fl" 3k+sɰPR98à2V8bNQA: StaڇȲta+ҪթUOHyE{PЕHJFW}zGIs}vIYlkQzF ?)xŎ261JiB /Ci^fޱj5JYjR}OUxjjd 'XVXfPg*|`e:EjS-+-J}Ʋjh5HDDWڍ>KI ::R TSE\ޡEfp!Xm~>N;|ds`t3cBU!OرSbpD؄ ^^_XiuKJoC?-bGzMOg:}m2>R7=uT.VVCS㶡[K4U7Xqc4ڝ= &f<#^Щk` pV?6t;AGC~֔_PaͦZ1OAG Rz b2/5jiA^B6u#zn7@`L1aLWaz2ѿ.5|M%`RPڤ65-EeF' X\ΪE|;/lme gKkP,r>bRX8X_} za{Rm)x+'yF™_> }YfT{s \e "MLZj@\5`l0? *`7VhW5]Y<@|P9zoP;&D\o+#t7Mm٬ i~DfVZu69Ρu,ŴՏI9 iJ&%jT u)+Te[4EZ'̓ɟßV1N"۲8žbͦz=@Wrf~=ZLƦH'ei/vVaQQduS `Y6 CC E @mZvtV5]V+ije52/-y+S-2K;zJkS`^MR5pT֙W\$Oen[ZGxYM’Te`mlBQN!(QJVwWX6EI]\k{!‚K5]5 WiG܅="1M-ź^h|BX/ Rܣ2WAPǙ]\R+ MQ EQu13n Omٔ ڮ' J|'L~SI7넭K2RCҪajuN$ ?R;j1u:馦hVS?{+4Աt3=fj)ޞ2G4ۣQ+v_j>V@TS)bř.Lн4qj[BԨF}QVTB mۍ JzѥV\ogJ +[|SZS닋_ٹfY 56NRpllZU=g`}oHl@bmo=axGp?R;uȔ*R;V, yhY/J6ܤ3Wٴ)] Z7 紎-Dg&ITb"_9ooI3aqP%|ʕ.L^)$x6 [D 2-Ѓ*|#iUmR TMU#P⦐딲]ZT\yMIi)5Z&h?ٖ\!^-^Qh%H7ǩB$ԳRGK5 UHaɽ/4}vU=Gh1pͱ0+ɶfzܟmaiWR*3ޢioѩ_!YOH.iBW q6 pq O؏D#A7ذ>RJpEMϬ>-o"rώ2uP׊ JEGE 2i_Ċm*#.#[%>&vs. ¬ 9)>:cA[ )CYW8jU5J+f ZN*x߁yzBi .f_U_PnB!0^R F`majh˼YOT‘Q.Np`cUPǨmܘi}ġԠV𷩵Ri D,E tծ:ZT5!VBset$X"wb}Hwr2hLiӐյfAOPBp~Tݠcp,~cST l*ԹPּ A_^+  ۈQx]BE4.>`M54ڕj)l73PR^iT=D@o hJPjj͖=  NO.f&RCbL joJ+smnb5*Sjm_a5U<ލG͔ѽ)lLӷN֨ܖ}B+QuFߵnHP"jc4ui (p.p,䶥C1n7ӹ`f= JB"Uk >aOHyu3Lo`zZi7l[?*15X|h|S lz͋Gwq&ǥJ`6*g5ŘSmAJnZvUU){N}ԒO%o:bj{^GLzM} J*4֒PǙqs(WUB{)jjIU ABJͱ55+iҗ-LCU.pn7\ XMh\f/n4ڟieՂzCj@%mItWO8yZBEڢ6:z4odE<oUyi_? [#ҭ17yw=hfͺDe @E}քaA=S*=n`qkʋETBmX\;Ś J./c{+ԦnPg3ڐ`1+ϣkYyzE.Xt|l(7c?2 .'p Ԛm-`ZuB1jQҕV$x3V7[En{i5QZNj(5Qzbki5lU% >S5kl5&jvJEwzAPu!Xl%=#&QY";Um-J fwR_*R*eYG{cnUV}m7IIk_S{dQM(7O|YQ He8$@`Eѯ~Q,!3`6pL6b{Z ߬˛K%C{TTLξK  ؠ NzPP.iRCNS ]{ER\`) ` dmpqjiֲz,e%jGk(>rrMAh4s'jj}* pcw;M 颽fZ@= 2p 2fTTcn\}XJ\]ԝ jj(# JM73g$_R6S DS[ GW?SNekA06C!?j11 "nb'&.DlÑiv qܻr[x\:Y[E6iMS}VtWGDj?Puϲoog!JT96Zk'(*tӮ) S[T;_X.fqd|Li 8zzHNAfXo!)!UgU=1(v_e=Kn2|a̻6'0d`< tb(?]ߨm*jm_ W下JT@BS YiJyQEeb=3ʞPSRJ_>o%WaMҽc&tgoAhQmFVkߐۙp3hXna+8fKqcc2 SD y17Ȋn&ǸmIXa!Ǩ6B(a`U5wK%ɴQ O(a0d?93~+w'#2H{pV?Aǫ^g*nEI̙jAF()KuTolB^Ш͉lPL,ynmqcJE .A"@#Ӹ0g| flG7XI0nn!(ۭф-V|*n^kmiɵ@@&4SH筥 f'13mH4 d!bK,m/Pp;a%KRiP5`{'*/ /(!U7wBC2Xr|k Q+9L.X0l`g,E>XMɅHoRP%)i^LZ=s*1h:f/*(2-{GP`pi,e/yp faMs :Z2Lm~TfN}Lv| )REl%=gȟХ:I-s(<@E@# =ḨmvGA/a爃m`O[CPTJKN`;VE[ڒ0kz3R-ko(@/bZAdw (Yr nטI%^=s { 28.JX{@%ŁeQF6 ݋R_,5csqct0*?p>$"Ap/K XK/xn/݉`a&[tSӻ?v( AῩLƲjB&j)BU997Rl vig1TffI A!# 1V4ɻ8thiĆ[=&; -;!{TS@o(9.T[ȊIX˘LLAyR mЎ?;{69 j&{hYzGKb,OA}xwD)iS*SchFQ,2LW,oJGa=o_чH 0 >/UҒqe.5*gkcדY!]$# k/y8il:E2p0!T߈k0OY}`0h0w!2G<*"+[)񞧁5U}K'JjNI3GzCuVA5: 76P-k锓"_xA6/Y=atZ2=X0%JULpJZZKtS)iTXsʵ{Zr׉N;. ՗u=Pz•=aRN'֖ކ:Da ̴ q u~ }z0"@&Qq5l~LAnSeBy`CSSۈN>nOn}&nokHcy3pA߶\`=!LrM^%*Lgm%CǓ)ӧw#E}Mv&ȣ(%:"?80GCyu#KK:rbxX 0IoG@/ܓ5V2Ó*ۓMUQ]WOVgNzzRALu*FժIjPtQ`XJj8Q*JN?GbQ;#rn%EkyzC= {2Jr`&#u`0 􌧈Ay&bA'X,<ɔ(^ $h D-QPNZkEv 3ドUShoň nhuw^b^^TBejM̱oF`1OIcap!3m939 Ff79Jj9Y #EcUɛnq[pw($ #*6I67&D @y܉j/8{|CE'FS`0AOL@`7Z6s  =bHHe}E(0~U1#= h6=& R2Qy x^Tb%M8=l%B̄$EĸxqCzb1H8!i^Vc-)MbVOO*9cbbX^k(#s Yl:F&a(zGEf#(B~!+|^rfP^3bor?hPJ xhyKE>eǹ61XX@o݌/V6J􌨖E6Jn#pLVhT\Ɍp O 壓vS~ yd2vPa;v͵w9TTO1R5l}LΓqnEFfJL$ ve廈x/q.J㸊G1Xs#"H oei^VeD#8 ҍKxGۏp%lEdۙ=Ihdŧ{-W2FC~0*": lLE B5U==؉au?0e2Xa.C{v `p .@oA(/)T+8|JɴHu}0 ,P9mʵlɷ 8m䓑)v~+;K_X!G$E´Cէr Lʛ* ߨ;XGkFq2޼#TF^zehqiB@jJ5@n"H|@wxcWW'헊; D [Ģ0.V ^i4T` SY\*?*ZYǡ5qyJFAYZTJN.1Tdu0E(|㜱%YkIojf!-u~b%KDakM8~=GC*zʄc h 'KvZ#]J$nʬJn<ӰZB[Ԕ+(.+DaD`|?j=fW Pd^ZX\c2XxY!A<6i[@|Nn/q T5aYQBP.zN:۬S%0bSۙ͢-/G}`# N7Yգ}QԒveU7 `fw8+\AØ>ՙec)&/KzFlJhI79dľG4Q-5]H,l)ȞƱۋtYM֖m=X Xaa,pwϸ;x1RhN])5Q\X+9zʿH fnwnn6NZ,]kkZ6brm`!UR0&52J)ȰhdH \^8L iʔ=|GFbTe@a"9$!w wa#%4:5.}'h}WzhmPUSDj`}c"g6CRjPQo M:Z: x&9!g`- (:'1xbIFW ꒣Ҥ/ $Ǐu%,A.Ӣs7p{9v'З\@cXH T0xX pe2`Sc19f~ZLq>O!'Oq?ӈg K10fa- @ eAqoڙ6˘okK z4@ DǺ".sf}_xm= b~YOJD',A-m0ܘl ĉ⁌!07V &\˱̶g_HC3øACpf -%9a7'30AyAA;k˓6&X⁌!~^$a.]& Cc>\{\,\c\am-ya2E"I2L \ e ˠ3˷v wq/iDjn"AȄZcb)\s>?1!Y| 1 7"{b`4<߸ߙv "¬8 c!Zg90=ÜC°0_D$b_~ehZ2o!0)ێe `AɛL6 fK/̱׺{ikLg@dE`p!M& b/s&t{ͣ0Ysh;!a0ߘ- - %baP%6N2@هq92`={o26/v c19̷Ywc0;iXIaViec7s=ۄ.KֆBD! #/ " W/a M]DQb(.I3<^xA&֙"q/<q0Cf  ApDL˫M q )ctŧK7ufQs 6'Q5b:wm5ք0`0 X F.ywp#v;o6kiDJ9 =' jeaifֹ,AԎcløN=O#S Gbc2@74!][zw E(,9 [7H 2~>>x\!q^/%^C[ss16`0 M %O+ &ț̺F=cIŢ)91¨,LE )" @jB 0Mre;R Mf.SvXFXr1*/!aeBjERYj[jUbR`_( RL\0r`_1&xLx4Pnf_q<{+ YQi9SS6 3oBaWax˃ & KK9Ogp lK.g]D0ՏLvs掮JN]IۘZPB2O# 9n bh"8K70--&iS662_V> vCMGr&וk̨jqi&X|@7n3jZ1p T`/񙺈k #sX1VJ;^VXbBֹ?+3S"$J ı'JukzB#߈ä>PBGʁ*/aq>;h.8>ደ.`ULu?Z,6/D_OJG DJ?J tE"wwZ;{05&WP@Sum, U9 J݃q|M ca1@t qyAQ}a z{|T\fEQ)%-S5*yZDD@A(b%0(AOs;v1JQY+f+Hw5ª,fRihDXE=x{ޞ;OHQ/{^ydL,LOoɩ+"DEnB6y|GWχd]1HG<)V!oBŵ6&?L9Q Ji^PRV8<䬳Y|myB1ȇ隱TK'ZTȴmn٩?-K=,Lׄ-K(+jȮM4&$ŎX8"6i"ԓ~+iͩS"YeOԏj" )$&&21՗NKGGR2qN)Jz FFE^/eC8(MH ԐfT摧QR}u HHԒw ~T UL,ŹHO %%,3^-VHȡ]()s+K%蜟"jIIq=Y<{PX) Xq(4kKxbXL " 89 [ЋLR(tI544%Y|le^ŊB^$PLHlV,T*FlYbbI&HSQBeLL\a ?X)V"Ћl@9D(쾊ذ+(: fÍ=闾JCE -@i,X\ f+y(= XCB klYYcXd(iL袅ۨ2)1G؋/|d'ұy8E"X}s$K lB샍薛E=-<_DcC=|shR$"ђ+(So- *bHM6K*FhBdhF^|ˬ{%DU.F2jIR䋕NjHq-:ԋOJ5445DŽ.8*Ěbw- צGV?K8j90JLM ",R#3Ӣ:м%k^E!eQv_L&GPSM5]!xMpV(hh4$a݈Q]/*bbj8$!DX^X~QX$+g"{*+k$;%4MlXcmo ^V$K)dCRe+9'b/C#Ð䨲,,N؄9B{YLHQG~Q5>&Fj %<=a bÎ,R/ch鐘1 3h,M G;Sab8HiԶ=2H-,$OQذ/7C'I{hxt/FJVf[<&\,%5{[cyHiDɈ$"Q?M{rD#Tqf^-b"3Z\j+oz5/ݐ%efXBN5_el6^+#Qė#CӢB²&Ņ#o^+!mr8$X9͒|&Kղ"xI}߹(ذNN$Zk(e3g![az[a1z؊1z]oyYӏTk+{MԎzIbڿ:b1XAr -5("zn#(hҏ6H,P4AP!i}>Wp(Qb$&Yc=rBGI4ikѥMȞC[Dz BC$9rhͩ8JUV=qoRk(EHRBp%Ee11"XJdRh]*l$ bDD4 B%-5tY[,QGIt%a bcJE|CP^:WRR~I>G:[iONdRo46ԂtЛOzvגTԩ2Q܅@g:6'Ӵ}.KZ ;WCJ5(9WlqziIկGjk}N} B]6KM覩ІEa"(((x4$Tpv=IMgSˆׁʗ_rsgKzzzwlӕIKJM䖜#ÿElDH V/2ebe"Zw=6+^JMMM.=!Ƈ!HOm% bFB|Bbt6gU2"r~ȩ|5viQ2)B)h<&&X yCBi#uTP Ϩ~[,LuBaq(AUtq_ DWQ[48$"-mG_]4!ρ̾q/%2袈XMП T)Dr,bg5B, ~T6UE^f'B:Yy_$K$k}""- K-ض^/ .I>6XS9/}`"H|ؒ(q)}DYHl >ԓ,M1ĬYx}DBYHhT,d(:ɉ4V_q%cem'JLZLbe!<c)h !7E .v" %\VignetteIndexEntry{kitten} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) ``` ## `knitr::include_graphics()` ``` {r} knitr::include_graphics("../man/figures/kitten.jpg") ``` ``` {r} knitr::include_graphics("another-kitten.jpg") ``` ## rmarkdown ![](../man/figures/kitten.jpg) ![](another-kitten.jpg) ## External package ```{r magick} magick::image_read("another-kitten.jpg") ``` ## Plot ```{r plot} plot(1:3) ```pkgdown/tests/testthat/assets/articles-images/docs/0000755000176200001440000000000014614000540022222 5ustar liggesuserspkgdown/tests/testthat/assets/articles-images/docs/reference/0000755000176200001440000000000014614000536024165 5ustar liggesuserspkgdown/tests/testthat/assets/articles-images/docs/reference/figures/0000755000176200001440000000000014614000536025631 5ustar liggesuserspkgdown/tests/testthat/assets/articles-images/docs/reference/figures/kitten.jpg0000644000176200001440000014335714614000536027646 0ustar liggesusersJFIFHHICC_PROFILE lcmsmntrRGB XYZ )9acspAPPL-lcms desc^cprt\ wtpthbkpt|rXYZgXYZbXYZrTRC@gTRC@bTRC@descc2textIXXYZ -XYZ 3XYZ o8XYZ bXYZ $curvck ?Q4!)2;FQw]kpz|i}0    ##*%%*525EE\    ##*%%*525EE\" ~TQPA 1 "oD@DA@A"" F EEcDD7 " " j PQȂEh" "Tb((QA D*""UU@* "FA@ 4TCv"9@F "*(""#QDD@ADQv Wyr]KD@QF(55j UCv {>{/V"+"A L]^~CXh4D݀(|B_FRJLO>m%|Ķ7=]?]UW]:cXe4AvK;6վ8Līy.2<#PG OWxWu =.7d%ov-yDwn~SyίN೭^lkQ Fpbf7C@Z;B4~[$> `_8noNײt9Y}o0FW=涨3'^hy[\Rv1m(0>{Aύy5 Wb *y3c58(WMWk؇o6=:/}Y hD7( =S)Ǥ(gЪ댧;XGIrdZO}1nA)$[=Wmg]Ӕk_`zkW3Q35ԾcZPPM ( /LM;͙uK2Ãfl\IQ1+.۾]=sɍb T7H{H7TA dql˰x"zvGwms[RݡKʮ*z~c<UE@V( sUعPzGPe'4c^hp= |[p~lkPTQ@TCt_Gc,r5V|FͬkY֎=Sy"M{.͞H(( nDQ`7\o=G7^f}ݤrƮd\}_V7" Uy+EcȖw)yqw,J؛$2#afMlz7ͭDP ((YO4 g1qZpϤ{u-ܻA-+KgA4T{hn];y#S>Q`tFSҺXg͎Dt8f oZ E@ (cs q:K)wYQ6MH-o8 y'>syZҽOK0FsWɍDh@ )踼߈.v|Ӧ~ut$㳾Tj/П}X}#&e$A;㕽~~h (H?(pWuUI&.: Ef';ovvwjO=cgZ5 2 +įHqU8Ӛu\#VHyk,OC{]Y3Vy ("F9f+i=Ns>|vG-iD_h$[\_NzI" 宊rgʹFu~&ISowQ?0rOouH;n3:<ƈTAjnPC=24͉Gz\;L-Μ۩km/ɾ/{o//&D@ "㬧+[H}\`y+vdj5nizM?1As}v{u4ؾO{=sMZAvA%'^b52EDDD{}c|8WQmHˠP??l?I ־BmEͨA"WkO&R _f,'5{n.r:n7[oZwџX:AшDApU k+A7yq*Ҹ0pj{5nɆmfƣ2;dvlcEA& A '0. (WqYhr<4c7ܻ:!m{?3~u^<@"""""5kDžlVG_ +>UxQ)W9%RS,,ws'|zL{s?1 $#Pby5w},! ^vSs(%QYNʉk7[ݛ[A~ٹ4IP5`B9C4[Cwei +)vE4X>3vsBa?F:Q/ E 1#5tIW:JvԯyZCsf%VbbNV[u~^MjpDDֱ Q5P(6CD?.h9.:IbĬ^|΢PV#Ʌfn?/v́~~^lA"cZT\(OBuڭ,ogDq֛:[E_g7Ec,Oq9b $cX5"/v1xȴ6#62Ghdz\:@lK Hw}V/<؈֌hA0"FF N۵2? IJ=? 'AN,=qY9mcԞFQ1D`6|0kp Uzt2J5-d;,\b]uzx3ͪo#Z (yR*6ˏԹ#v;㇗eY$i|bnKvm`0DDֱF#CM."}*LT:mm wo\E+]'鯡c:QF5b5w5Z7EˈpHm9*> dv7O?5Q{[{w@kX#zXK^Y3҆Cˉsv? 6@q"ͳbj"r7ɺ7<#KkQkZDS[ k2 jPuYœWYpVeyK_5{u%gj^`cAs:$]-`G`pSŭ( Ej5]znaK*s[`2g F#֠G9k w!>RlS gz|oU`QjU!F`ئZ[/6ڀ"5cZ:xnN1MePT8ő2V:Y?\Hc;_On /_wWHuսo k֠K AiG"K,[UqlZǩrw%*,]Զ^ש;w5-FcX֠Q^S\b{\tTP>2_:R?OYQJg%޾~Lb%" k#TWg$9,Y6U2qؿct;/Oiyd2)']Yx]-Gֳ-&"#cLm$nV%SMeYpt/֮M d`ɺvư{]4.@Dj#QmD`Cc23>@^쯛{}~M6ʒ{}l*!<};e"@@@TDy[\\OR 9mko8E&Vưuzz,>wM( yxch2AjhsZt _5ac{W·6fU =}WVM QPxj#I+J;Ec2*$n -hڽs]7736D`[=gn?D8+B[9%4^#u&Zzʥ<2k%l#AG=ZZΞ3?w іtq<]9WCV),hcDK*^+bǖﶙ9pDGq+X?WXoʝ/Tlk45 yMrc%TEL}7oڳYNa (sSʦv6Dzbz-~MUW"jZ9Nh/GmNv^Gm" =#GOrOXReqZ:m&un [Q)W{7 WiI'=ܝObs}}^F D+7q\?Zls/sOᇮ>k'/*믤g~x/6}VȻ\]ek+_Id2Kx>uӻ=s9vhQŒ>\i-:K7{iXRMT`sܠ+h5QA珍|yހ~|r]n -pW\9UAA"  *5g0HGGե5DWWEDA@Db"#婮-:ļeY* h  zUxADDA@Aj5v'  \ڀ@A #ִj"AUQ9U6"" AcZ""(5 Usթl mM1a& Mpq=6>0B]2V[|)$g ޾a[:Z} 3Xpz̵v=0g+YoPgW|vXԓMg+._#Wsmf%wO!48g+8;(ǃMmsՄ(K~O#Fn?Ͳ>o`4Vy%ޫ]9\ G껐Rl l2z,ݯU`!BX??Kp櫯 H `B'tSf~A۵NL1+.^s'E'&a#F}Wm<ҷjDsl,erJ%qRcc U5 hR+~t% L% 3>lج5cf@rlNZhӪB8Mʢ940J.qsh7 IEh Tޞaxq!s*5[Zim3䦚bS*UUP5ew*!e{)Wz@L< Elg(֑V@/7NͮKVRG ]˞jHfUn9\|Ɣ]9x.Wȭ.}s͸Ev֔%˧-`G䞫k_v5dzeǒztt:;il 9m͂c!EΣnD`!D)0"*V `1$ZĬb@"&"bbah$+3 @&, DWv"@_-k6_K~O[ \=gqx`{zM*rܶ :ϛ&ks{=߆~.]KO|Ã[>x{>_C=[~go?7G]<_og>w[?K+{9{oc2Vf#$,$)WG]4*-#&fBV1 q($D2!"P@#1 2$03A`BzX+0vcOm[qMhO)\7X-ђm}7ZCodݦFi]h`hKb&&32&2g;|s9#pngb2}r^-,쬸?^͠*\ꮟ핚Wz,_WwXg^f-zWE F$;eyF1,{1%.؍YuV-ϳabC EG"qLO cCRJ[J.,dLaZZ\m6Uk0H5?ySL II+zOʓ$G}C*J?jl鍫6ftc\PnfÇeP:.p#Vɒ. t*w4~qDZk(Њ~jV@Z@q֩-š|\XwύVGgOreuxw7墎ov ŭZN@'S9._M ;[9oi?"wmez<]"Zh(UU5aW©)*4Ɨ-€~#w>UE8 B&[rq%#eO $82qe*{o=M&L]Bß[\p,#AuN.v`%sjk ;/<(sL'ga[~ݓ>bJ >X7E(:vp' ƸRø#y.\ߡ0^Mcwe]4}RJ9V,W8J}T\0mP%u%Ai# 5G~&ԳຣZH'X A|ZHm /Khʻ)SG5ÓRvr}|jUo5dbϰsvٚ-gH@OeI5酟=wp/e;+4Wv7Wmy#;M gnQL'2捞1601|$Y2.oUXֲ&H#YB=;>&i M^ u'բ\gUJdO-z|ڹLD,H` T72y ]fKA6V龱o^ḫ퍒X*܏Z7CLdvwl3FҐA}\~}C?,!l^h4kׄrYAo_W+?3QMbOR>h0 ORp6ЕoEa]B&ڝ=DFU}- |ZN䣉 f*<اډ^Ll{K5ܮSR*~}"y#!⬮-\:3Z lR3uAiRl8T I]٨€+Sg0k~I**gkkw:1)/_ci"C,L"'mp>' Kl45q%Գ$Rho*Eu(+ |鶷:4T}C$f_n5䶮Ix"˘۳Xgfc-0!I~u򱶄HT,3&/۳4@Eq?>3dF]aQG>-SQ<+2_rECXG9J mqM NNW 6i"CVKE#2 c@\RxrZc=8}}__\V["9Α<)q&̖`DN0C,-YO$bR+f&=Jcr,ҕ8ȎЖm i}XCݥW!>#&J&q!idLˀ!\CYCȄgCS'}g"?q77@F/ЭLJ ",{g39 WUDOUc"N\6!0;Q\J_2ڕ+%`m5vzӍvLX 3<@ "J-3KE6VDerCw\17 PBQı<ܪc ~FqVθu>0 sNd[Y*l&M2UO;.32Y)%_W~)y%43s;fybh&r "$GO!hAZ߬.91Avai ٥gg fхjܻ q65|DAgf1]f-,!-,Nh^hvD:g<#^iVV! 9Zf> m)yd-ۈm8;)3q]E ݺmmk;]"n صCa t)b$<Ȓe+)ު%BK"kGXKFc?Έ_rt H l8 @agވ> ضl{T3`.}+]JYCIu#=Ö1败HK 0†fR0Be`K6JDsbӚ!6Q}#'7"}.5bu)5',0UI #xς:nލ]*5nbW; jnZb[‹Q܇ۅf1s<%ߟ\1bg2 hzgOE65Xz8T%#Wly"F!mOr3`1$vC}./צt˱XEjJuϢV7< ^'*eu\ŝ-ˆ,=s&*J6brC Y5 ")fc:=56,%<c cQ5l\,(J;eC"$v91"9ALNk0@dO 1\l+ciT(mI0v|pЭuUQ?J NçjSR`|$S"oanʢ"E ܥjB\N,N{$eM.$ض#YIR3,VSW^-hJe.e+΂߰aA܀?Ϝ`aU尙0~p}FIު^%*g@& s]¥@ذ5EZR7nï~̤֤֔>)E-d,[զPPO#iMEqN'-$66`bވ2$~_rBw99sy`H}e}hO"8,* P`תEFC[NGؙ7ĽevѻAjZz6ͺϛl\]uf$CYwoQYl,dѢ d2j hX;%LY,gެAfC)(j9s9sH aFNB¯%Xx8 VN ĕ >SD6W¶rޫ=A~c{kؖuA)de8-&6Q),lK+6PtݘA"WY;<Ƞ]׎K$YpZ{uOؘs9s9s.d8=m VdJ3R]eĭjnQ\g.4_)˔e.׹zR9`(M6M%+!WdXJ-A2:LJ$!A-DN_oSIg9s9sr8!T^/%Yؿ(zDCUWf#Rcń65a5\eSjEV]#>>BduU!gRFhzR1 0Cbd=c+Yc;PB8&>֥LTul> RZQQRLXapbU,x5[م$秊\J{FʷbeUf"&A*/]lk `0ؒ[2ԭP̤JTve,9s9s?ǜdd16![2X&?DOWn"}/6+Ȱ`,gܻybnVפb=kIr:SZ,E;3}h6卤a6 ]IFWWxZ )oH{x)ǜ2~IJ3 Ab%Vfu}bl7M&lkk6ا,DL ,^l5Wmt@ՊPCn"{Sal@ٙ'V^'NE?1͟4{>XfUSn*5f[ڙ Zr.U^\}r[ o^$  k^g#`J!C%!2omm, .?o&NK'-Aq6 "O2 ei#[skzԶ`O`$e QAqLm!׮)7f2uc,EX*nJn5`C+YBُ}ŝ~Sq0+TTe_oq6}y? g] $B<r#I@F)k.(hmWk1upKc$ aN]eA˝C6&uv w)ַjV"z&z Ky7f =ʐ1MΔAH&fbf y*ȏYrya̡ްv"+ nӚAOhqb|laţ)E MUdsr=d^|ًF@N[@Ƌ՚T&fNȚV":EIjڝbcM<ࢹIݷ01`0JnF!Rϱ2S^<|1wvy%RUZ#5? |~Pv,e XXCKc ܝ(7))a]Vq:Gȃw >lZ#\L?`,"g, 6jmVe5?fB :nƷvL il\s%X?RaV+ֻ8oh/&SյXu1,& L[FjaMd*pG5r-P)Uf$F%ɸJ-gs3+R9aLN2&mkeUqhI-B0{R,;Ckz6E R9u A{n@uۘUlOּ̫{"]YWH=UaA֮BukVkUaj`LS-Ef[hW`)ݷAINec9s(( arg]&\$,ӘbhEq BmeΗvkQZY׮":) eI;Vrj܆aP_g+VçK~6.ygq).ê-Y{Sm㓱^\nv(Z ǐwQ\s8̮2kzSq0Yb-b'*k_+5$Qg_ i XI=49's#K0Ĵ{ |q-%9&YG1{n9_T6O0xŴHC,*]bl*ܰy o"]TZ,,R/JN6WY&.gqz0SE:}8Ȍ8q&m7LZ`^>blyk9M";dHesX۞]0H- ~H޳363]snFeNױ Hhٸ%FMb 6&p䰒z6u\+R+` 2 s[p 3$  +eYi?+kˣKo%XMGnqr9LlA$8MCOcam ,`53fdS31,R}QK]\ su3 #]1WR'B*X2>AȰµͮrݙT=Q26<J!&P&Xʈ:S&7`>-ԛBq{& K3}:s>ʺab>j͆XJ'h9 a4Z0hC$qf3SeSݖ=,eϷ0 rɜE )ZK9|ƫPӁD#"FBc 2 sBXZCkOZL =U[?UXң\AV HMǗ{'uemyl#is\肈|dd&2*dxi G8ŞÌm~=zLWMCι83sM"ϛ6shfұ^U9``tz"bF{mc^qSiO+Dؽn9yOo|Z'fiOQig$bq?6-[υ\7vF7-wxV{5onC@Jڼ -e&+8hL}f+^1Xc!Q#:\Ƣmx;8PH2G$c=c,3Hޙ1XfN>kU+*^][)*1,* "8)ιx38qg\mH,yW-eK #jеOu]h*ڎW¬`xyk(xΛyJ<:mrR3?9o9s?ל99s9s9}sF!1A"Qa2qBP#R3br C$S`@cs?|[U荵wHp?R?of؜b0}UŦx]ęBׇǪc;KKswuuiD{Y6=Т۞5ePuWa2xm#.#CdkwV.$` :T6?n<u='qy>Iś+&jgx> pj3;vY* 'P;8 pas5"'Tkw7 A?GBLQcIɖm FC]tQ"z'puQxD"P`x/-[FiRS_+Ԩ&FF]f_k >v2~9D&*9,7ˊ|Ӎ;aq7ߌ&!UkUFKD v]y[ "mG4" )!E'eU]3꣼8˒"%$Zچ-v%Ibѧ|y;](Mq1qw皍΃M.q^3ztWLwֻm vgt |e&`|cCl&u} 0?izOx^ѡĵOy`3Nc}=OQ!8C;|\Cv#';P%QYZ.QNER߈X":?ě3$.Q|6itF㱟TTAٽ#0/5T,l@''tlV\)kz^ .BmidZrg6Q"Ph?RyBsT!ip"ӧȦ8'\&M%ߢ/P`ȻGȟo dsuDM}ߦB^zkC@kN5Ic@v9ivLu5^ r5Sp "hlW c>i+<;V7K;Eu ˿޳T_b2 e8G-qrt>E= 6=J{&Y#qA÷|4U@ʹwO7DNFqRiig `-r@^˲M 'rwϴaVRkir5Zdq<ԾV}ώă벸`&j4QI{!}!^tQݼy883(=a\AB&:jkL^To4^d7[](q2pFZ:TCsO¿52Y?xwX6NV0Od-glֈ/|HV~hU˧~'kc$Qhcߌi丨GݯNa&]A io ƢH jm>s .QNy\5VtE/i>:]2= !L|S]9mQv]3-Qiո9k4~ctj6b~Tz4y],8`5CSXq\|JYƎw'8F泩B'`dn:ƻNpts? j ԩw%>]K)?a##מ(UwO j׸|g>݀[v"CAqݜ6T鳊2KG"> s sXQhyE-Ĉ=9,(U> 9Ev txsFʘps٢IU#K+'Z"Ne ȣ#I!MR=9!p ' oPWАAsGBa"7Ħj t͊5jd$jyQ嶱D9N!:.]:v5MdOWju?a< N79 AF8'5[7~`]} '|7ڻPs{{O:z[? x.ha9쁕Μge={'KuA: Zz,"7\G*CvQ9փSZEƓiܶt cl8 cDgFz)8S\`]ZA꩜Ds2ַC & 3ISZ+6sx,ԬnUϭ.P-qtC-n̡%2g䎠G䁤 Ĕ׺M]τ|Tx m9yqLòmZ=PLAeLGDD@C Bfciy kG4G,=8=Ӂi73X=ISoL'*4ȩ&$ןScpMJD3zʤqkqa1N8]d3_h < o,b|P4#haѹdUi1|o+N Iԭ}W`+Vh~F8j|fҝ-to9,ynG1 E 6&ɝ6 G9Zk= X"3A13#6D=:E;G$ >(Ϩ[&m~?4k5qZ [FLy [Nd ''}cnw^tYdƫ!81 kyy+y[UINS`d պ`#泩_ܬUK%_g]Rk7^jtMiH ,4G[(T9tݕ a?Nk}!i aIK@eZdܕXBF=Θk[T:Q.#=r(tSu/'S}U :TϪya9!k3Ѫ\:Jwv֎n໨$&?u'GNt{KpVc@X>ȩM{;six:bI;ewר)1ȫ7vgb  ϒ9䋆:ss3þ2WD4 -sm-&:ye<#w n D.h'  z-wZ= y`-w44>)-MtX?&?>Xa%Rj1!9}5Uʎ`J>HnJ88ځs$GD{;vpK0U2 * G]Nuk?G N*&ZwwO%: +hn vaޑLm)"\rui@*C m@8Ժ0ot} exAW!̀x~H49)pOf;#uR<6"Dyu1ZceX5DVtGvce=#PUOc\wb0vXխcv`%PDÈ83 a+Z׀4}YɼX \pdd1=Cy8:c sZ$G3h}٤D:w~H"4h0jQ29'Qp;~Mq@  ؆`C}S=Qhs !H_ƧnI#Q1?NyE޻Xz0hѫ"h4Am`9pQc녒'&B?4x <¶ 't=ϔ9ܵuX@1!;ȉ%m8p1lOAU-E*F'bP>%U}I>klzm%8.DaqϚ9]&v7 'V4iac(mT!&_D1WY5_?WsƤ7椏\Aѱ?s=j"^xa>Z-eNܡ4 "z\'lP@ Z9oI7|̦FO0ާDy,2lݝM9m#KuEx' ,uh݂NuGHcHNy L0 8* ?Aˋ'S-#"ݑFi i[a!07Q֎dʹ NOQ(BwGǡ'ᶋxNe p1vȵp3yO[|HMww][o̦LW'y=dC}pV8ҿYc}hG]ᜋ~82 o7D>j#M ʕf<Be`: 4kCGieYY 2a kn!ٙJN?! -ZgY*{;P殘!bs-m'xPApR˄i|5V磀$S?E뇒Ɵ`߄803 Z2iWԦ`k Ha c sm )ҳ? I|^ꁸ8V各GL'6nVʍĂnIR فn$._5J?ADwS.*x'q'ZL~4UuKzv8"~iELb=C{1s=LDnOA:) #mG+Rk{%(ΫKA^!:8D[R"@# q77஦Vsj"AR6?ܰ~hّ Clqۚ}U₃\OQ!8>*V~hM;h>h+:4!K9D>KU dy~j GI3z D55KY&>Dhzv^D8j?eh;A%SHučmdn1n;|ƅ`:+Z!p_D{0pG~:;8OѐAʁ@'DF$JdcGN%)k" i_T)AK$y}J7E3\Ep3\ ~Ϸ|O8~s<܀yn3r j$e[(hܹ(?"CCFGn^s ,t"!4nfQ]Fx!|6La )w GwGkioi4馨Ō'uTܡb]$k0z( 9(zO-T(΋EM(TF9!E+e]1SgkUi|– 8~&a 5};9m;x'џ'uLX tOm7 k]CҜжGYpTvW9\5IM]>#U4_T}@T7:hW.aZ\cӒt}6'g- }6!v"wr+45htꃇ  ?f+(jRXZAEa -ܮ.=[F6ӪD,(~v" %Jx7V9v䬪lq͎}z!\ `ÓBn;tMez._BZq'nN gчt<ky:sW޴;Pp ^idB-PJ.:,dX%C3CĠ7o/] k?@k?$pxNɭh+ O3N.v~0$k6GMu8.#kT0 ?|dowIJ4lS{@0~@t;l3͇%کwZ-iڹէ֒>~ o4{$KڱAhu2ɏO$\<ܝ:!f`X#E ~J0b)\L*HX\Q)ZTx޾OE/U n:1>qAgxFmX$éG!%3>o>>>tOqʩ*xH0 AeL<*7sOnTjWu oOXjS .iF|3VSj4Kc`/h Kjm#1?T`߆~!~ŏty#/XeT|.?_UŢh걪S)iGۄs#g3: n50 WFct|_KD*i}-ӪP8]j_"e1i_A\tvDc#"E2sAHVf;?ҝWA)(͂8\A[ x|x{ k\x5-|ԏn$ X_; ۊ,/58Z@B C>2c|EJ;YWxm>6 ;PcFָq*.LnSs0rAUli]<˒sa!Fr>P$ƆSY]SkoSwIBs<KP,өO\5GQ?sZnGMS2ٝv?zH>[Nz-NUniY,%V @ۮ;K~}'n}=\m vq!@s+08x8h.* %xpZ`6%m"H5 hVΉn܊twy]QLMh8T]!۹! \u7TpkLftQ i&5xE? UPpޛA] :${ MAa.TeJ:DWemK\zDkb6HFE =y&i&p:d&=NFD޷;_B@ʼCP4Ih`)C 3W @)*e5=Pqo]nҦIG$\) Бh0N.O!rCza$i~Jw2L l:ZUsMhs]H,>u{m n^H5Mm[0Okݼ;6U{=jp{#:\Ҩ4A眅Tՠ*d{F8'57;xc1U@x]CHFoE+Vdp d5q - 5R{;Z:#eW4b& %I!R_j]xGJ?.$6@8 27֖5) 7&(?8XovL;Np"^b5OK" dQN ' |g wZ-UݚNeG#-Uic+^sxEԮ:Cm}G$Ca#MtsM Ntkٱ݈CI^*{#UT"r5k5(I\"J+U3ehЏ݁("n"WvLpK4k䩽xӞ[hپ)$j-'.jGsZ&n'L&xu͍Ahտw8p#L?P2A>X폒@pČnFR=kioG6tSHw\鹜+/Ć8dKTn\qi80s?|ƄgZ}ߢaCc`t+-ROEZZDP Bc ~(o<CW7(iXTpFo+9!^aWdGp@8d[m1Nse`uN]w:(Teg#"9/OAeJsBqu"Fmzwj1̬i [ts[A8j-wgg@]ibfy¸1VZ'Y2 Box!a&T-Z#O@fƜs6 T5 GFg`UJͱ<9UR^91ێ"0XM^A (hmZd@$j1#`8Bvr-hmv? 86p@HKE81w4a{HG1O0׶iy'6CZZXsJecQpQ\9  T8 ~%mlj:O5 &V !(Oz}Eʻ/Nj#4ELH(t'v`9]r 5r_o,.!7=`1D_~4uZ]t)\ *{/x0zS择8OV|tEz\Gn0SCSK/alƕS9M{U杜T۴}P p!4@!e4 e>R?4'AȎJH'}nv a6iQ.iDXU)fע 8_ɮ9d1ƪQXzmVw ʘ@2`,8,7V}P<%C7 `΋!)Ftjo9#Z߾ǪgG"N!;*h_1㎕[$M4~-Uk1kxsSDW'(?n8w-'y9;V\N=JnjtvӉVd!y)pioeV|Qy"ڲ҅% \71C % {Dj<逿֏oݎDTsYP`Gy P?'Tz.5q)!շklA4羈i3th}3]@iʸϯ5Z-8{Lo~Xh!Kͼ)~m?cZxi]a$s[l[{Nz.p捭\+OEdabUoZq貚3`3j?A8pSTO1*@&S{*F:r tkIXjƟ%W1[*-3jbƇBgpٸ%5 85cFr .Z} 喫Ki@8IQYV9 @:m a"ZzZ)!rN2G{ F-vҏ)M$2PcN]z.hcU$9J}Jcx ! 2D(K95LwYfFQū>%גsA әD1({-PV%h[hS#{5Ѕܼ\#p#et!2 `9ʨ)ԣR5Bp: 訢VO4Kϒ NN-kBˣgG>i U)\9P&©ih!?ѫφ$7Tg ծxH^!\ x'6w䆡 H j !`&42ri;(f6L=c s_S=Q($Ϛ`nzXщ$. mULP6?cQ- hO*x<($;G)Y)Zkg>EYQBLèRܷpӺ{ c)2!~9F;HɲUnkP?(?E- ݦ" aW[2¨~EsOTliObe*= $F5zU GDZtENkvEm8(HMnB/G+%`i)ĦϹ2ZQ8Zu” @ 082P:_o ӣCih5U^!QRSɻ.qBFŽKN$PkQs<;E8?hMq~F+䨔@ a9ϢpĎyp4h70 iS;8D pQ0zaX?gA#-5Hגo6Eahe0!> "D#D Z,Pvд] cdHU4J[:iП?![Uy9 NdǵHxSU>!Z KvPjC !zYDGN&4'?aM#Dz[ Y#Dž4Zj!>SFL  o2'( :1K +*[ P'%jA-v?c5GiZt(ۑ[5Q, C*ڇ1ݟcyg;Ear讥\4Rʒ9G2?0 kE/42g(P>)EJӋOV{*hui@GXY0ZcwB'uH{Td,KMnҿipS a7C⅒)kjqnr&JhMPq5$ ,k‰qD"CчJOTB6NrV>^Z-r$$IdZ[~K㓔9YZG%۱‡cslP nٜ8)nTgp ESl d|Hdt*"\=V\'CB h- XX &6QzqdثcEw=v \NJۂ$U;rM{ vVN@Do]ꅦ9eg5EM2 EDBl Q62ܠ+ Os钪S3.]p˓( vwD'Tq+<^V\J:j7š$9@2ؕáVQmHX٢삹vS.SMVįJ7eV\9!GiL++At[ n4"d|K>jXn>yz?fEhZ*A`즴87ݤD7)lmW[u3.<>W*!1AQaq 0@P?ǯ_ge,گ~L?RJ+~|ԩRW|W|T_D_ 5+COϊ*TRJ+TR|J*T_Lrj`ƅێ!\"qI*T*'¥J*T_Rnc|9(Dr1t^FÓ<˗寸 rPw(CQs\Ce~*WJ*TR|:~XdFٔWOʕN0~bMuU @T'qIsD1cM3%a'H0{-"+&g8`h0@Z-[-R_jЂC܁YgyE䢶) 846 @Jh11{%GUEXqvic*s:@hǓk$kULE/գ^awȽ]%)'d @JX`T / 0R4׉ZB/(eUe\5TXj2.ͪ1[ s02!V[{È6 +ia/Aĵub \+MB} އz`>}(5/y%g;#4?7 ӊkP \ $V{Ax/n׈j}#̴,) \bRHkG"k U^nRZ4>qFK)³B4؀Y@Pe_L⠝c!p߰Īb#AWzfUkϾ|AȀS4CGR^a^$2R咺4q|?0>kѮlQ6_JB֗쐲;*Cۆ MJ䰩cܤ,`0!#Z5ٕ$=%{U!X!Y!mDO5C/#$l kn q\-t3O-S^ЃT& <Gs'%&Nzfs Z8?i"XjyieuB̍6T[~ G]d2$lK~<@CuxɄ ՔxfnU 9kX[#qLZnf?d>7I@IAV36hY#{0yU(!:bSc;`:K{Sx@bqR mN4 WF.8Y*jy"5V0Mlr{1_IY >ڀ'gx LSq2ZУBV~,-=F@^ lhIG,!x?cEebpey] q`tkŖ@U^YF`Q3y,z)U+&=dAp#d1P{Q2l ib-XIt_`f*^WY)Gcϰ^A8.S7Zf1f=_WмӜ 4-c -W~̄RVڱz#@x1i5@wTJf-U腏0Ѷi,|t5-V/Y Z)~+=k54, * pbP8}O- ۟au$2*ĪH5q` 4)Tc (}aܢ %֫ fഅnGmnY",XTVE/\Jk*3bK{p¯&Q)n X i.<P0̐EW/VKR7bOd+I[9*(ZG{w}`d)#5e(%4vΉtBsruA[ wAhح*0qGeFglJp(%We׶h0q梣k' b!;<ADRѮ7XXt!B#]Q Xx*_4DFs.u+bQ%ucgJ穙Z,{m+VT(bc4 F0$Oy>01΀Sp":g,H56yȞ 2CO'~rϒXu ;(Jɭ'/iskODh:aj8wZ.OK x}V6b~e(q譮^콡 Јjwg/x#29l47^S4.:;NpJ4#d|ffDf.*5 6l^`  1~n_|˱E:Q+l7͊ԖxS!FIvkI1k) jneZ::ΏZ5 z25>|[r=KUWEi (d?K /ưy>e!ڥאJ-jP%# 7(r]*eP4Ah9`\! !pFJR}!+Zۦ9mGo+V8F & _ihYdzL$Ͽ;2=ăs4HY +X?i򨚅g<]f^J)e  >ma$tٚIH P]n KvAOh: @J=p*Dܲ9"LBB3XTiTL.c0H3fmZ6EXuܰq0[֍t}3`1j.G( eUTcN\1ꀸ:OF^X)t8 &U`4@_ba(*~ܿ*87ѕ]+Մ@WT~\fp1^!ո<S (F9{d#(0)lZμybBڌ[bղDfSPPUR]PBLjSDhsz]䦏,ѺaĪS釰=S:YTd%c v\,uw0cd|oPڃ!LX@<GAsPb(VbQOi6*8k,dշ!fLHN7/'Hm,P 䥟pd#{ ?5Uj!0`J[Ml yfb) L[*(UQbPh)|5EywSxR 2,AʣHt 8ZwRtT$!XRiߨl `x@[cX)V;J\+3ƪ t 8,_,c~l P)JnDһkP7+C:ctV$TcٿQy  Zq,$6)1n|@~Zqbl虅J^Ս)#8.k"I`⅄ ]ljjrU0)Bo(mw3L7edD/"eCw%ۆ#J`ňWDJX\{gf‚")4ėA7×lhU;`/F?Y@0Pū5p=CCwM~hxR[hot)1V* pVhy2vU}=Rw|&Lo [ #BoIJ٠ݎظ_fe :}hFjoEwFG p skt\Y|W0ֺZ<]FmU4{HzU[K@v&}A6D`|`cA^ۯ(o;rׅD/KIh4(О"78GC1o jhSQ&OΙ &tc9, ܨcbcLQv& !u7L =n`b뚁9ol])a g,MPeVy pX]!"!Q_d:Wf|q+xJmRb MmKbg PeEt%Y@[WPV PaG6E;Xc1+HQU[R"A"eTx/ `@V 2Z؄LMY:a´ڎKq5IF:Tr/L wQwAȸ`xGϝr.:Ϙcjny [ E<:Ǹǃ$™:ec9f_ڼK&ع\ D|?EŮǠ>[~Bv, 'nП))\h9~e vҀf[)zp%ԽP8QXXJa^~R;Xa%!Xame,]eEnGc JbF}&ӭ%$ñf@k'f(oֽϻ!#|.8]$)We)#` -r^vY bRg/G鎁N&۴rÛR؛`r"ʑ^_,LJ$Ox )ri{fP0FݿDNХotE[x1V*jߘ9}us+?%=~ecШ_jDw{E t=pLQ5i+RǁD9/Hl˚hf ꈴho'a^e2YJWCoyXL{"dGڨqMca9` s,CdcA0J6H𦖏ҶyEYalش 5eKfkelUY%S^Uq W~~ ezQ@8%]B;P729rĹ.|0ba\4{b gs8`/U .:ŀvBmYja8V#(l+<=ķ`' k>9Iחh|\IJ}TH<֝GaؘP[IǦSy'$eB- +ehtКjv) ꣡d>*e*ʚgM@mC+ɹXu v>"/bTHi)mw@Z+:@L?@ i@DKp}_Pۿ }FECQx:^/\ }Y5JVkBޗ -c0]t&*W_鍊% c dC|BI[6oq5Y F-*b|FO]8K+F 6a-orZY,-zb+[=%t%S&4_ǔaeX  T+7z'uDXZ'׸z];V0%K K(xqu%jS冫\k/%\MpqْO]}2Vp/`+F9 uEh~ [:0oVz$ L;+3iP ʼ^q%J ri"񺱍 `vQc' ze>bwľ̥oܼ"|bg/YA^ h hKhɉ%Iد_͜l(" ps |d,,/\GݪނXǓO,X-P:9/&~<a( w?ңR9i*˦X9{ccJz>) j+ה" vVhSPLS v>S." 8 q)28%Z_C`>mG %֍)ZT4]8M㘰̵ hȑl!cuqM=yP-v{>o,v p ø@Pyn;TpMk9sU&3|-?ʷ(@ADK!̪Z0 KS y& VbV--6<4y>a7CXD"uVฅQxD! !f)f'gFnEG MspPN _ea u|$i QFtj^ [c{MU4˖pV rb2A"D5_ZZeEŒ),в=~K=KY|#0UJP=D!h5 NLƒ8b;\x8r}{\@8pq)0&&ڱπ/CFusq\@[GhWC .s ay]A9Q- ť׷Fd5S}싀v.%ȯ6#@X5M|IW0[ ,ip#c`xqRs42t`({Ƣs Vqth-"я⬛ļTq ZbTFaykÄzaa$("Pb?U?_Zcj.ħ7TFJ+Lxl>^'%x ;C%Ψf[  WQ -$1Nn2{#)(LA1.eWh<0r~CzjFU6BJpS(z ]leZlRRlS0.Y⚎Lan3ʆl+el Lv3Zaśl͑sz4J aP6&/}CW]!WG2^`ut>2D –is^^y&HAzS \ۿEq6)P'SE8j qa7v f7S=%W Q@}BpwNJd(TǛdFBRa7XZ S Wqu)Od3'B®*Ij  # sܿRQ wș-r wz<$`6<'ᶌ0,oɀWp%@]!@l3M T$O#g|C+c~;U esI)N +Д§R.,~?j_g\.3rUѸ`Vm PN*0x "1)wp4+X0AwbI.1(%R3[ 10lGRmI*cQLjJ5_g\ 8EP ]Nj9Q8F-[ J#逡7a@MX8-AcrKtwij41ޠl ʹC"f PЌ0/q e3/l40R/_r<@?vոQn Ii{rnˀ{g8:fXBB|40W회OZ+ak^!{4hXm%IjyK- 5uɻ#MaLSqNV%ؠ'N"%Ff ̬5- "\^j"J2e2 {P4탇PXiG+1o4XByʌcHύCy.0'1ZIDPIb!)zN)v*)([">G E̳R?Vqfbn~ \` YkS,]5l-k˶ rzX0.19Y # M`h(k@1 D5Za_c?#,v)QNf[]0(/`lcB+93KVlLgA(z00#=ѭkgvXLt(/Hx|aʯ=ūeX{o}̔Efd1箆nHani*U~:l@FO_ޑ1z ͓ cRܢ2m sfZ0`_c"`j1D.809rࡶ2jqynad!JPhhB573/-]&,>&`>>N&&4x2Y`HH`0ƠBV pUܮҸFx.*c2*x($[9讔2L"'&pЭ8uA0[,jm"\1尿ZAR K|BKԮMԐ%~.\P <]JBuwIkrtED( O9F+6̨(3EJf 18MmZ4*i D!ۤ$#0p;@IgxUh9=33s2ﰐ8{DVh,4MH ^=ˑ"榊șoL4t m0?)~,D~$H'7/rH`5IUn?G4B#]{j/l]\Bw`e-1/C;%yh3gwl [uyMaup6^).pN^ C'{X282D^#}<QAHȮ5+Phᘄ0Fk(! kG!!6ۆ(^ N4"底A:8Xʂ#KPU$R7WX̑A 6{ca@-Ax?`RrzZ:*z==Y`@ށbcr J5eZ^GB Ő ѭ2?K9]+dE[)_>!yah*LaЬ>  @9 9 0b ]1Giчa2!&eI>KHdplR& 8\GO /_n.8%Hז`V޺d-}d/Jkczn%gWVHa?\C 8EѰp؜BL.V<1MzaױԢ%VвJG^A8mL\  &vHQM`3KϘLoc-4*w&Җ}W#)#20 eFP\wfLEa[ ZafQ3%DO7/4"1 vʴ *n $e#ce 8,XNhץuU2(t+ԙyBcutӑ#vmE5/ FY R ivøT?fSuEįdM60|\I3ae.KeԬy&V+isbJd &AW b1c -WY[03`NASiRn~UfD%*QP=3!T`={ uQhNX8d/y9% !A 0K[j1kDj <==*pĕ@ 3ټ Qc+/1W* BPAT>*' sPC?!ji&tRGFMAىQ+ zanNIIx,щR:ua$pab\ӓZ0Y[ SgK ^21Cَц#4dj8%P`=! ]XXƁ : EM.8Vx[(1?Ԓ"h;;Yg7+•7`Ԥ.eQflB,!vG2yk \~T_l"lLSs~qD(ȑ9k nC!d^$%TvMpዥp̭]f5Ŀ,!0ş*(-'TfpvlG\,7[X @-vm 7(}9%p1"V1O%߅ˠX,H*%1G 1"Mto~ĢƔbs*64%\bV4DcY6aQK(P- .cBJ}cHEȝtEg9yK F}^&QCs/ EtQ39nҔbz 0G$Xv&&n\\.j&J8|$DhbK**0"O`ei1Bj0p%˳{eקے+\$%ڷXh򚊍YC:`U@qCpQ#q9ʱ(X>>Ro(#VL+D3z<5Q%q I> c2bFcTG5}D\&cx+bsshRq/큚w2 Zؖ/Ln?$l@pY!1_Jq.GFk$Q`UPTflt@])CrΠH)oQRJ!cԩUb' @ $"3r%eX,ݑ7N5H3Y,l% ԈhJs dTD5uv# O=c@w]^ZNQ'3aWX*0F vmJNP0@~\4#^"U|^LJ_^U0F-`IhquTq:,2g*&RvY"azW <,, RpJ ?C4In )2$>H|oܸ?-8X\$F\ˑ:X;Yb)P xA|41/ Kڱjpd]⬐F@ET0lJ@*VR*L6@qGO(גV^J+Q'>H2TfWA=EUF@΍BG g: ekiHm?^UGV+dڤe\L/7;"v )*T_ޥ?2BA۞T,# kOs_GXP+#G7 J+~%6&e`4*AD p̚CTHu(@ qQʇ¶~+MϓYrr˗.\<%w.\.\.\.\X˗/.\r>_J%y\ZZ[1h2˗?/!1A 0@a"Qq2#BP?.Ye_ƾ|6YeY~,iYe_/ھ͚ID~1}G #(K2؊g'%rW,D d. p1jeVC_)*R?[-Zz"4-\T_9?4KQ*?Y2Fm~95c!v]W1813b vqiEϤbomVz2:=ei.JYBHݒ(^ʌ+&F$1! dR5yc?9A~c}W;U{fe噚invd[^'G@&Wsi>R8F!w:"i/W*Qj3N'&ISrMZ% Q(憞GJHj6bk>IfQ?-3I6M?j_"V]e'6&cJFm<;LMhhdDCE'\sfƙ4zˊH'#&Q{[}=S3Qۤ&H{YHOzENv?ie䒔"zY>ͅAyBn2bv)ms D䶿zv}JM6C-.3Ou&늤g`҃Qp=5ߓV,nW37+&F]2ͶOOF6f+d };>)#jr+t6HjFij%&mZ|0x0fQ{[/迳U%tzviYq>$yU2}c1_S9IF+ڳ}.)Yq+k5TĠ&Şf,U 3 3O!/,cWřԔ '2zN/&-KzFrK$Mu3w>YeGMZjfҢ1(1SY f6M2Xb"ZXiǿÁF\Q{#S\[mdp*jh)42`9_12U!cJ=lI$wlH|VY~ %$d1O m3+Bp3cmM6R'6h[ZN)"-͘frE쿆dL׸]YdhXvlUi$Ir&$h+_{Q1ߗ/'z7#re&Y /9Cd՚i~>{I8R$+&)q["id+mv;wbfr/⮹o䩍Q[*H&>I5I46_&USV[1I.L3K32N# .K|_d9;7#ctC&+go8IrFM3O߶4IS$](cۥD*uCHcTzx1MŘq Dpv5CIkII%E.l*E%ӿET;P"`eYeLqIG (ԈN b9$!!E~*1K2,DEQ*ĭ. DH|1Z(n$. oj4U&!};"H.fd&Чĉv7ծ%f(lkۘe>xculhl;eȟE4U$$푔sXؤ3w,OqB}T2VAНkY}-qe.!1A 0@"Qa2qB`?/]t]Wˮ?BܢzuAki4cu(N<ů}&GҒV*f,0!T̺X^C2N&Dzf~E=:G,S^`'?GE_َ8!bNŋ&Bm3Iw J䢶\ظcV%\L8B+bٶ(ƙ4woTD™DIu fPkɑMJbssH?_<ۤ(\YTݛ4d[vgIQ(+Ȯ3ѶfMS"+ɨJӦ&(P^3$N.<ˍSIQM5(Y3!E$g$Þm5XۊLMB䵑7iXбKO.In5˟V0($N)Rg&فܘFpBB4&IE;f=JY\j%wG,{Yo|mne:~? ry)O~_ũS[#ZbR_NϨmTO>+{4Mdェ"5X$k7.j1'%&iwCg㒓I0cPH&3ɸ$g',춣IA\#_}dO s|1_䋔/rEɪ)tQgcYOerU3zQTn(l줇}-*chKI1N- TH7BchB4>~ 0% B^mFE;ks$Vihnk)ǃ$j_ Zt'RC*$bHKCϑE"eh͌QE&E=hؕ&}&abl\rEwS"ѵy2I#O{茈MQvq!=d[bo5፶)}¤be2FXֆ"$2iGr>$ll:̑4QB+BE 9]^l[-L䡶įc[c$| DXB}DN}r->#rY.˲'u 2|(_g1ǢD5H=+G&D^,نJ6$Nt(,/8ք4!2D$鮫ً11Hd" 1FR&},WZ"s@-4%f;bآ,Lwća \ 6KJD#d"!fI;V*]eTc"o#ɋUC6ke"Rf6)Q6쮮H/݃c1Y6FԷe)tSHse[Fr Ǖ_'֌$2y7[ԓJIcLWTN/[+z!>fOk%4ENǝv7~WE\בLW^WJQEzpkgdown/tests/testthat/assets/articles-images/docs/articles/0000755000176200001440000000000014614000541024031 5ustar liggesuserspkgdown/tests/testthat/assets/articles-images/docs/articles/kitten.html0000644000176200001440000001663514614000564026235 0ustar liggesusers kitten • kittens

    knitr::include_graphics()

    knitr::include_graphics("../man/figures/kitten.jpg")

    knitr::include_graphics("another-kitten.jpg")

    rmarkdown

    External package

    magick::image_read("another-kitten.jpg")

    Plot

    plot(1:3)

    Site built with pkgdown 2.0.9.9000.

    pkgdown/tests/testthat/assets/articles-images/docs/articles/kitten_files/0000755000176200001440000000000014614000540026510 5ustar liggesuserspkgdown/tests/testthat/assets/articles-images/docs/articles/kitten_files/figure-html/0000755000176200001440000000000014614000564030741 5ustar liggesuserspkgdown/tests/testthat/assets/articles-images/docs/articles/kitten_files/figure-html/magick-1.png0000644000176200001440000105524614614000564033055 0ustar liggesusersPNG  IHDR*_iCCPicc(c``I-f``+) rwRR` ̠`\\À|T uAfVp'?@\PTds@HR6]bdO!%`5 g 퐎NBbCd#]M(I(ў 0" !, LKb,' Ēf20loe`SY|riQj) >x9uG67{@iŏ$'Ǿ.b8fMˇ_S# cHRMz&u0`:pQ<bKGD pHYs  ~IDATxg$K&s\DDWv r'+rȟftꊺ%2C0s=\ȌTUan@!U~~"2uS]@_{?xvp{ t9:=yp⹋HDԹ.u6=5 +G^]Sq<^Aa ZWSDgׁWkZkuظưdžA9vO= 78Us#3Hw;JPG?D=ێݽN2 |E8g:\= P2|rq+.Ȼ )TFw|m2p=n߿bKzP{,[auui?Shbw!;~g/@8Qϖ^cxasdz}h0|%佺 |X7 |>ps9t-eQ c ܧa+UO&Oi>lmyzw'#{hu^|U-};1d<!SqCsS_k𩀓!p4}e<".N/8wyΞϤ!@XwĖ8ܡOdOSa(yJ{:Wk!N8}LqR 6x?'4~C#;ew>EY{vutO7T}x9Sߧ<<=NUϡe?.UO~\)qC?'+ ұ{4C~z x]j8e{n/M|s{dj3GܡQZ 8@QDܱ ?!A]D{[v+/ԂlM5 ^ђu~mbB]o;܂:bz+NMT's}bn fI:ak~=mm[T';vh3wdzV֨'`gdͻB}7G+C谶H򸯔@}ܪ ͷ&=oc/6:?%vE1VSIk>q,Tᄿ.yXU6hEpytNA"1oa^s1?Eq=aUũ$')Y*ywZVg w0zq;[݀jrx='m/ 'Щx>_=8a'7xrQ5Y3DO۟z_9gw`WpCY $|`w# w w坲9.ƣ?[KsB^l|8pNIyv{U(;*>+5@L3S|.p ҉CGur<Ç"nw6g7+۲& p:Ӎ+p E@dNԋܟnw%So*?w{ʏ %wmq^9z&騄۞rZu?T@?aVۻ8L[I:_{+<\ ޜp$_Tb~x=={`7<[`V=N|n{mO*cOn@@C.bc*ߜxtunu3}>]xVpl2_: n2E#)Q/Xy}Y\<=p4NG}~z+>^D8b;䧧|=p 7_O}Z1?!<5oNq蓄ũF4><+s`QYv!) (Q`&cJ @;hY!o  ?S"*n8Lo$c`p yG~UOe}f/upyw+6:ptKe§w;6aۅkv,_= Ww~gl<#^vwۭ'F`Ncmxnįcϻ7r]Ú;M#qp_,8`e?AxvNDy_&qBؽ!/{`X'WstpWy}0'C}@}p=7g<3+IX ӒJ$zw^RaaafNi}p¾G2 3'a ~kOn G{;hO4K{w9ʜض2w0{%w8t~OՔy=vrx/4w7o;Z5'~_Fҿ .sIއzl:@q8_,CÃR$o/!vBXsȩ듁w̩^܎ʒom:#-vd5;SA@=ܻiw\ٝ]Ew&p'祩0r=89D\tYu&EQ zGxI kIԝ_liB!N%^rEA?#SY{pV{r-;䌖:=DSk-s*ײpTȏ{zi(~ "}n];#ub{u߿݀QOјS$_A~_^ëC47mQA쵪3]C[Cy4@"aUxN`~3URw/Oݱ15`/wcVi eHTcv'jmqG D8\ctZJS~;l N]!qrǃ⅚?4G݇#hKW+=cEP7L|1o,B[g1QQwoz_etwHp{w#SL~{Zd@}@D@7IYT>'4ނQ@C$8{9.>'ԏG|8Y*pK}@GF[9wr9bp9tXt m{u;y&hxN >z+p)#dݡK?˝8p*EȺpu섄9 pGT: q04z5q{߳ؓC`ރ}>]wp5QzNsCT/" kŝ!N ~ =lV@E0 jpOܓ|<(~4E7|mңr3 mΡS]Jn|ac|[h;Hz"Aߞ LnZ鞢}t į*>x>?Ъk}GƎԳ;kb8?z?dC ]k81',NT ZD J2>s?G@ ;?|aqp&Y}8 =߽C@q8 +C@} jqާg3ǡKdjZ-sOuJSFN9āq{ڟ:/خ7O&~p0FOY݁볩e{jvE1ՙsϫ!Qjqmo>au Žw|t1tʑ=^uV>6 Nܫݑ@ǮCLҌ7^p#}D<2_c- 9-818AN;޳Ӻ-1yl  \ 9Qo"bHzOt"^CV Q9֓OW<,9EۤM!;&Ύ'』_٧?g;[I JKq/??ݡ{DNjԽ{ Fvmȁs#?$qF:[CSc#2W¨@꨿ۏM0%%wl{.1k 0$'gx:?8S"(?u% q{nu7Ɂ<; %q+YQGn[F{: pMp@4'i a!8>$Zq|pOu?G11%A 8iC <)RG<&f8GE  Y A:SU86#~?;G}|2rR+˰ @h^$ X ש<0pƇB!VWK"vTy~^Gz{{D9ٮj8QS85;fWCk죄 lV߱Q5p]| k:WyX[pIފ|髤!-" ^O؍Aq> ީܹQ`u3NPA|w@b;PC|8:?SLa<L}J‡*@p,2w@<#sA=`w\QI`yO?w*'l"0D_qx[ bxn<8;K@/o밹a2H1D ]Eq]>'w$h1;S}ܙ ~)yt[fj Q{ۏ0ꗥ{s.w5:!׃ n3!d8 x iVzxP8+ V!? xL~c(3dp"> 8߀T{{"D `p<!˸ + >87yj2IOQl;0  7sU$ :ZSx;Ġe`}~-HVBÕʔL~DA|f1'PQ[#n!@#l p+,SnԬ+U25WEMcD>t <>l~őַO9}e;~Syew c0:};-uTǤ~f"Gp ؋@F 8a&ARtlx MLՠlIZ x3BϹ?7c&<9>9YŞ28PbG6oO@w!hƉ[C`^"~P x2 iavS~ <ڞm{wr,'ڂ)^ BG.ڝ@ S|GAY̏Nਸ਼D/fL38pѷfBl\?EQ{R|j@;Z@@{ƀo~TvӢGIbHc0>8P ;#(}^T\(z)Ɍ ?GpO|Ў6 xRb MHo@I^ES"{Pޭkܕ9XQL+p?_<]d@"1d+^3vcv9v;Iz曚'^OHbHCd'A }; CGkv瀀N.<uʻ>A=aRf5 h!H рj鰋`@KEO6M+W?FMMOŀ@{3p "G=#xs=I~)>n^p,}w +0]B| Q$y#yc@ڧQSdދo?86sT1e-P1 V~x#Y𬱗VI0*`Ά'ukus@a=x'~}ii *9 NrlʝaRÇKrsSFpҟ$4QzJ_|: 0ұǏzNq4Uih癝 4CS!;=">F@׈ :9P{ U?F&(k7@ v؞$6lO:s"BD A󖳭V4;m_L=æJhҏSz:okfF.*rͧ Q˙0Ȋ,ȑ@[QJEQEQ"9nNWJ\/Q/9t&XWda*?e,>|BdRUC"VOT}"p/"TkI=_'Jۈ"@<6EYH@vcmA"a Ivg`A<✳|YE@i"h"dU#R}ΦBȀo0WbH`ED ;lej8HEB$$ƘQ#C3ms6De@ާBS'XuO6 ߰(}ͽegL盬ȍ--04)ksW7T8 ܽ{6k2ϊ|m|cՄFvV%)Tor)Pe D&~a{5D$q_ "gdZĕe6K*JJ! MTIJZ vý:D / ɓaUG" Y=g2˲l^.W7e^%1Rb(tB:eӕ`GAP%7wJ/c Ц'=j<ØEQjRjqXሰ̸2K:)z+?ltG{#">L_1>Aߏp[1;ޗ(~>Z`g<5E A$ THD30 :%"$۳RU=+补KDHp>1Nx&g."Mݲ,s N 񠶠I=?<_ѵ[os|NHX~fg&_/77!'@UR+iwI@$RG$ZєF#"?_( 8=$v( #gIq#ΥOSQ$OIJOz|08aۜh lYV_|Y.7X+QD!EJk}I"fffNC&@Py1{MuG8 mӉ ZlYqŚhOz6YaU[Rm36+6_nn7;,4)֞HYCZ;D끠"_Dp4@gAg;K+kpɟa+9r^iXܦeXm#Aaʲ\._|)B{zWH)孷@_a_ uX쵡=C CP`NE!Bcȓa F(^G>j99ʙ㵿_n>no9MSM*bO)֠+=n@@ ~pEZ繵R^f@h^ rdDk<# X`m̂EȉXkOWl#BDD"ʒ19g"y4@Pʛpm:gm5+ԛv?dfnNkt(u.gG =+*AD􉛇oH_B)C U4uר6?10xxfaШ9G92/j5C)REDHR*D R*ZG^ Iđ 8G$yѠ,;cWC izuQޓВ;b=bUn/NTq)>Yn90' "g#l4Dqc`F@5"_cQHA"40rNGiKO}(cj32 irՕVZ@T9 S 'DKMӧ>ޚ$"Z{[(bU ըvcFPvw2 b/: hRD$Y$1lL~TFcVJAmEPi VXCDVE"*jw!6͡k8VmGsW\6α`j*+4˗>^\!FZ'I$ V*$ԅBVlppzJχ=t|1:'1%"k$J9V"_Z眏L*41vFQM+Hi@e8$QJYkD!9z;M7<mhfϊyAwOv+Xgx󇏟>}ʲLHIUO}"D5z}=Mp @2L SU. c"J)|ynJgXR*HX+bՓsMJ)u <'85F/&A@}F']:b:\('(•&_f((XVCwT0m,qt]=g3([,#&0sֺSa5qzdf#)RD1lybBD19"GZE16C*>jvaG~P; z@3;61˧rΥQ7I& ?|݋-3MEUTHlYIf*(`afk-hC p>;#"&ffrE!Fqr@+M%J0"?nCfL^on%DO,IQccQiR ?ߢ(-*EiDt鿃*vnM'˩zh0V{n7&6=ޭom+{'ߣ&d\U}~b^C]F&hQ*[*VIP5RǑNWCHN{k}%X#9sœı1+"!bD$J)^fCB;en34zPc븇8nr#B5o1s緷_eoEJiR(ڒgieB6ȈxΓ8`(iHRhZՊMm_k"*Qay^lqQUq"7[jt{{hϊ1$5(9`km y֡_J[5>E33mbܥDaz;mxtV(4%WjUw!*-4Epgq"ZsD,-i.I%R?zhNrJ}1(ހ@#gf./OU5s݄FJX.v%/EQ$1(2#pv6<ϝ)$RiMưsiJD2+ /,q`\e58Jx)t/an$26/H?dYyQf>l6d"R%QJ%uJk,"^@0( w̃ػuF0:_n7Ta+ k/BiʝCfoDZ91QQf9H eΓ4iR~Ζy;-O86*˲( eSg-B!OI\]])ʲZghfR)sbJ&E:a4AWEZ,.wbuքl15 uޭVhb}5Ss6eKbکA&:OPuqH@lOlQ[ QEAV^@ȯ*P%GvGQ)5y烌T> ՙF1|Gtt?)@O}AͩqHDử,vtu6ci_2?kmAG:@w^˲,77^.뵏1^sƘOE4,ʲdf 6MEIx-/3V̳#mFܐYeT_J)y?Ή} W4FG񬀈0+daa?zSTbzPsRŘ}nv֣q-v-ޓ&Lv@#g6糣Wp)or孟b޶mKl6_|,7Y2Kͭbo8P.z6!fRnZZefp 's("l"Y 7F^c>c }muZ3, Zf9WeEQc^)"D`A(mRte#MksΗl> -<ѝ(`E @Cȭհ%"A(iRI=Lnoos5s].ιsfβL)eLX\9a.oSxarE5ZD1²K4"ȓ+j<}]s@+m+kzK-k(,YBHY"V1C)j綽}֟{rsjTѽyxf' xmNL1fFa+7x+cE9QgMQzqeEc-E&Qu[M*j}qq7eO2Kwh>^7~._L{ dJ"u,;oW՘CC͵{z,c{Sw]wcmOBq,5m 9gٕe^)so" Ym?\<U;.9%TJ$0\aMLu("|ެכ( %u|2g6է%P!o|e3RZk!t8*Л:fV˗/y#Bbb\Y֥gI#̋feׯ_gYfY,$-*Q4( *s.uT}?Y-;)Lg]i1iH-&Lp 9ړ&U I/ > d#BZ E扙5&MXۣ sͧ"pk`F,dnf97S$u)9&H"* gdj>v 8#Vpʆ{EoY_s7m+{|[51M47n?컷Q)%oON xロfo޼Z[kU(bk|& U(IsN8)؞-fEQEFDQ90[f „,@H, jQPQa|j$TI}X;vCW^3|nnУY+Wd+)Uі3voi`QO XkKSE\.ͺqbc0""lTj2[Hg6)kc y9WěUgl|ؚ=އS&mZUUǗ0ЌPvicOUTn|8a\0sǶ;*:poO%wUD.(""(iccЌ:\eYyGao!u{{z'Ү44fqr{{K ٚ|fvQZi2K/y{uuU֛r*a$Xqi֋:%T{vx}3F,/ß`E!}ؗՌ('X']N1&7YVB$EH I|bwԘb!@-dO͋7'3(^gvp!oh!cU_ :#MbЖU\6F%?{af1"U#[+q3J&o,~ADJkRo?Y6OgWWo޼Aje'{EQ}7 iɳl6Ǐ?| @>]i{M031s^ -a@>d}qT;pzeLF{s8hShg$fz5knoo땈A|rZy[*Uz,:I($R^`'S_5zMDo߾4Q-߽{wuu:s EYڈT>^Hk,kEc34XV!L)؝C0!>_E>*dEDQ ֕՝m/3B;US{?M w@O>%!Um:\+_!CÇQK6&v.CXP]}^f۽mJ@S.Mߟ_iR%gf4QX'&[e?~5뛛h_*M?1+ez^+4,WM$$IWD @DŽ(N7NQepF;CKLZ;G#c-vFOZ,Mgq""|9UcҪmÅ^+dQq.sT7'A5rCQ{2HZ7Sׇ}uŧrZEQԖyx;)L97޿lHi_b%V;Lj)*yZzW1Fh>( \^6YwT#+]y?֑%a/azޔ{']֌8TwOHCo SAՖSUOࡢ(fy!3T8DBk~ Y)G} K},9a~P)ޯmaC/WLEP%0^C"BkssL9]QE18,SHl8.R*[h()|6)ZnΖo޼yϟ߾}E7L42Wm`Un64Y VѻT"d6َ/Đb#6pmi3wX DDP8$IYkZk4TCDZ[!՚(UoUցjC~1S3j [<ЫΧ;r˞]|[p}'vʷP2 i+ya_}R;k (D@Lf'3<8bv+ED)x2GDPHkR,z_?e_P϶wߟWskCG)(ׯO\yէO6~]Vd՗^>Enlc$UI23ܮgeY*^__+^~]Zns}sY>95Zkbsjd'#U,6OZ *Ď+9!w(,8M Q2[fed'(N!EP?4m@ @Cc F\ϡ`xn;.]!G3}AECj*ѫ5zO`*aJ8P 7?}-i̧9x@tߕA"kT>Q1y^ Hc97tDZkcL+7ggg%T<.;犢u4 6?|.ϟ?}ݻw咈nnn4-P+\i1Ç__a<4J+54Z~wɐyY?Nt>E [k(8NIJ[셖Xűd TQӪۆPtiF*x,J vyK~5l,]s·Run$aduY*H7Z*O1ч0sT@NT7iw~%^F:Oh|suש+ ﮀ0@h&Q"Uw꟫-w7cf\.4I,ooo߼J8`m>U$%N~?۲,__konnT/ `)rKGggglbB߾{O2w?8~fI$"GރJJkM 9DZ5X;*$}W+fQV>|{L,Mp@= wC5#OtJyU5u36"{8BO+Yy]l6k&%އ[)FXEWFaY""THikUOě^{sv+TR4Ʃi~uKs nj?-u/b-Mnp]2lN(h?˲\VeFđJgryy.zi.`)Rܼ{ezgDdEQ\GQH`Kq&4*Wc8^,o߾/77W\!YΘ>dQDDL%*,KL ! H :Ggݝ@צX5'\H Iўnb(\o(ʾeZ[Q]J:PfDćHkhcf*6 o#W 2c.~1q&-/N7ة_5MQu&ʇdmՖ zv[Ի\.-fI D(՗ϟ?74ljR)[JEq6իWR͍0(no4֊_]+gK$]D)ea B'WWWD/|ݻwR\$?1: @"|TgR"sGA߼`X"v(_m%yzʦ]2FNdT ۫mI*'ĺ̫m[0ſtZKJi":|9fٺ1z1~<|xe($ _+ M;mYvX|o޳gb%'C vKHKޡy*N z[d* }Z"-'ڊJ?TO4+'3#*ftJ@"4J{Nڳ fj1DOEqzֱw$:jE hKtS]'nOlWo F n!k3 WWADě{/jӈۚҔekM^/sϝ@g+"58fʼDsu7o,KCgM*(Z[nl)-`eJ)*IYV4MQQ?^(|@$ (HQ*bD$9/6nλF5=fm/DgTFHHc[*rd%R^eEzk4%ulo԰5-#Xpqi'^kj3vV<(aJ)#HR"JʆwmWs"#0o|}^BŜ̡+lEyį.YPDι׿ˇƘ$A8߬$֤izvv6_"xS"BqKٗc8VJi˛jY|>gE^XdztlVէO>}|Z)u@y$Yܬ$IVj(l0c"eZȈR{cWg'WH(}RU$IC#uTmE$d̬A"fWyG "L?yuﮣR)]sHbi˫QG/ FT]ߊH)$Boju IORO<[\em{]qo1ס{$jz)?uŻϣ즻+i~ȑ)>#'[Lļߝʈ2 1Yin<  9I)mq')7NSq5-R#G[%HtU #sn\ӧO?O Ds3E"IGqqqy*"U%`aa޲+ :["eYX[:ˈBJHQE|;k,(y1ӧOIf3cR'IiLQJY:cR fgDPX IZH-5Q;;8@;.BJE*֭lc4PkUͫbm̚HRTEwuDJQDyNPiȏ%eYә!j&c[ȓOh}$n#z36vGgiSttkoAa_?ObdgဝSqk`qJp^1^9͜"cͬF+-݅?MJG `O5\#}fy$ieZ-M,$q,R)b$IcR +Wmse^2/(L(8ё&Egk-,7E~?~ߕ_Q{>Lzl6^9޽{1_ZOJKԊ8s>1T-BHRTѩ9vH)tS0)'։j^,M)퍷RHb }ĦZ~Dp]U-ǸV*kj p{9b[4"-놽wS@,UnTj\1ZMAN7CEDJ#_je·c ;`T"c~w_-\Y y:8beb?k%պmC^Nzԓ_5rZoMTI O-z2Qȗln%HJ 4)4dj狄P?ڔ[F/J[ˍ;r(qrKRJ6ҽ35@c\ xileS"|7 {gx8̩pSӷx"u"N4b< }cztɍk"jR(~_~#rII5D4.ZkE2E˚cf}(H1l9"FYDH/on:H&[1UqI9R@Di_sF +$"RbI-CnOcTcDjTX~j>T%^FCp{BbUJ+`Ea@N|ĴhƴC}YuڣPD[}}K{]mm-S#D;>po w_@|Nw أ)r|ssCJ,Q$5?^882ENgv:sC}ShS+&_iK0BMAamk'"RJ׶S!je1b,u䬮핯njN8P (p3=m"<94%^ b^xoa88.y3|`S!ppR5=vhDﭤϒWU`#*yC[& IKV3k\qY`E*ڥ193'I~SA8DuW-{qsnɫ͝1#ET'lryf:J Xc2/VUEq@ei([V,ދ/6N )ʉY{hZW33)PJIqavYmŬ Mzm=]1 3Sc&Zq*)uHx/mUkܟjvGMg !=JzטepO$co!jєߡm =c?AM~pر|[ He kZxe^iY=cL$J)vhC$qP$6Uεαs@ylITke-K(cf^VI~+D1Xo6:/gjv~j5KW|7gggYWzP(K"O]7777}+X(fۨ DZ XDQ #F?`[ʥ%pr|Hm@ @FBd-f((')=@Z\q}mDi[;ܫ4XYKm[>Evnv?>ɷ@nwEЕg;W;m?in5\X6>p%-,UVx ,, U` $ujMp3 ;:ҚH?͔˙g88Jb[@sDZ- uYθ4I"X1e&JzF(,cgG)eIE^.bH4, gcQ:Q_JcJ[\Ei:bQW.non8"we,clhY9 @E$bEDZ{w< j?U)j*/ -T@JUXIi"#c/"JG$FCU "cJ,$}Ċ\gFʋam2 sa*bbui<׷x~{[h4C#N[2VwVja=[q[0cW?ǵ?h}hCK'|XGt䣉tͣRX=mǵg+@}~'W`4w47{q9Li_GM 3_l^ˆX1jh%bغ(`c=7|`Kd,4ɶ'K1[-9coBQUv_U&b\VeYB͛7?~\o7J)I9"/..Ç}ݻwnno.KTYn,{5^Zk@DܘQoKVܦ@8櫶auWM=}3~i}(] ds!WNSg>NZlXor+4Ol`8ÇTߦp8 ;Hߣt-/l0--Zb wD"x~ff(TK1Yynǹɛ$ZD$rmBWZk}"(BOyaED7~AŨp|}}m埯~_~<{v6e9%[o//?l|*ADƄ?|?߽"Z{{{;׫<"@􁮼6c'cMmju5"C/lO[lKeZ91sj,^mv-n&V=ᇡDWi7CD xwzx+{< ^ u n|-Xn.,AV)01 VQ[I-0X%ojo>dYU](9cG:sX 3֒i~=/)MuCXtQYSxj_,ٹ?._:?sYJJQI2_~l6x%ʪ4ibJ$o?OJo7oV$Itsc>~$ &R-a1U!K G9~CqnӖj5vPDY*h3OiⰅM5YZ ڣ+Y׋/jOV4>UR@P^\|x-=,m\.ww?W;*u+VOf曍٣*B#3TY#s?|kMQ)=c$ъDD,y-JZkٺQ9Vqw[#W9/a˿wnVՕ?$I"(>~x{ső֊"I/~Ero$q"l%!ܓP!)1)A!woԢ{hT=Wmlڭ*[s*a]B!lO0r^p\]?le-iXgwGS7.6+>IOк=܄ ƯhΟ`9S-UO5n2mJ۹^TAe51muΖ%͔J7! 1(Q_Zef""[VbWHW=r"E"Z@@)#I$I4],f^.Wgbt,N@8MWՊHk%IjA+Ec{k&9}QP,N? -Ʒɾ n ox!ƜRBex,ޯ"lST؛ܱ΁n*ٖŰȼ=$?GЮY^1m&]w_?ד!]-G&Jv`@{P ڵ!n9m$av!`?SM7~p^͕xys9Qб34Z[SE\݊.Ͼ{拁MVūׯP@LYXSFZsYEQd)K"$MsyEq331s- {=;AZSp!ZS*H:VZm1̳4EJG_֚_?|LWD ;g]S,n?|3Pg4MҸ,rҔie߿O4M<޼z ,ӟϓdfͲBk5ʟ󻹷 :|jm['B.MLJTYD-*ƘF j&DėQWIyhv6n>QDQZ+YkjrֲF$x"QH5y6wuW))1NPѶ ځBG_C6!#adI9?^?@[0VpԇVm~X|4|,>-,{9[xHwBDsi PKR(PyyG@D*+>|Df11"iP($1UX(VzvDlZ+95w-3x&"EgwP@WZ"/|%qlUe 3!"aYYҸ((εX,ffԛpCM(4ϣj /H>i;@TKUgGҭ542<36xvw6( †XW_?G<\{H+@PZ)gLq3v_[k98:aQrUeFTH +DNLYf wqq'|Eq5[-?QZaQO_n,[D\ٙyi1&SEőVyQZo9͟a[PY8o3卛]uG?z}F5媃 q5JJ͍*qkj ޵UN'֧>5 Iݸ6_ ܮ?࣊ qO@fD J<$G;Ss'{8&\̲l^Vtqvt l8Fzħg{9Ea+H`vdt_+8bmj{Nڷ@I׆qDiWwwRz< $C̷*r#^;\ݮwTz**R޻;Ğ&'-V.E(R|5B·__yH7WDleZˋ$;[sf+]HUoT8ރە}Loի1t 윎HiD&[V?EnpPDfYm6ۏ?m6 DQicRZk qY-a:vnKYMv{mZ H?󪭲,L8( _sstRޠ̳LD[&}jZEzt4ܜ0D-COkLYsz罹Qr8࣊ qoxD?zmq/oߴwl wWKYz7zm{ۏ#Y@mHT__~i$޼bUeiL$"lݶnJ]j8tV*"oL@ U[#IAd Ei]gHtsZ\\}YH+UVrFSXc3JcA /rOt-mr53+Bcl6c Xk<74zK$ j|DZcVX,D\Vq\_?> 1o}6*v~n +)NLg]5YTQ> gEz9-@"PmڶD*CH}[a)}TV|B5 \ IUrB*12:R1uW|kכ( 9g+E⊂*! 쌰jPkbֱ1Q+B`5&V7Pgi8JšٙDDr\!Ig7˛o߾~8Ai+dAh l\Dix}:y:w(`J{yqDıV 8"EZ'䙱VXuXk̶4 :RZkPHؘ”ΕΕZGpH|.4JHi8_F"@`DR0cևIl6̼X,h(-X#ũaШ@VSJ#%$W6_5 *T$U6l^Mo;:-ms o\2}ag "Uqyta-asICtF;`]odCnxn./zzHeF?<4@eܓ5s2/bkY}aexvm3uuD^o)bS=LSD^kF@Mt~~piڲ,=/$Ig:bqBDŐa 6/sx(4X צ󈕪PiV)JO_ݟ_~?H_|DZ|/WB9SEAZ[n6EY_^]EM鬧^yRcmY -묀SJWI!6=@F(/6qNj֞_gX~EQZkeUWĢOcFӉ +""@f=2ۡE7ƾ-2WUWۚ9ĭړG #&_2*3uDǁ~i8F(=^됂{q;cY{zi׀{dSOkNau+Iog&ǓVdS2%"SHY};ؔ6c!H$2 ґ :vc-dq\wnܟ ޟ'IrtV{mLv陑_ÑUܑŦS,@ׇlKncml`.Jb=w.-fzk@ށ4Jh-YEJ)N!y:_wPpY8NegTcG$,7 ٜ5]i#v)f%Mt$EB",-IDATC*Xgzݻ,6LG`qv)|ޜ-WWWeY.oX;Y늲0)gI:AB"$jQBl(^BX+Ds ]eJg KƔ;9oSZoűV8Rk)7̬P-1XQuE99>c뜋O+@ :1֔YHy#jn"^o& aFwf; Zbfٶ 3L]_ҭ#dmD$EX瘝BķO[DtYvuyge^iqY. )Yfgek&"Tw'm?t2/i1F4=??W |2F#FJ`aY[y 8H!E烑l~IQ%]]]E,WfΔDʢD$MdZ;c8FRyWmnOG5jqan+n֧1J!oRUuՕlndˇn۽uNovn`O-A/b`F7jaYSaޡaUiug93xBՏvm֤wL.`BJ\85mUܔ@ HެYooon+Z.BEULK0;aW3^#6JG"RcFċ4MR\%.f d|vְEQy6̔d)G=Ɣ:@EsYG|\ )3;X^>p? f`1Gǵ~WDj]w<֊\#wq12( TeeY H*IҲ,b6c3EV^ؙr;ZleQD&jZ zEɵ !QD9@F[w5v[V@}7[Op{ V3AI1ͰYwAw {X{W9B(TI+Cs'S3-8":1Wk $[ҸW8.!^+t`w{liVREY+E' (^noo1b-œYvJiDp֡$dT{," ۤ"IRj$2ˋ4I$fcfqsS)W?,sc4"gjuZW^f(Ddo6M^8fh:Eʔ*~N7JP9 ;6-W~,Z!;դY:E "@\l|f5D$CeL\FqJUFsm/Qlv&qdLZ-)\.IsAUvD(J)`!XHUu>s܆Ӗl{>:2upSH=nNۺ­ho$xT}`T6E߄z}sZ{ӛ7o4tRT99g!(~dyͬΒFı;Ÿ?JٙҊ̉HXyP8&4g2>||yqq*H@ID7ZOހ9Z+E '"1ܳUKc}(*5f!UzSgɁ6FJc5q+ʲtlqLDEb1,u%ZlܓrimX̙ry[Ej6K,HGRGjXfF&ucnxƢ~{cimGtR| ֭E]2^1[{‱S3fպq~#oĿ9֜Kc{vq7A'>QaFm}u8vB9w)"Ro~D8"cLYyv}}e+plqvfbh"#O뫠^ ;euFLZ& kqJ Olwoa^# c"E4b GDo71\Id6}qDI9c'UrY۳sn&cIi Rj1HYH#cdET(|Em S"mJ'r)q1Ưabrכj9EcSXc8<ϒ$6sV+eYQ~DXMNf-@^VƖe yQQ^y>5" {@uhcv!BoH[s,OH,">6ReUvdO50jھQGоPw;^coɆNFoT`Mv) 2aaΌ~8;߱XyTCX-VYA=D0y.}w<@~:]eUY'.ME+Q qUe%^B@RD"77_>~^8EςѫW6Mزt)(4xAc3={܃!k$5e8I9Q2K"H(ԖXkr͗M-3dvy;α)$#G>Ł62cmggeDIFId܁HE:D`kM%b~>˽?4W 4 9c-* FX\?(e]V8͜s՛7o,):YBf&rEO9\m&<' DM ylel6{(bt'qiE,-$qΕ%izqqY˜ryA8yw^R}lH8ҍS,(4EBc7;$Dn:$Ɣu(ZW!C)ɶ gjI7Jt\Z)E}0Ζ3+R 5\^(,EzƖe’e,|u};f^.XeYYZ:뜳E bqZhhֲsj^oʢi"gz:HQƖ^ORlH٭KJ)j{7y5d& vdZ++a~8I7vpT?C$2^#=ߨڰן(`!W{ְï͕* 1g$T]aax)-T1)4[UIm, v/jL' X,V^z7O?1793l6#"o- )9̘pXkCk_ƈSMrcx)C0v`*FwsapL \}ֶ"c 7{کm]yHl./& X^W>|q{G^u>z#afS~pV@0y\+GRCHdbUDZEӈ0go~xeEY2RH,eYYkcjY|ku~~hZ-Ky^1,Kxޘ4Zc1¢ M~1&ʫWWi:RI"BeEi$ID2gZc"dY)R <7gTʲ0fEZkl~JsH̩^.0JQ.Pqq\HGK"FD_oݹ=hR0ͭ֎/J%רԯF:EzaO;n{2S%cd[*)<+}x3>RvX]}>T,l1Z#OmXEHAE!",|`"Ŏ2g>U 3+yۢfRsP卨]bʲ(9`c 8W*mm3^kȲl^o6ua<+7IZRT1^`bv j53F5ܚE;&Onᄌcg5OyX V!DZO ZOFmkaUL1AFw5cB m`iUԵo[v'eNexjk ^,-1WM3> VyD؄:*0x16 Eoao '7)WBʼn2c'H%sV2!!P|12 >~^|w(JE $BYJYWϮHG9"QD3>cDΝc"_&sX/E,֦4nX,2/bYqXI>eo "&ߤĄ,@;sⱻ+"#fec9^jcY\]gDuoOuϖ]9|(| rZ)EYe߻*o"Ui<ˬGԨPQ4"y`Z[ER=3Cֻ3P>!R&;DZk*Iߴ YZ,Z\o㧶m>}/~Ç#~ ض Ƙ]oCi~N˜\ɂ:DOZA`_-~10ODgY.,cۻDȤL(e9Oas ߻4˲,SH e.2P7M"P>޹䣕RV ŇHIsISQbN c,\J5Q ,KtIZy#yHѵJK ;{۶g(7vUBTUJwhIUJx#"T=% @tC%fqR^N_ sg+ɽV>經  f_F-yZ~N/?}KŰ.<ˮO_ηw|؅iB'9eq {ybdOyܑ=B!}.cr4½d+yD>~ k{A];-#EbnHMics} !Đ4E ޭwhgNSd{AHJI)Qȫ Qև|qs}kH7Zj~u^޶BH#Y%[.4yYeYlDl:uzv)zebfD1zGxWzʘ$Su3#zNKBDQIiI9ƨ,˲{`6Zm `&Didm]b17-e%h|W]~ڇ`{+R2s>o׫RD^Ik|xl.-ic]L^ǮkRJYYgɋ"FiI"<#;FbJn!oyS(Gi; !~bx\ӮvD`!I na<#:ȟ_;%}az4)ON?#Lkqɤ99 k(bkgvF(E}6a<=*D&ȑ H;7 y&Ykmy'Ebܽ~*E{gDqD`Bđ,<.ۺHlȈvun|}ߧLGZ,˲,J*7Y1R)LDftYSPRJ!{f1*FICUJqҗ5GHaKHcb%_r2A'֧KU ~`J ;eB"ϷVg1F ެɒW{.ZgYX<zzrE}#bEB!ҙm;Όw BLUUiuRb;&δIwRJ!$f "9@.9{(D)!S40ER1 =̧f7kg@X _RrR_ކs]l/&MO?WT;n*S i Ry1h? &"; 4Rp%HQ^<XwwҽCxxAg~K$ϗzLCirrH6ABsDm]?>Ų(Pgt)@ !z@K4֤ce/IY>sӐ{ H(5,9C{yo|saE~ssn7}߇HĜe5KCf[ofp)Đ`rZVU%6eC&f34(pL;(.GkmpD\ !LX=$U2QGD,2\x>*`"\"ZeY%|ʦm~gLVŇh /RO>g|Vml,So۶i^E䜍!vm eY*PhH@}oZkgBq|>_.5PRke d2k!#Ds  (Dbăw1F K: &??wg1.y~%?_> /N%'vo}S/  'B5n/Pg쁰>FJ맧'\,}l6z>_(h.BROvkM}}pvA5Dlч)Hp!D>Ɛ)y9D9`$s۶Y]__w]׶mi$TJi=j|6!bI1'$0Ҋ"h1Fsd6Jy,o,{xxFd]%[k̬ժE?<<cf_Rcs@|xZonn)Rw)pfs:\Bۭ1J1J4ƌoB' m[LkwWWWB 9(l߇ TC$9 JZċf29 dA>9cϿ{N}0/EJ }sq*~0҃?L3&胸c7 /K0ek%avk6u=ہF2rfL> k7u^IIκlFD!9!@ G,H/:0 )cL{@$fFR)W ڶmŢ*K^ܼ~Xhmfm9qaJuozݵ-+m@>DymߍF v($}Uʲ, $}2MR(<!V+3;B2 :R %}o!Ee:e)3wnWO@*kݫۖB7mʲȳ9g{1YZ$ haPZ )Ҁbp>i' Rw=刐zk@(8rp!R@b1zAH!R*%5;"T4}FR/1 äR4.4@=6>x%&gd tKӍ Izw=9|x1gܳZO4ڗ Ԝ DLrjE1ϘQ!jz7aaө]Vc;gp @ĔU09 DnmGl9D:#0Q L&h%8{ ,LdԨTZ*RZ7͓9׶mrQEV|>+Q?uimu{J)!,}Ak@)5E׶cp!M L{d'$hGXy#YYǹ:+Đm+˲,iC;SDJI50*7m eQ(zkB}]맇)G↌۶JAcLjB0Q]כfZ^6u yxxjZ'i^ZbHɜ}{yC`5sS1Z(/*_M_؟_srah&,h|?=h%fMt<:r70yq\s!(p:Hc]H]yƦh7 f@@+ j!D2U9_,?~꺶Ȳ4ƴd1eg}xxb"⤙ ) @)<@18tTƏRJc,g7oH!c,7 YkuɢdQ)jBHXk˪HF17wwbx1z5'%"򽅝}5~,Dɸɔ J)"LԔRodefTUUD=3]Oi `՛w^?><<ݽ.b^@EQf>"1%@Ķmu]wumx֮2)\9lWBlVmšc@ ,ZgG"> yR4$ GoKQ1ƶ1F"H1>geh)I!:ED! 4vJ0 1*/b`B0~0!>->Ҁi߻fbϮqr/)Y}}___'Hypέ|63l{Lӵz__]Eh*"6ytBژ0E >R.B Yc!ޮW@$8nb%Zi6F!b$OA$  }|(D.4]u/d^2eչ(z ~=С}?k8,6gs8 q{t'#t‰O`Ž;h _z#~'bT]iy<<`SL~˥|Ty!dDD {`}2麘actBZQ6U󲘕ER? zz1$fvdYyh#w},泮2/˒aLIR&{on1FS}51hs]Raܱ{\ZEQ9I%ιi yuhgYY+9CX.Bu]/?wD1ύ1yY$(nӠ4M3̈́}%R}4ɂ @#[GDzX>}ϗ9(T'v.dYVUsZ,?}4M%Bp`c)%;)rQ͖뇇z^=>b@ . ]UEuuȲC$EQ# + bDiy=19svNm^8 cQ^3\S @=Q?՟/.ɿOwA]Gw<^y% s>:$vmszӝCx}1w9G5ϞPB)um۵;6M4J!IA(zO)9.0 \pu8\ &f!Bv]VOO M!B 18z\R,/#ŇLJǧ""{^tQ'L<7I!AJy ɳ@+v]w)M]#bROF :1sh ;J}2w3EʶZG#v2M{M)SH4b<___YnWOD ZNʄ1Py+l6vB 6Mz||b(!eC6im" 7 t}/JͪY׵z`>ޛyd68Gy>C7a9g}e !8gc Z+TRi*AJ " `Efe̻pҿYg]?ޗ4]{,WX`՞'dL?MО3m^2Aߴ`O>^M!]OO)aO+&ie&>NV托br`PKD؂(i(Rqy#%ͦ/C``EfIc"^\_]]-@`j6ӛwoEs/py}5WW׷wPuibX,fŢi}{8u+onn_ʔ ڤefYfIzstՃ8˓9!u,'R0t0j:\^J w15cӵ*JcWWW&\.c~0m_}?o1"#@(Dsdb buS B#Y?' ̌olݖ\Dpm{[ɔu , ̫۶ylAr`Z}fEn2㼵͌^.FyUy)D,*`J'yg3eDQdF.eY/Qh2m(dceI5\=/B*i|6_~NbdA0Cu^ofwV5J,gs| ̽u CB*۶IFk_~Us{Db%gmˌM QKyZ=|x=^]j)/w Q+ShmE^,@ F)P@(̵\sOYէw~xUۯ]y}ݻo~q_LQ.n^. DJ,L1T,&*fq_M:Ӷ/5A'uPL #Ѕs2)43ș12/@0M?+:/N1a1O%t0cOᓩ#_OG%g{xs̡t> a?ϜlS,AsqнS ՘`R4܃Of/HLQs IJ}C[kVZkZi)%y` JJ)$ (&ؑ"0GzBNlVT3"jgE6.x(˲ۛo^{믿fbG&@$ DyrDZ*Tf&mwy,Kf&3$A/!io8iSj s]LQz368˲r\,V#ͤΌ֦(,ˈ۶J$tUUEQ(VeY"pΦU!CDkf![D',,˼y%tb +Һ^J^Ie#I)]dpx}}4ZS|Ï?&?`(R)M[4 D >#\\7ݏ>՛bbqu}sSyeլZ\-n_(VYBg1&B XS޴01Sz{_~[O}\hF‹}S޲81dP_ڳ B/٦"LJR*.%Kf+$0R,KD'.$Irn !22s$ )KRN5cͶό1:#rRF]qXD+r6UUJz=c s${cQHl;Dsv熙뮮6Xݛ7oc4c'YksmB׶&϶Mp} .W6EjuEYei)EЂ"z(1TTuc7ռFھAj6S@yY:J ԲLKedB" RniBK9/uJk8p/Sԗ<(/._8~JslY#}#uN6'N@[ɶ /.3J1.צ&W ˀgYXF`!kٰ)be0"Nqcs~>Z0YO $i%[Mka>KkMrB JJok}"LJ c]ʡUJ03^yzbQ"3T ĞcZ ffN]̠l} Ajl6]-ntu6__)I)1|v敵`\ ZoWr>B-$5˲iZFI;wɑ7rrM`]ߤ"٬ڶU`=rS #!(X9D&dȑ6H; &ԮVJj%P D Yws>Wׯ߼{(9gK87wv&fTt,\,g!blm[}=H)Zngj"$ƬiATVK}DWJb8٨T\")Moۦ(*pj"cbr1@۶J͆91mQl)ĶCo_=>>~VkzKhRb1rBr9ϟ(!L}(Ĥ7f[M no曦EQ#6ILjsiZB'2ռ쬓ZY.8<|g T2t.JY@ Gr5Q`CGoف3e\ ˕/YwL]S Y=P9qwwk%w{K{u@||&&V/A0Int5=xBdyNx:6Lx78q#d Lλp90>1?EJ'6]״jxxxzlNj?xWUU%u$>7Q1QoV}uB<3l1M`igy9Ƙ$ @H:wIMM>/Cm0ǘ4Nُu8Yk̬2S,Ckl4vY=====uM|`b-ç蜳ziVɺ.bL(D,6JC1~Δ d|Z뛛'@Z^Gcru-,ef.fb]Ƙ:u[eιɌ6R FPR " B:gHmOO &/MU*tmzݬLn&7B)0W6h3?+B 0M0(D TɾӒT:`;xz{RŔH>Հ_?/"𱚛t<ꈣs#C8oN|6w<9F8Bo0xCI;}VG/&gQ㲷hck"40L}E0JwqF^(,#đxatIY j" @TwĹٙvי`!Djm[wufJo6#ru&fZkkl6C![.WWWu]gy( !*sB@4"F OB({fbZ@^(5Mw>|BIJʵ$~jBuPWZ3BeؾeUto/7??|_}R8]O[.nC(g߽tϻގu/zS]/^3J<]?Hٙ%7Y^~rG})}u sCrS|2×$dZ&1R),l|B}R֗I=d`&W=p[( Ӵu^JW3cs=ija91aIDnEQH) 8%xKRGHcQ*!T (tI^Nj(\ejy]bJYk_V1@Y%>2%iߴCy{O>zjqRym۾GReWU[I'=8&ZlMt_1tO7~S^,=eԏ %8p[B9[}Ã?nt b`wynB|Z]s{{YYUͿwY}({#UUU{lW71Ƨl6.y3-A(BpuvB*sBۿw޽{njRꛛ(o{0F(DR =e|6 ,bH2030ÿ__+}s=dM]f̔1k--E ahPrZ?evAG'Vc:abNX$Iۗo1|VTO\sLՒ$񢀿aCi;{1#p^"=Jtt~Ϊ=|<be!z9"ʲlXeID]m-2yr1@reYffy !eO6(eY6y,%;Ru-Ȳ,yC`U$ʩ*7Fg>tu[NJٶcN1 mVmjE1}]oKRJm8ә@`f^??feyWv>{ﻮKt yo[,UnXJ LۺlBJ#(U3%E۫Mr+;\.(11ϻGA<8ym^,ϫH_^zSՕ`jꆙ&˳u K%T S:\3LPC̙ʌ3 Nj/9 ϊS&yy=1L13qC>[Yh^/ , D(>+|~DNN/p _U8S:hmzI㕄 |UIOԘόnU~ !gsf`>JkmBHZ뼵2/  +VY!Fzc11x k!&ު*JP0]uB@!yUVYnwIt])J)h>/sRֺ(lVeY]׍+) $S$8c.+0F|#Tj=vljϹ(,KK]ɳ0ĘcsDmi^IBH6BH@!Hy$F4n Y۷]4} ^ =0Jbz9VDT .YMLXlegywnZ!1ƘLEoodDÉheFk%RpH9Jm]wλBJ2"1""D~ӏ貪ټ* g]p{,Jc(2AZL11#%SfDO}}/ÿ7|b\OpOF( 5ܐ/>)^F1V;gs/*<h08Qr(A?=ѫzZ 0^C ݿxv!٭ر\EAưLʙ%P$ D$bJ#pp!r4ZK]gxuYHglb @!TS&GbOrfrTt}^_;g&3,Kf],ps{ -<˄ VR )icz!S*uwʻ5Dʵ!0"`p.N̕< y/1P ͍1b#pڛ`pRo7z[{'F#B2BlMt9C!pd" ַۦ]vuc.>z|Fdx!tDgYB$ޥef罳^]f.diJ%)˅{׶6:XWeRZ*!2B TBH (u[7]Y, 12)/^~s{{7ZP}ߵ]v nNCh[P8Umwg;ֹDx,P볅]yBӀap>(H2:}%%&A`!x4M۶% mnBv6FB}zlէOzZm6M۵]ߴ)2;bmŠ0xgb1D""}o*bILÓXIDEY:k*ϲoF!BS7R(L !bZg&Z&1DB 1$gJm.Z(?h nڬ^}w5P >ĦC$3E!eH|g H(.e@ ؏<" {3%̏k bLh/ |\Ңv96DP]|asBdI. |Femc{hR1TQΔ.BkFI)yrQQk1j)(A$ Zsuu4fO$UUm;])RիWYV , !"3d1:B$Q "#䲪2w"H!#9|ki_]ϤB*=.4m/o+{e  bHhS} 1><7`Z;b?[rrk˿h;ig# :;;Uy4ݡMbp0!m__;_{_| c_g <y"6 c2["}ZiţsMnO,Ĩ[F 3Ҿ'өaۻS5i73J@cYl\&YzAk*bB`曛jV2sumYAH'CspgE6:3YEQhvZcE~7o!Z)%L9{yJu3s22.S`=!/"j. hpץI֎dcƁH|B_Vu2|>{pfk7}$TJm}Ï~Ӻz뉅0&yeUYB ںiڮ Jnf&<;c c$fיYYwDQegE1:D%2!b!1)K1{R RAR PE:JJ%")b AUEYaɪ~uw]f"3##sGZ(i u⑷Ŝ~9|D7eʹLc4 k=}㰎zrޑ3}H/Z\p)db j_aч4\v})FeτLKst>^]]-l6R]/dZ$!{vfU ^,J 6!yK)Õ gUqX?&s5AR#ȦLY}_|Ç{\o]mj#R$_QXzj#bBf.yƸC|rl<(9S*L _(ڟ'ANQBO:K4sdGd;>0='꽑é?(S ,v=ϩMK;'~|I"ϬP9LL/k{``9BD_&z" ^Uw澮꺮kvvm!Ar6FP|fPJ5MzMUUۧ:"* HB96˲Ȑ@RYQhU,^.e1֮c 3+eQw*OݻwRfnfॶEQeif;-糔1ЇU9ARtZYkG2\X!6TJI&"m+ ;Cmr>9wwͦmTZmW\W럽Z\](gdR))u1˥zl]ׅٮY=>﷛]]׽PZ!Dk3+\RʘE؃:7}dJ1d̼qaVVۺnk!T͛WeYfr$4!x;DBpZ)ܵΫ w11JREMX΢k3e^y6P C &`fvۮkbH+dOa)t};@'Dg=GͱJs}l>湟“5y?9i?r$??D틱P1}nu].c1A]4IH %8e fx޽Nҩv(X Lj'&L\ЇÅ8RW,(@ h8z,.O>&kӃ:NIB٠BH!D A( %M~:+RV; 1Jt1eu{wӏ?z F 26TQɬe RaVBsdzv}5) ԙ1QJ)Lat1QI<1UUU乷nV)PҺ ̊\祏tN**-1:9RSd"e&b!4@R J@db{&F@)L 8|hy_gׯ^X眷D8Xڛn:H#Hw_j &z{_oϾn7͝2Z̲^egPի7_onet(j郠k,ޅ E.P$b%Q DL䛧')CWO"Em2t>P Fnk)Ĭ7?6_{-,DW"Ű\狫(R@ 3;,"lͱWRdyF mS$,G&/Vutm'Pju#H[R9\t $NX=o I=} Y'If:ԣ0 ͎cBrOjS/pJ0/ 9A ԇ#1i g9|*Lo??4g:C|t_Jq89ya/蔢6(|g- 8?ǽu1s,vP:pdx _-N}J-M@?<<(% km]I>yv$3G2!&vhJ}ܺq"3T V{KxRa# {kU)Ӈm@!$oWmn_bdly!," Q }+$Uj>~#kCa)<Ā,X0O B fv1eV^EރHYu];\.n]-˾C(1Ʈksy_g1F(ID}QKc`f!ֆ ?}w L PkRRh2 1z^^OF*b6M˶뺶͝ ]fTbQELR9ڢ)0${.L#/7_. p:?_y',LϦW/_W{tu={T V^>D垐"p xhpWx/#_%J$$de?Ao+pJ<<]GNK$ 5#)H)(/0s̼Z6}\.WJyushf˂ׯ?a7*"Ac3)ɲą$a29<דD@ZK㜳Cb)e[VBxՓ,ZsN)Ud3璯7e/(<<Zk\""Sncu1_C#9!~* NIFVL{ͱ?|$ctuBi1l1?Fj͟W_},f,$HB2I* ^E&Un383}#0w7O?0bCP$H O={ј\J{z|,5#RJ "Jl[HBllu%l/ʲ,Fl6v;riLT`\Z/˻;#y d-13" 9ϋ,ik`/$Dme*Elb&6DHiI>N,pyϔw=RTsni&= QTNODG9UxQ{v-=|埽텹B3'k/ܗϡBbbdu\LC__Sis x<µ玝4r|xO5{\>-qUӡKN7iS2B w;۶m!x,H S& R횒;H3ٮ kTr@}u>5FN!F@0ŝ0J*}a'Ĕ'-j}I'o2(̴TJH) K B% XQ($`i\ [i]=?fMߴ]mWӓ1 o7YTo|_oZ@ϯ evm"hB-TRJm$D01~i#Hx;baw4^s2""ֺ*3 QoZH ><JS#9/J)(Rum:Hy,+(b/OZAy]AۻWww"|2"oNT_I_` Z>c0jly]r^c>hH6^ sbnoНWx|t 7D̝.X Ecs,|&y{)& eO{'䃂~>[v$w5M"y>'lVM8fEJ_=>}ͻLB:S_YkeQ&̗TF1ET(kKZcR"pu٬ʋt]SՊ)\j dBTU#V,KJ|Y)_B2#UO< 1F d!R*=:MCPJ!AM0yGRވ C%SDD P*MBfR-fsD9(>I*sW_-n__El@I@qX+QeY$΢?{xzrg`mWGH RDwM+bHAϨu3ҘLaFf((ևW]i%S$a檚%n)-Xy:6ZJLiUs"[s QQhcI y&8Zbh۾z;f:N " "@b LGR(EdR;xb8|ڹ<3\hd~F} ?_b= `<ex:{z9bbG0p1;Ngy*<<↏ G1%ɳ/b8FRNA`}Eook {/ft:s"9^2fS !&IP9-8mE7E"nLL#mv(R,$8, c$U҃S IՓ GQRJ"2b|yW~#1vK#!^-)!8y2l6ai?o̽ԛb cH@u[rT ]w*)A i#HEu#[!{r-EȊ:B}4yKe}ӂ!(q\cB \41i}ᅦgRJ}KDyE. ,ˋ9Z.-Y襔,r6)s%%D Qr!12xumny-zva#R@1Cܑȟf8Ÿ]hgu;{E&٣#|VaY3M71^Pf.3}6g0\$ƣ`:hvR=N 0рϭQD L^ 55@8Dk9 +>b[9{,P 镲}ܼ~:z`{ Vй0Y${NZ*EUUB E5mLe4M\d{{_u pʲ,^&.Q\D䭥Ln IBJ)&ha4ڝ\S3h )i)jZ|#`MD&ܵͷ?|_wby}?z7]; DRJ-mO{C8p]W?^V>H(D3" W?rmSy%@ 4K!)V{b6QGV(ڦ! WWr) Te,+rZZ21mzRdN~6햢E)ٹ#Y+,KT,ˢ*qeYb`"c( :H>DoEm˲LT1 `ff#: /g_S 휜O9w/ .k2P}%|""1̖tfpQ yrr>[s~@Mz8sT*<?)gSϮ|Ojߘ/\N#"K٘ܘ>3ںaȎ# -Zm Jrߴp xzW7otM>oӂ*{wIu&]̗j6/+HnҔ:眫j>٦CDւw>zyU͋h6HQ%1[,R6q?_g 0Ձ[IINȉ+$h!H4 yGJmvuk)~Cx`?4ZC{z7dv|a9[_6sdvv#k2sAeLvr󲸽KFZD̲uC",!bZ1ݶ((A<<|pc~tymY)UCb{z>_c\T>GD} ;9\ 6sDkM|X)NcURu%3ҀdfpI|){nb9/,r'*d׉xOP}|_A;e/PQ/&ag>v qIE+u4sj`0Nq0䁀ݢ3fq<`^G+/=CNi9 v!ùQtBHD!` LZJ%egyfI]DbD!z~V# 1(6M󬘕B !]ŸnbfjiRJ<˳̠]ۡ@cLYR !4yKPRJ`Y1f6I)hcd#e O%hLX0e2&ij)2Y1h0eLҁJH&Hu<=>2ׯj^| ]Ǐ~7~'(52rلdpl -z:,}@4 |i߷ak~z6rVev}3Օ:])D|e @q)M[gYB"YnM]y׵OO+kfn:!VYfivIǾMVKU1 1z-횾m嬒@}nԼ_TyY͌1J)AR*M°3s(!P ƒ $"(t3@ @{3f*<9w,G^AfOL{$_Gw `#`LļGNCH8g7¡}<ύmn6LJi?xPXm |$)ѹ΍$D ú_F7KUe1r~/K^IDATYWYY7=h1D RawBnDWUp*f}_T1&#!c({onA7Fk-|/;uYD,ZsyND͢ab56N-!ռE!4DB R_cLF:DH4R};9ZL\,N{_:BkArRL뜐g-VpO)oj>L0] 2bBf2{)wC1<-|?m|q~ŃΙ=7{} O9u̸cP(mۥф/\dBy۶OOO1̳"gfBHf1,Z)ֵ\,U1 >b ϖm,&@ȬuۦvΥeUyƻl CP늢H,P"rJQRPw7Os!͇CU>L<,ϣ0FDcQ?=>}Z*S"sk}͛n֭@ "8lld)$fYVж.8[=4l> Q't Z򗿼{qe."!Ĩ,CD!!GH9 .ĔIy˲tNR)OO9U au̘eYݯb:Doc DIk,̐<1R𑙥}ݴmi777߼iȄ:3c۶i]{@@)ppn#)Ly(uu-E%p!V+,R홗wc| QL\TR )RIctf R$u}1HIɼVܼ~'P@Ƶ-P e&tvw[zBWs\6o߽AݷჂy3 DR,",KNF$!H)Ty_6a1"ۺnV ILIZ"%@lL|}ߥʐ1FfH٫R$T_mM EQfYf i)PP)QE!T*RK8xcr'<|gp10i*1>S6Ov/\>@LLIw/ >,w=m#==|>㽛Ck_eOn{HD=?v.:Ln,>ħj38k?tګ'g*q5GyڶmYI-0 k <20E)rC̀E"gq޽7Y&!$&!>/II0`BZ뤁u7&,@D%#h)UX '`j/Lƀ/_hEݗNnkk2 /vΏH؄"CH!0sNy|2z'r̋jxuu5fJ<ϯvnS)80  (AuJ%+%kyyVeLaZWEew'VJYkzRmGRhLw8 =Sʩ$ >D I¥}k)ruTEQ$lT6^(ITRfysމ~e]35D&ۺ?bvQM "D$|V\)"eW )Gn!D‡Ym-| cnEV@tbZH!< #r] D}d2 !'T! "L],n?|\.PhFRQD2DP #1pD̑|2`"}q6N\yihHҗq_>BW?7BO^2:_,_x&=~Fg&,^.!`'x?e?yCDT;hju/0%1v")%]fCuv\AClLy$hEcf̬(!x c`(DݎDNy6Q &QߴlaQ7ie1R"VYi2g 7RZ' $gr$0a9t)"ƒOHD$4 8|gYa;mcCXYd& >3FIcafiL E캾]F=2i)1J oo><]ÇBtB],R D]DFDb oJ,2!2mVJJdDZu 9B0ceQlDx2Hb!^b!u U{/JoZ.1s"#>}|X.o޼*2)d=( B#wQc6F (  G/L*/y.=i@ >LxIg8q_榄˼6t>ʙE r'iH:/"P8 PKRL(@GPLr[$tRԒluv,1I" !S'WoD sMD1D#B޺!Qo@pC$#ozf!*Jk&9*yίn2nGweC[BQ̯u&](ePDa@VzCJ00Rgm9o~ج~UmVb՛~SU9v1fYfv6}nY,Rjv/6ONIDF`!IvadO\כzfRksUU%#!`V[ [3њ:~X@~-5 SFZʀ@DYB,eEd9Ŵ;蝗e Q p3:ΉgfM_wj:m]>uDj>s<A'4Qu/ q

    7o|77W @BSs7.证"?Ghy1 c$~CȄ̃_!FNY+P< W7SC2M~'Wx8zr'mTL J Iʦi}߶>}WotM \֦*)&B6FhZ@yV < %b*vH&p"azOLbkN}Cp`|MeBP2h.H98EQeɈ8)u t!YV^MowV;U2R8(U.z)sgZyol8f"^o?7UU?{{Wee RJ兡hJ)cl6Yt%1ƼȈO8FyeQ"G<ϕ1z%QI) <}U>=?P"VڤW2>'̬vO؞_N @ws>ї.T>Y9gdqs7, LSu?2bnVp{ڬ:OÿOP\ϻd<1POW F4(Q (:K񾑆seY6ϵI2͍LE}߯O8Ͳ,K-L{)ɲd1hdh$#XZ؁S("anDpjwpqB8뀑jH-L<#@8ק|\\-W^o+WEUUM֛߁;(,HCc1H>Y^.nԲtC<= -H )Ri?}w?ȳEW_2xWEVf!Z;Eھp'Dޟ5r$i-b$UsFa<췞骛̬"\9 j΃ qȬw\\OU?%"߶b  @ ޲BD<e3:75wlTQ<Љy9焀s a>0:] 'xj0OѲ{d{ 鳃a;App&%g.'S[{zSDʒR97yޚc:L]uu]ekj6eYZfs{{}\Z)zgER$@Jy&BgEZT4^ L1x:xq4F0cjDS1ɠWR*I4KDDmM<,2 u_9uS*IY֭ۤu:+BK=%'O[JJEfE7[e^ knc5[=?mחWQ%6{'z*Jh:Q8{yR3K^Z_\J9VwtΑsk5R%r$5 H2EP~ٲߖ;@7+޵4MCd:ہ.{rn?iqo!s ~f,:ǧ$ͯ>/Fc_M2TLpC^Y1]ԢTT8^;MF'Ÿ=se|='M .|0G@Dh"&,˒.F9ͭsL%L;UbիW>}ZViuugk%4MTSZD4i$P2#狆޺aBg"⿆HIXW> hoƱ^nv3&0mc$I"$"GD !PJlڮKL (fiȭT*]f4jSm?.K!nMR%|#]\m*kݢ֑omo۪ʴZ_Ҁ^ ls}yj 8/r޴Y5M6+H)@ j!CxO9D(fk<@ HxFRBO\Ί2[=OEzݼ5V&<_^Hpft2 hcl&]xgŤS!ϖZC/O~JG=i? W'P]vnmiY 0'_(}<(Z^)e뺦i9%f^]]Ƙ뺦^rƘz꧟~Rt1+)(;a)I|޶m4|)wa";Uj;BÀ4191tqُE)ЩREQ8"藦)g=֩:YJ{$(gZLWD\8dq5,mzUoŒx(Dif[E m6alתTnmyE&\ݗ_p$5Z|~:sD\,UUm6"Q/j)npȬ(,Y5{czs΃fYuY܀s24' L)!Zjլq& 86iڶm|?|sqn?woNy1F?uOLtp DI9'|i!O3gKhck_{a&ANR"i<k `;?pQs*ޅ "|?Sh#9q,!"XeiH (0WBJ$fn4Mky.͍l潯zݚBfiZ|^r!MfYgq6_嬜,X'Ie;<3MwڮﺾΡ@uy"n众r> @b OC}JrDub(FD$I.Mb2Dʲ\J])E׵iV",˸]D5][۵,'tMTqY|]#aswo*=]wͶWwv?W_Zf$n^Xw]ٮ7qeLOJ)mt#@uvM۰%d{ 3aᣃ_XwGp81gZM._s`W4]! 8m&RpvȲ1ޮH Ũj\BV M6h^*n9D"˲pTWcX+ ;p23TcN swPĠE"&fn& k=Q҈Rʪ AJ\&u)QdYDE(ֹE4yl:kRczNRSrNLs'Dajɒ>wJ)$Է7(լbVR IrcxDRB6A1Mu ԛ&-gʠ̸B*K9D w'$DQtپ uΑYrN gZ%ɖ/bZ"_cvm+Y *C ( x8! GDpQb|&&N%W>G}g'" u-//YS_95{PzD^^Y4fb,벬IOZ|(bn9y"U4Mּ|$I2(,/J%DZRsO!i"Vh1FJW <CD#ﵖ5ml닷_>OΚVIע@Yƈw$|:"aХ!d9H*qO8S) w~;/΄o_OŬ O|Ү&g0xLja Sqa"7N>j4A8gof&0ϵen+;,D@H4RZ )w/|\.iUQUzb6RroڮkZ{}sX,?ˣ1˵ȷ)eԱ~  rjeRx~7v0ԅ{"WvH@h RIhA>(4Ϙ{BIZkA{c[뀻q*uZz$JNs$#F(ӷMu2]42!Gr^ѷCHc?}lZ7+YEu[W?|*vm+\`hHNL'IRUIIy4[(% zo9~=|R2'p΃71KDg9")Ոdκs=K)N IH9*TEaD؏)v4וּWc{%?b>iRˏ|cY?AGɵja꽘>unE`6ihr@xO5|OHK-@B%BIP#&U2(N*o޾ZyID$g^ ]wu @UUmr,3v6Ƥil.uc筳8,8Ypu{?aVg=.S3DƢQ[s*+J$@$IRT* p(H7쇃$l6R߾77UU1F ȓm隺U:cjThq}ۮ+T]ױV[oח2 )4NRՁ)Zo7o3?4M% kmDn6+֫ll(R$ܐMS&01ݝ-< A8 NQiDsN*"m۪nEQu Bj˲,˒; ZkbD G!R2)qr_߷Nj*~O,?N {xpx\%xRB NTJ'vD^.ul۶EDl6SJ=>>><+. I4B4MRy e8H]bG˃7)#`ve9 AveNSBtcZ'UUB@x[o,xjVLZ 9L_׭#f3hJTc5|dL$I״]Z"g'-i:Y}wIޮ$M;< ciGeYQDihq,߉!%טڳD@"_}%>POEtc DODЃ@EiGf1Fy8 )$iMJfe-{ ,u]UUR&:I,($0ӅR"Gĥ1x6 EE]8л3E[оz:R c1 Z磂ȯHtR53{HIŲFjq8뽿/۶+cڡHB[^׵3 tf$9%NdQDg"vB{(LJu) ^i 5JSc 1s @B|D 4BZcL0)19眳!q<ɕRigD=J!xF/X0r b-^Xal+`O'm=yIL{*^gJҗLs3yZ<9g,h E񯎾bP1z8 c?4- II.e*c! 4t]IG)RVEDDKDJ)RW0R2sabˡ~ :s nFbzdހ8|ڢ(sl;ѻ\!hRZZ jN[v]UUB<ê"ʹNI (8Ri֪B9@(sBlƁˋtY޲_,XVEYԕ׶=Y[R q^[.\UUU=>>(Nւ1DĶc@1Xyvuu5ϳt$( TuU5mݘ{i2"$Qi"P!@s}k]emW6+J Cle^l/y9³H>Ojw##xp8WG:䖍r[ 0>&WՓj8X'=qѸf_fp{E" $PJ ,!)$H\-L$X0s5[MZDrTR+fs*chHCs2Ig|_gB\{&STeN<}ʚ_h(ԬPSɴ8ڞȅ>}~GlR0*b*_ ? `(':I)& wH9ѱyYE1I{ι#mzQ9Kk]E3U ս!@"{4lMjc sC$h|ah=`f#-b8bݍ#{e  b sub;@2:Q9gi|d.T$ LR㚜Ʒˋ$IPL8]4Y,-RyTvν}62fysb|@"s)eeܺx삕ȐmIi{ 6M_-8+ hR,Jk~ /lpgk6HvYGę$I5gŋ-GaM#[穗zRa GN𯮞o>R8|bPY?}vПs:xp86}aTG'3 q\:I%5zdTEdi؉ndzq:MRhuel6+2$Dc VJ%c7$OS![QIdYq^fǪ =GŌ+e 1I;qޓ!;vFQJ)(4KA$-4MB窪=Qe :f&fSm<ϓT:>$LAQ)fi;)eߴι꺞1i(;!erC?Rx@/Ip:JNhÑ{{zHO!̇eۡ=% @Ȇ#ð* pxޣwiy"۷vv;ʲg%ι4/_`88v{E3MoIX@9{X DbSX.9˲ޣ'vP:ru]5by!f<*7,IE$mޮ|Rv86XqxˆYD2km[zbQD,Y^6P8$`]㳦< 5FJ jZI){ksbyI=[WuSm@(YQ:|۶{(sޒlg.7-AJ0=ʁkĵE 1D!ϿCy80lֻF4loA8Er>I)= u}߃x@ir환4o0^HvQ&O}cnzn,oI|NcD=rH{ʴ8:}^ &\{cc(<# iuyZ!{FcTَU7x$mXm rg{ ڗKUڇXQ!Dgzk3Qh@B]z|Du}oۺ6]':B""yzޯl{-|6G$Je `~c(Yu-Yʲl>Kq1qiUU[5w1L%$gg&H)X\.&l6ڋ2R(ofޚ@X/8 #2O=p@Pp  e/z h+Kg2?'K'T/>Ҏ.x Վ.8%*仲s G.]"2`;X^_v5̓Bι+1:8V [̓9&.l\!$ 8W9Qj8B!PpoQHʵ ӱ)Zڲ} b5;\Pi;:ZPq3xh<~w v'v7JiH],˲$%@̺*Q!CpCU5VJ)Tk F}||LY{k{)qJqO^/_iz 9n( SPϩ";>LcӬi }m} ) H}N>$ҡ,ɔ=uЂ9Ʉu3#&jvyLg2=]O|XN lx)#I̔'COn;x1ƏrDpuL "hF!8$ zXC ]q]Ɩs0lc %p#4= 1vϮTġA Is0DlL'Ď*VCZIĨ]۶_xWb^EuƘޘcP?VU <ܼ!nZn+5iiggRh 8R)n-"^__/˴M}~xuSy$Ǫ5"J$qZ#AUJJ,<9̟eDARru? dZ5M%$2Jh""նOʲ\,Y9gNcD4k$ kS2dlǐ&,ɘj>lk3+S3'.qV vp'A oo~h_NJԩ'wl})s>5HaO>`4^ 괟@_:~OgOU{c@9qb2wm<.AQJ);< MTʪ_"Bv[tٮg3MS"2&qAgr*ɱų5y)ޣ_"Q/o Z)e0BM B09Y]S >JCZT1A!"4..˲4p??(GVY ]gqDbc&c?WMt~ƥ9j5\eii֌%UVG!q>g@:ˁՕi{ə_R}Qk=+J6>J$Qn>Z*MmkLD.17(R$};ߗscc'Q41B4Sʊ=MY tp6])|Ɂ]lANg[SRXwx 'fNp6v0xSs=x2&_<(Ro IG`o 2>9ogfo<񜲁gg~z`s10 7,9~]ZK/ E6 'occOґ=WW1E 42o8'PJZv*׍.T^5Mydo,"ZꭵB";B2m*0xDagvNak&ubZ?~9g4Uh Ck&x笱( o1 ._#n.l6u]Ø͝...8[Ӷ-JeY&dU%?g:MA ;2k%ﺲ,;UU)!DDjJ&i*$UB=EH}C,!A" Y3-B()Y3@M&t4Zqx jX }^p Zk"2ps6EUk¯x>>Wu0Nש塪0glx^_W>`E$M=5gGByjMI 4v'SVJ>pp}ygO3oS!{Spw:<9gl`ƚ3Vv ؏B)@o덧4:ckaEGĠ;ȹ]8BtAyZ,KC`}@G೔F's OpmA'/q`~DT c%}0"l19XRЕ/8C8k;J!Fd'#dJ)TRJNCnň˟0%w|Vb4#"yXG0B̯H34ρ-i ȚQC,гl68 a<>2όRJ%d]m*)߽ySƜ5}2A:IDuMc۶m]ۊ+IuDJJ+8jHc:4"EUUu]VsnZGA/& "HlDnڶly9(imRYcRPDZ}/9^i T8{2;fGxBc`$.UJU<#5 C*k8ޥgz(v^=/8:~Sz8 .)A0`lD@ i% Ruvh,9`hUU=< h%cΓN5DƔܻ_כȂ;:xb*׌#x0O"O)`WHhZCqI ƨAXMs;8VЈg0,QWdPÞO5D7!jGW;HsŠJ0:C}oBCQl. SoMuQ"Hc ٻݬˌ\Cby*MgfHiH Lsf W}luI˲m٬tNҶ1M뺮Rټ(b>cK3])l5]$ɬK1p_ÂqSᾳׯ^՗]lmi矵WWWMk*%Tv]4BsZHア$/1N>0K@R..~ qb>m;BFVNN3) '*vF M,m(>vt6~A<>A%.2\NgDi|qDp= {Ї."ǞVh;Dq㇁ņ-/?HS{ԵM#qv7W>i2[!w@ z cqlB 5 e(B*Myk-B%yﻶzv9uN&| "9pơFhM׆Në;Jz_M:v;_s^8s~>>q$|Pxx?cʸaݓ@]81GDd󆝈$0$C|Ľ콅yK*|w0M2& k0" "F!=k!fq!Jo8<  ^zﻮocڎf'$ iJ%8 TirQ)U%7R9纺dE.zH^%O֢( W-Q,d(~p8Z+Z.޽˖᦬}Sw!DmIsY|yq1̈́L֙7MӠ(v̗|SW5[Rs5R2z]kVh늜fI {o݈!ơ6\]]$iNDeTbJ5F%M BfejO~;xn)Xo)~nn34=rQ -;nLBt|?rOS"tbǧ:"8OswT͙xzRJ8N!$ρ!qTdynѩp0NOb'N$Pu$5\bw拠2@Cs\ 2KGDf` U)ڝӹYJ)qPԀapËEAX.Ju;<[V`E^UUs>IkZD̲L(1IFa1 fPpMk|7Pz9J၄*0uTM&q7*7 ,gEի<۶ E۶͆;lf[kT,v6dzuH'u]?>9R9襞4C|P(C<˲3lƇ;fPo1m;TH6*^$vPYt}X` jqȴ"((Di+1lnVm 猷.I뮯Q'22ZbNyl64@}o=q^w[캎9mۮڶu!#(IUMt#\*Ig.jJozX)9̙A sB`v|̟&O0Ȼ8F xq^%Iu~:@w|;r"y: S GKgr6 0˙2qC|0D S<3;tSk{f?rx Bi꽗%.8j>$#"'8ND57BCe "t[A;gpD0xwY*8$XqF~"br3x< F͆ %R( 5#붪j='?gY9MPoZnC!ހ"ϵf^=v]w}qݰw*_*87m+QpPW7*r]߿?n6jXKy}V5U~FݽHX.]ol6: z\ {XereAJ388&+rNtH8Xi>bx_yy=[k`D8)٢hgCcO;{J7za}TA3x'+NJ6as^ '8bO#t/,^~M3D +\cN?S?? )s35xODn 9 b࿔= +_>>>rvJerIzO{ =n>[ O$IȘ P34>?Ӷ3 =Ї)!DE@=᎑{?ڕ|wVh'""%"n|OD! iM{=Bv}q9!cgGCLDD},\!hFPO@=mUCJN\ LRrݱRc4 wȁBrX C:=8,Ey}}]%?6MsPs 晤lUfl^|jl+nFsѠYgTZDRJz6樂8\.SUS[yQdJcJvΓDfvmZ)YT4jUUU7cVHL>B, Rpy9IL^B1|5~w=K(K̴?%#]n<=a= pQ,Oxd$(NE0fMx$4Sikjr d{^ nX\'I|H1S=uFDN :?y= q2$~wH#Ҵ߇ 2*K)&ӆnqH*5i`ʵScpBE󖈘`Q!8VBtXcln9A"j9VJucmJ쒪 Ų\z"}&Ҁn~sٲE,p;箮8i~,y_zan[t&l$˘Z kͦjhl|lV*(iaX3q/.;}1J:&Hc vyAv4susu61l&wN^9;zIGD<&ǛɿrT^#CE+`qA9s !WꆏU-&a8jyOu'@Dr43yH(NRb)C3%"$a* !e[VͶbʗmRAH)J M5m8gkZkںaj /YH{,$IeYEmȁN"3!UhH$uI}\V@ _ݧۻ<yִR}Ӿ~z6c$IRm45zϸ<9)w}edw$C;ƧTWȟai8ǻ(,y4(V9(g3bR$Q,?1{{n3M_:Fv:x 'iѱqp ,1@('NXRt${Wb(sJUEIX/&xo< 玟ڹ [at7rgwA? W`) Jk% YI4fBd5ff WNjGr@(m B=Q!2}?vyߩL~>A/]+N R{S[Ta;|~OGh~x{Zײ\ =ИrpSlj8\ND9еw7ޚvnpl7ý1!Jd^j2!< Q;[' 0@FN8,}h8h: *8T_Ѯ*xc_z118"d`{/O"ǀ(CKpbp|V)"` >I y60K...޼~}qq!7aZ6zHY^ ئ0B&IBĺYC(Ҍ9G#Ԭi!c`dkn۶m{/} TZ$da6M3Ͷ}}yy9+Dd! )NӶ7g+H*%$Qr6KӔzkk_%WT)"MXK)jS:$9AJaLbyUSWZyT aȃr&]H l6VR-x5r!r5ϡ8DzMh3uc!91 sYHH̤:3p揚<^Lt=N~C,rP̟SDGYjp*>0{\0{HkƇIJ9J;)aP~oY<鼎Z\o),K7ޡ`L8,*n\H~Q$ |h@ѱ'*#rPƣ*V6' ;}[ fg0qqp@8Np!-R5a'(aT̡ؗ(YQ'<Ա"#w `\....Di*z֛mR`^[U]o6*[ |% )jCsEe0۷iI伒ZYe,=T^k=_,ڦ_׶7$A.2PPot䙕zB̔F%;gھIizkTRJ@!7Sܥv.D!#]I)Rٹ>I]8a%(Ś26 kc.Q`ܚZE/Κ,,yVk搰9(8O9pV3!bÍp \G~2\.Nq/a79Ex')s.C;`ޓ_G<ZPHPj8?{4aO˚8SIgQ1LWl`r;@݌]N;@Eu Q8N{;xB_9  wbU:YG1d g`/[ zlB 5J9o) e$kel۶u_R HbZeyuuU@ιjY=6U-4-k4ze:ыb\ !^?>u:U:xOӴ("͔TܷVCOgb<{IXksT{BlZ( )crw7n62/ʢDI bvھB;r"};XVc$%sNFD\XeYxԸ[sX1ƀ5 ]s131%>x!Pz̈́؜yF"G)OT9F8Ga(΃J7=j'i}430YM C-B3 fGq'o$Nz pB OJ?S"OBЧL3Sz~naߘ 7> F#WXzȍ]ehxE"dL;aGi!Eh_d`ZӵAa3Q_ [( ":nmo4l̓uv0Mnr}}}uueR =?/Ҍ[KycSUUi R'<ꫯ]޶m Dsҹ!, B꺮["M{ ,3RʛkXiX,..nMFRY iEQp6 tDifᎁZ,刈e|3qbV>g-Q-rV9F0Q?`=.*YuA2Mkz׵B¹5>I"I9"KH`+jH} ߬9ךL V]~OGT˔H~+rnH'Bwz Ķ?8%)5|l8p.z* LI.}r]_#hw?Q|0t:dfo/pOr|S򋐆)SB8ӊ(G/ƨ@vX7EU\pIth"yyIX>R];9O| kP w U=O=ϟ3~ HO'$] e=3qS"`hT$BB(?()OyRPcԚFFDƸf!޸"b@DG`]"C D%eYEf|ukmoz ($f52u4}W_w3oB ndV7˓Rf:IӜNbQΔRml6\1/z(Rcj\o\߼}{ssJΑ>/Kb^'YW,lnMvKuXBu$]ݰ/ n$ zX,@Jkb!xي B Pj5CZADZ:Q>2#M( ~0a<wql6 0pgfPs^ X\HCvfDAde 9'1,Uxx:9v&=c8wq:ył +5,[ٿ   1.&u{DZ&m9?~\, FR3}]=oZk4 |]Pn6܃39rQ.v-f3z\ul Ï?UUR... 3n~^Bl1hiY0ƘvlȔb6-y^^\]^^dYy^YVHaP';)Ľϼlf7 ^HYs/B֦J)R!'`4MV!O c*vby̾uv<_^r:ȱO2Lz:)O\iUJu],Ieg#'sP78ѐ:@&'mJD<6f Uqā$u}X)D=/hK9erto$g=xt<q|0S1=8uo'tD'̍cT+1=uid?pܽ6YQHˣ&EË:Xr׳p rXw7@~m٠Y`ۊazBAwv1k9#F; M圈H3={l(WR1ԹfHVO*IurνM1!{To>tw[7բI@)B)5RTnY$IۡX9e#e"mˁXX^^$M4UzdxN P X8#F$=sNβLk4 CּB6,`9\avbX>U _Il'SGN05dM㹳I~xy?SylΗ`!XXmxh1'gu8p Gk !Of:&.7"qK;H ɧ-`Obh\C# *`aun?B)>&J˱6ba {904 !"Cľok[!߀@ftR$K=wy_~YŇfîiRT,ɐ$^9 /X^\m㇟B"ʹIQa -,6x-ŷգrVDG>cLP,ٌ쐳c֫LJV?uNAU؉2339}?<,gyg$yJ)Ue\^.˲ ,U25ڏИp(IFtp'b,|#, vh G2V.I'5y}Z2p>Hh\4EQ{₈m:k9SL,KUuU7m'훷oߢ?j 9+i֝1*MeY8{eYܞYByZNӾYN4M2iWRJxf:v4CNO@e$Hbtֿ>;O}=Nപ>VKQyqS hd(| r=OL@<18+O:6{hGpA(XlX!"x@>6Ə^f0`h#Y K9? D 0@J @ևpߵZiأ;1ta3[g\E$],_~ׯ?}OO޹,$M"+E{6M}///mucRj:Q 3 .I|\UU匕I"Ⱦ]9, {/4B )Hi]3F_m𰺻WNTk-RdIov\x٪_,:KiNhf9`(ɕʃe1+DQETSzkXw>vy餔<ܩ"A,Y;`bwKeP 8KY!X@|f1=4$?Z٠yXbů˜\o*:%d'U}z-I'urvӁ=8:Cw i8Ȃc, )$Bζmkʓkv^Vz`*%RIMgC i( :U2p1J)$Ts|stwYd^#b=0"Sǚ󡸂/:nWwrA8l {]/qc{&hy;rg"}} bk xw "2H{xg {4G=p;h^Wȃ(Ccl/;XKrܗ}ihGpadiFuΑcr0#jSH(ȳBHo;c?l`rsRJVZkI\]]]]]i!?XX{$aơ(A`eٛ?r^?s&uzVJeNC )HD(Bx0Ɂڰi9y{V)%%;krwULRYvDŽjd4͔R(E$zkvsߖ=&BIw\͑N||dů"}eY. nFP93 (Nc08^EfI u oo:GG۞#OtP퉾a{ xRLɧ;Ů$"=q5q`qb2:b4{!Nᓬcۏ#“d=qWR iH2MDkborh(.y<èb2!IDIcr(v!B@(:`~MD) <ÊWJ%BSEl4J(V)Bl6"Y ǘ 8~\:^4 dP .k;btfa$ќc9?{h{K{wq!}ΞSyG+ACQ`ЈADio;^OzlLl]31%D}|A}ţ3Exφ-"@!;\wĴ{Pa_""2Q 1'.n P"R#bl S$T[)'ΓriCD7o\^^~~( ۛo7Zǻ;&2DDr\^\pz~n6uH0+ SY>@Bqj`e0{Y[Y~ތ=@8cDH=ZSЏ0jχt/7x$viDWXCڳ'/uD@FqWyp_cc7$)4"dgaiNycW닢ޥܯ/>~xxx`$ۛm4Ndb53.IX,84üdPy~yy뺩{Jwww/rw}AJ)rhz]|>l6[VB4ϭ-.fe$۶9=Vlp7hp ʢ(R ٙ6̹f4MݶYQp~5<'a)4B%0+Y< AJ.W!=8W5<6Ngb2f'e*6BW4@^rИ F$sO>MS'sͣ%Sx" m&>N]~G?< ;o5c0.Xk{ɯp!N:FR( QDI$`yPhk'!-$c])iCyTnı@QҦgbG[|]0VN%qa0 #j CEb6}?=;pmX,yEQ:R }.1{ ,Ylۏ]iy&-o~K_w]__}1OR1Iټ UQzO7YI}oLv)f]ycR& PY넒\ZE[fxZksO|>"T4H9Ͳ,I(]R&I%q\ab10!1BRPJr RuЗЎ0Am˺Fqcv?'åq1p \\J܋$\;sOp\bRqOB/Կq3Xp>_O*S>1dhv0ı{iXĔV֯1Rˁxlc_q'vD_}~8{;vBEx;=b!1to]D M%KƸ7`! mBpRJBXiӆS Rai/~!k-xb1疎9)e^B ]\?ZNGs2 U:fVggE)cM2ee|0sN 쩟=Ggɫ;=xr-`ϡx_xBI(?r[! -<.kmw3pܥS"04`6]p1&MD@b7w@ށwԁ+w,ErEfoP\&D Pwv4M sfwZKFi}uuUg6}M|>fZHkm]MtB}͛7]gTJO{{8ct^_.r|m$>}u0eYvZn|} "֪m[( ~RR;+m$ID m) Q($ 56D8msNIJܡW1Ͱ941dγ*CPr /~UU9+nR]לͨ>kSS_Zg@Ɣ,ǒ6$<&Wpps=tn]1>xS>0xc}4R/gmr#Xc,Г!K%0uo*٩`Tս-)I@l]j evJB "Ou<@z"}SH(OnNΙщŮqWJ]Z˲,Rm[5"^__Vzgbe4www ]۴u*..qu]wֻ/1͆dι,~$ZD2M1v}u]`Qh9?l`^JBO` x\|7/\t|6 +<9?yS{BfC}ҍ2mr|=NNy{&uٟ?ϣ\Xȩj~v® #;.[OҟD@sc%XN;0 5Mpg{azݩ4Q(|?pIE(mߵ}X\|WUUl6,t{ge~a6gݻbL1/ʋooo{J(fU4?!o۷ۇ޾}?Z 9SX2vz\lO> 1u]uYYh뺮 [m.KWB`6^.5}sœ4/Rhՙ>/̭՞\TIpe.PFKi(UJU[D-μ{`c\}ya / >^rZv|9rvFrZ$8a<~ I bl3ay>xUX- ˮ{J>>wظě0 0dj'5>?Ct;X0p9xpcH.D<ꍧ3>8F4!5gQsz ǢdhY $!Hq&-"8T"b'=!Q($S A!Sl]c|x:FD PL֛YB0=̟4QOuf;`\#h.9/Z{n.%K@_\\cBzxO?ZLݷ///w꺶ֵm*Mt&Zcgˋߗf[\cժ뺋/"=ֺ4Mo޾p_,.닛W}˛o֛6MӶ˲$D|Z{aERo9/Goun[(em]UEn6*Qy>{m^E9tvNbYr6oF!\T~tr$ӿ^o޼{7ͪy-RsґB B*I(b_ Q; xB!|kgZ $xB) MÙKBbXZn_l29uHﭵul˫8APF TynYo۶rrȰA< HPPlVp!.x8F3^ő-^LON:~0L> 6r)G8\4$ Ku(PWJ}rC(y'"1mpУd2aQ%$~m0rB" = 8p Qk E}\1FQ tGCq|k̲lXEsTf2s/ o{}}4? ,㦁~Z]]]}o߿ymRmE<ӟ=nnn[&躎Z6J)mg]:1րj1*YVն3|>/af2`=+a>w]0XCBB.X2[*NM8~m8G=S.:r/ڇq^xqq<}ӑL.PBr_SRJ-wP-;͌cc`c 0v/BI/ݐ GZ?$Rē7y{;~A_3tZ[$Zr%{5s£z~8T .s,Dqc ou@zaw[("p <'oT8D%Sߓ$AA.0*X>tb*Ͳ짟~K8͸麇 J#xU ,뚃UU!|>rnǶ"Ewwy{xxX,_~OI|?~TJ1F۷oǏ7MSm2n[XY%Iȷm]̋V{g岪*}RJg%MӶm350s9\%YX-,ckߵy'iZmZ(W2M-57R&HstTFkK:z86' s\DXn PJw6Ϸ'Cs m2_8=Zk>Ɂ/*3ye;ߘ_UÔB,S'}?XOhnrLS ;f)^ z$`=@ݎAS'zIb0KϡhM 3crisXB}* cl`̭ADbJ c!!dZ? Đ_RsU^^6BHu7okyoիW_|EZ>|oɓOdeO?|7 3iǟ 8o7ۛׯ޾}l6n~bt=8V#u]7MSvzڙ!*g%iEDOV$Iʲ*,r"1{l8?:}{'4H6ܨEBr9H{4s"rT4 J)`_m;>i#OIzoO%`*.F:]8"?t8JSj>u0a !nM$\Hp%ţeFw8 8\.癓#9ûd+6`~~0@!6!rw@, o('I͛7Y}~B\]]- J[ ~yq͛|ӧO>V+Drեfݢ2˝s*M(?]}ۿ+˒>}L qwwNhz||d<-޽{OOL%4ep[% I!7mT,,Uu}}eYl6-'I1v}e1+eYwN2r>ca6u}]UU$y9wS~~Aϱ|" Gkeq]W8w k`Y%2M484dwVL&@JX3=͸G(V*18GIHW9IoR@@$4dۭ'+]~K "4jO  -_ذFG2@ 5&CCΏB+0&/XC>t=&ňhH@1Vj%7f777iÏ ׺7 i% ^yQ}v>o6OW^UU?azd#cLׯs}Z^^,KċxǏnxBx/9/X/# UxG$>.f3hXj^/mF;\c{<Ҧi ;17Y[;Im;+)ȓ^vR~Ծ!竧I @| Dg#xF4Dyj +h1Wx70 v>y#Ѽ&(!_z4eLy(s2;= Mpd ғGt=8ێ?Bc]E#ـ"@<@eחy>Mӛ<ϛm~X1۳Lqgβj>7}ڬgeYLÇ+Dtuu}yyio 6XY"b!R?|Q)%#ֺio®SY{6M|UJpFNAv->kXLHgsU Mr ȷ Z'ulL¼qm|a(ûXX鲞fX ` ɿp'DGwN3gM9^o|ߌ>z>9)ǟ ONJmzԲ)-h:*jh!C|0Z z xO~TekB;ޓ*$r_&p>h*5m@]7qt-nDe?LQb>r0ײ, L#tF[nյI$,˛Ǐl#)eW7\.q~\^]6mnsqqqyy\.7͟vpCM۶ֻ4GfeX,Y]\\p1"&Jm{ͻ7oV#|nwww pΧOy!( 䑲,3mgݼڶvrIDx bL-˒$.Z Wgۦo{IT% O{R%6bUt g8 +'Ƈ1 9z\&In8YS8 ⎛S1r.z5 ^Ł{ sgT_q{"9L^ t86<\v;ÿ0<7y@`(%=9 %;5O" #iphE @XgFurY2 r`=b9ǻ3РXjp$|TxP~ e!4q+s 7@@< [J ),\U!% !B!51_}"~gDo,M˲d9M|V*AH|8o6ju}}_ɲo%r΁GLW_yO~]oqMeyk|5ժ, "_mR˘$I|#JUݻ_J9|` 4BH%Jӻ׊@9ّp2N9׫<_oY.Ľ(_'ډqc&?/e\rz-tw S@wpH?Bf 䋀{7+wOD=NMW&"w76!z ?iM:4JbG߹y׬S_~4zF|n%Rp{T򫯾ᆱۼ,cO}^aRJJP޿5I#i$YU-EfÈcwd9]5nP x13wKf$+ʜFAħ^s)1[:I%u]"Tƍ)Lcz,kJ 說ͦnmYYm"AWK!nS5fm3id]]3]$b2&_)lw9X/`9| az[EjjPW,9q>~Ç?nY]s̽ Hy>SǚSaMXmmƕD{)Ǖm} o=`mrɔ WC5Ǝ J \\+%3L\i(l41_D6 Ff ҞɁBo 2`0'N, [LSLE'0$@- 'lo}3]փuHD8Աq2aHw5}M%>|8f}D1JJUSo/|߷mOU]"j?VUOO]xu<?w!DyN wxxv{:޼z(M* +AXTX*pVޫESSTZȐ<>j)$nW4)Bq9뢰r:#ꪪtEL%S:BGzHOxlp&"YQ!FvN&4 o!@ʛmcnmT츻S?pSn.*Ij(JJhp>R¶*%9jI )/~BWO@`X00oHL0PCV 0+ayeZyk1b0"(j?!Jm((26/$̋mi甊01L`|MMѭ$uE*)ŴP-U>~("TuL]P޽Spp<y{My?_o[]Ÿ'z>~xwwh9F'uzv=o޼,?~Tt@软 zv΁'_I5  -"ΛifJ-0|j rܽWBl:3u]sr`U]{_׍]J2*Qmhp5=ZeH^ٟ a܇> >w=<<@5:$ D.|۶ *<=>>=7+Em[sm6񨠫,9 Br=H[U 8<+m {0Gu:IS΋5^K_ylB,H?x/緉M!"@`Tp+ %NL[HqKJa|YQ&[_%Ȣ1HK!Tu}m{; _~v۷o۶ 42E???<<_zEDxsTՇp-9uo+MDw}Çwoe4v:T;"ru GtDnmUOn9 iJTwZ5M4=v}fp(޹n@Mx_*WG? VGE3*Fөn }Zٱi"`j2R]כMs8WGejU.QMr`QŲYf50ˠ~sVPӊSob~d6VNO]pOb.x|kPm.*y ÍyE&WAr!}Q) 2%?jyk<V㎃`loHx(#)tԱ^QK2H/ @Mm{k=R~fIB MUOӫW/_x]ջNc@_߾}?O?w?v_~w>$>l۷mOe?ʳ50X|*s舓j'j "ի?ϻogfJzӪ|*|~vi6zQyèlw@aKEKnJpFqgK"EcZŐC/HnT|֚Ж3o^J\ v;Y-Kn,&XxTt2;lSb9E_ K.3/PBLJ)q)直[|{bp$$B%Ӫ#r+#"")R]bL LREs]͚#[#BED3]έk6EYm[um7ۍn|mr%7ÃFFYv0[OÇ~~嗿!Nڪ0uw/A=n6Www=^B"pl6IJznov.Elz4)&FW^Nu۾{nHci6-۷lV<7LS37yFD碴[@/r"<+j+r9BȑwGҕ>F4 7LYhN)Ma:7Ehr1ʮ)ҮK{O^2Wզ؈Yv fRbѫYGmj(:"bVt>B{ZofwSاAnK'AѕhjJ|nU.VJ^hL! E2*(0M4uDpZ!!&dԲTz}2Dz`T. 1, (aC*zBZHK@_uOnU&3lwwvpÛ7oݩV@zA-}8%VfCU c9rIjy8M_d3RQ^"QOUDE2}ߕ!OO}G*/jGװsp?M=C$KRj2VZ-Y˖]~I4F)vEN(`B hji.$Ȉ3ZRzȸp0#Z`xZ3Bj{r2*)==%Ŕy?2""Ի];TUS׵ Cpν~9GM A*;@զ~wOxvŔDmo^vQw]UU_K=e?km=RUU@ p<XѢWz_>-EL4&>l6ּ6)bxl6mG.zBMdei>p"sHXdZJOe0=bkƞ>3Mi[<~] nn0Բ D޷v~J;&@zM.ӑ(YziMӜ$џzR5yOhU_R~Ҷr6UiN9ӯJ ٢g~rS"u+p&=l>I0R=? Wd, il;C.W!#1!yYbaJ[*S*箵tT߾:=}mQp\G~+NfU߫f9߿?gD?fCfV$۷ozru·ou}8uU4 8J\L yj:נ@٦@r75D߫}x4Jtx=Uld\(ۥ6Sr֌i:*ڜkhnU >E+nv~X9,D0Ͼitu!"f<&2b0)Rű 1YD 0Ŏz^H |JV 䶫K:X!x+1^iTt:)s$"Yf7O?BǺ?3:!twwwo߾!?#::w_?>}+\v;\܇po6U啢sZ,|"?&j-XۭVTLm v@uWH>G10ƬQp1& ӭP:v$s0H2bxue24 "*`C' "|UcA;tst|ZҘVeVJ'J 4~Ԋ&)BrvUsl6 Mi6Ε%>lFf] ^W{5, "fw5\i8Jf $ɷP  7$7=-] kp XykYa`+טFgS7”c>;{Gﶻv ]Sun *$חKv8-\lKORUe.>A$xXo8^J%jmR?:ŊWsPC I %Hڭ?BB!;WJURlraJcgakgv", ډHEN>L.ӑjj>dHFbM{-{8wʧ( ;Ї;Ew駟m4w!c{nW^uO{&)>]y$GtmםU~7Mضm׺ׯ_7n%nwux8(ӖTUU׵ιnwU۶}ߓX}_{չ}vD"TN5.(U=~]ۍtVzJUF"}'r#U]2'O+?$4ȒC hW95̇.yCPzW)"3("<<a!~Ҷ$|;/I͝`gv9~PdPMUWdRcQz\pm4u{ aZNfA#ȡ$F2,4υbX8S]D՗paÂTc6е3wۦfɡ뙙^x$B8i~0!i~>M+n?QqhWΫQm!޽=OVùS/ j4A=$,n6?_o6-k6 m6^S;W;W׵N`&cɑ:mŢxrtUi&^뺮Ǔ"ԫxYNGK-v 2}VZDfs0Xki聓&pZ&˲ywtҵrQjd9Χ"AU3 ),m_ݹ`tCCuX3P׃#7vԳ9y8$fBdR/119ًCt5v^/D !i2GbTez(/: sN7pja,`$hk!g5y腤}PA,ZDX Qj׸XOܚx<:_WUfZ&df'j}̾޼yCVF:}whv>JS6{4>|8<<޽{m6?.:ݻw?oߝ}Q=[愮ܵ͛7Ï_2,mjӼ}x<72#\HmfbvkV[zW^{8 a[תH::9y r1*s-Zd;2hPűWؐ)E'钥a9N6;3-ŶE>|p<߼yl4}nB1CEui5 cU6u{V[ȯZXk,cղ%Qi [G.~>< ^Ǘ]iDXu%勷E\6=2hWrJv\[00^i%E[:e a"c1# 3?|wT/"Iks6۷}sU sQ}=P YGDʂիWw_ǶmEvu]Nj^vfs<qcUכ65m[ ]]U @UU;x|x:wHU Bi5+;75kr@@Fo8tHD@і ;DR84!:kK}B$峞6+oS+򦛩jUI#{=e2#[ѓ٫'"HDNsUV2ҕ;JU?~ 'Te8wX5ׯA݌D*7U  FkTy_U8%zC&S3:WA9J-j:tT%qYR gzLhΏb?C!3,>״UշvG榮k"P?JdQm6-*]_0!jw '9>y*`/_2_*/8;(mÒ!#(i֥s _wPN 2AӍpI/T1`< 2CT3<ߘB)ߨELVb -ιp;WB~xAk7oހ;Tu[zM޻n'z !ǎCS~9=g̈W?f%RnWŰٞp;0DD' ԪrT[OjVE%&."iT(qT%oLwx'0ɣ] 框 )RTK`IrAijXۋ s X4`XgB6-,;]>w8LE>x_ZMc4뤪Ϫ,YZ&MW`'N>Y]6sk Y: CSČ3lxB$_zF)F_K0۾u[avfR 7w 1Rz`)nͲYQHkҐWD8Q_өUod_WpT,Dl~?yAA?x ~;өׯ_{r?~$@$w<z:>|?mwyRpTwv?~ܧ:q#Su]}A "DDB`*3B*eJ!R&9pU@DTyhMA9pBOD7b\r=Ֆ&2TdK !x&.wJ=֬7T͆  Nԅ 8fy.UWQ5=X|LM*奟_.pw7mI0SV]QIYik+p!k9`.2DV$nb qY,Bm=p<7G>V,$uXw)A5QfSiϭbGP\f}|뺪9BBc~l,wݛ7oN.0?>>HUUrb/G6hv')0V*CAB ! uvtU[ARY.R"rRz%Ƙ7S(*@GqD$ hZaEɌh;}Օ/'!AupA! KH3-\RL˝#[ލV0'b6`V,Qy~1b~v=_}ano/ol=Od͞ޏ}=HyEUjyPfh"Jy^[&[ @heNr/^@G2HzuR @@P'oN9Zե:-*B|n{|||xxQUU՟'-0kMڬۙ'"/],}{>Q㫾Oh|yЧNt i[}C|*b~ ?xG`꒧ϚMY?zsi6t'"HcN!Cġ]"9KƙyK|=& ©=2FCtfZMtxq&X`nϜL!.{0Nj406k"kfuk>OмڟqrKR*ǘ@fmzj7͔n0u6} Cqv%$@D-ZHFkt y @l΢.@\ЃpOYiU<4I9dkDD`9G!$owwsέ׆}u]{K++! ܿ~g"Ћ!r!@ҵo߼{Ç>S#pwx=1oA_Wx<ĕ;ljFғo߾{1 ~[U|Jnm ܉H@M<"Hz-Ac$ [VB"G-#r3UZJP<ɠ$`]vyʈ]w".9MN%lTPG: ! bDƴYT02p.+/$Ri1 %6+꺮CUUmwC`-ED$Bk0ёLۆr ^Dڞx ~PyQxV6C[, B ,/T~I@|~JaqW7܂Rwu0419ŇLuW^H`1,"O$;TUZؔBndEp"H4 \tm'"N) 4ޅrf|EݩN|>K &pL=h=wJN }/Ӈ TzՖ#Y2-q2:ΘR/!XY0%K5oL&oaPP1o4oӫOL2ӫceADp1gE:)veXE+cd<, [>V W;])N>;ej=w]U9I] /Ձ ћ@8{JOdྙfXȊ7?Osnm$8qtZ_6SIx$3 `D0,T50Ж~8yBrG s2W \| ^Rt;900Iu YGDTq~G z3'kXʅد>S19띶[ ~'xᢳc `.?A67 N1oaAb*,i  t!I@pވkψȚZDsD1ß'k ]Z)vumۦi_Ǯ뽫{"j#DλʹPU="A uC9Ii~6"rcՋCD-ň.%2B`L'V'm+L[0]I6℥] bM@F!rF1ӵCɎF D]-mj17y=7[ɣŃGӏ0m[m+=Ÿ] ;FoqL;,fd +R;6I-ķ:`|ɍ zo;}wQlh S!fYGbn6 vQݰB] #]WWD008MmuLDv?~4ElUө57p<RY|5!=jf 缯*vtb/Z)VGoܽjjvhaRj5NZ;*8ŇdZR\<&R(E(YX҂)̬X<]"32 \x.ra"2^0sP-&W{*y]]{6X(cv` iQRJMS K g.09&"I̹q5%< JL̠淩$kndܻU B8B)虃snux'f>vnkMmLa;Pu҈<yv_5!x"Qt@MU؇uŢj5[aia\8sxOCW~|+ 6ϫIf,J02sJDC W\\2/` n_0o0Nɚ.D7:~G*#zb Wx, aҟ]W"!%ӓ"_OЃnDl n 9i80;٭)S <36{ [\wVdG aFrRݪ<-Oza"fB<FS?>>n߾Ô3("̧%v[oGfhwn{:N1!D佈t]G3ٓwDtj["_5z&.1ZLKsiste(!RT}ktEXC7&:mCMW !7Kȶ$kNpژTmZ/DC졓f\iS\荞 3pʓ j^y﫪N-&yXo!jS/}Kf:pMiiip z3ޮٟ3rכ]0:{5سF_ _qnGs e?]U%%76iCAu]sגwVHi}':8H T@ C"DtTR7U9>`L~;Ρ0J #Dz}^]DB4J*8"g)# ùw5TW)#<Y-j@+&,֥L_ oٖWSbsjpERaxw_ؖZIıD m1׎2ʧmlK?N˾0\\|| ᲍13wdgN:%+ix ȄlnǃnZjFuEnFDЫ#t4Hz<DTm]MP/aը" \98R;%@D@ # ="zi/ƅHasZSP\3YjeEy|V8316k, +]ϥmgDD8PFN$ b}1˂p n^9M8NԳiPTڋ&O$<nK3ZEiզk"cn*L/=3r,(RXnLVAoFʛv\ $*G^Dz\m<ЄT9Ք6u8v݂lIMapihI.({$U>R= uTTj3۔^O֣ĺZzfr̅%M-v-+DWdºLMM 2 l?aU+|k\Q7'fv>3 QkTL⎮ƒ(NP\0>EDY4n: lN3!* K`1#,}6x Ԟ#zCZ{GQ?}.}w'!L_LiY2+ڧgR>i1$]+UɉimzDLa)קA,']=_(CɨO&$J_F,|}%gnPm$ Dg!ԉR(߯3dX|If^6K|ݪ[Rl}8%۟1"RaFkeVa*2" o@}C0Օh!6Z&MP]-( t.J" fm"(}A8V#ЕL{Бmض_&D=Ufw85Lp @\] 'DGN43'Lw.Rd"\sY"Wz3PgaW>:<ԥ'Mj"PkzڢY'+?om^i3[8^OSJO? 7 GD Ciq8Bh>MF.CR@0)c !.^j3ḰUpNpx c@8pMꄧ 1|VKQ#A8[fTyF 6 E4,R[p>)O-ysKs>Z.~Qxqk|W FOܞK=HubAgI10<-Iv! In4 ?_'}vqs^3\!KHm5"mdɆ'^Hw:a0@RҀ$7UrT9[Zi08b- LФ!ڶ_6@K3Zvhz@t$8Qf>鋊R#JD)e̐8b ,=9Qq 03 W5H\ju0b"a|Z&l[)_LM=ӕRa+;_Yfrtkz~_d>jHo B?,1mS.0UO\k)OJ.3K0\*mtƤjfEʬȭ@RfQ s}u] ;m"P$y5Хe}>KBBz?ݑ-;?f^WDYR^0bѸ=ULtJ6\5?Q^K]M/O^h8D2N8%8IK1d&v4T<ջz?yFkiǯj7 ؖ@7?8= @c(}mFn+=Cqvs-n-VU+cJt)G.9>ub)dO;3zznF|$)ԙ;¤4b*x:۶;$ ̈)ؼp:!q"QU?OQzK !wIϳMtJ.|֗ٯ:_Q+#{jʝUoޗ9/۞ qs!}SD6ڒzicjTKlS{V2= 7$ 㜤$Im>>W:}4H^I/D\=WBꗙ>*OzӴbr"6,UVzWc"G!C98G>ӝ۶m39@L¨C.ĤFYˉS4&pX0`e皉jˀ9?>]:P@FTC@lW4.ޣ#]P]`go7"2U43{v@s p \7:6+N]<p+t7e4"ɘ}@49=}bL5d̸WkYgj= b5JQ]jB`qAK7c1 :q" D$ AZ(ΡUMZ/bŌMn1Cvv^ʙ(B2ˁSMBT09|Vd6D3'UOEsu=W%}VK~96WoSV2ZhDBCXoUU - GlfFg<B^|-cXBxK7tޮKJ'Z?g2 xmN[eTaF #6]H`;\P5/.d蒧xL`T ?ɱ0 8! Ez6Qu]5hh>0k|TUUk,=83fgDTC.x-!؍l2nS,%֛Lio gjaZ z[8˭ 9U#nc 3J-B.ޯQ9n/N&<Lp(\6q ??oE֋;V>ŭ_soo|GKxKB?+󧏥hɠmo0{W@VE⮠#rzи,Qbusn;B1}u;Wy$ nضZpۮz۶}}PPP3^US,8UtB>;:ڪR3\sWQtx h~  hɱ9|SEGW9 # 4@M]oh[oda4j@9ѡ]u]www׶B8̘9mg}V㤊'OEnX<^SM)fjxz[f(cj8g $^ڋъbRBN !p\KIWUUiҏ"u1jBw䜺,@䘤6WJO8K#v^YWq¤8]A-gkq4>r4-50t= Q [b3e!@(}px~yIam}UZn j$' ^+qpY@zIs5SJ`ʎ (fJ%1D)*r-ɟUU !8.)R$eirAO@)X`@!Ņ*,)yVKp"RdaW9FQS"U B. ;ױo>6ecmzR8wZ1x"Yp 1<=99~8wDv)t!sa-G 5ďN?D)jUGu+DQA^`0 +Z`H帏>V@4gf󈳆yܰ{I5 |SXSQ5x'A9<!5 pAR[|f7oc̋;>srB7J3Dr*:?a4ug`Ȓ! WjթR@-kB= BCua&rrA& FfA.8Md)ΒshX:|;sJA}Qf4#\gA)6'~rʤ,* ,Ef̄hT^fӫ([h͙d$=~e5~sRjZ[MGyA19R:VŴx:>WY\&ԇ8>nȞaj@wR-KpB҈ *R?|L+M8(Tq 13`6w>4vr.4Ce $Y$&Xt#3mԐ*m0 Fq5Fi]Ӗ5 % &-1Kd@3l+a"ˣs"(*KޟKWKWOװ@iu=` ɼ]>,q@pgQE W&˔)0ICZqC5%+;'tu&="$F.( WD6r fz7jt," C; , DG8y(g4)41۩ՕM!&3II+]Lʻ7X; 67AnyW_V\a/oytugae6oSn }1\X@e9k\Kb[D `m:FgvDDo\GRB_:z?g3jG]pAzTR'V۶UYŀ® TR<"UuUW d~qrz۶#ـwKZh+|( v#quztRlQC]PBb >Me@=KvMU"xIyU]1*)l֒0sޛXk2RLG/Z$#NI.|gF{TXf_q+6/1AW>!"86q"O.;vE&y S(@ߦjr~U:VKk=#"sPնUm5rn{DY ]4g/.q.kom+% Y * Zi~ \!22-{ζ5[ ^tqXg*Jy%qGR|t+V62) ">bIDAT᠀ 0pPurh{kUWB )0a4=AP\asvR"g/+Vyv| |*Q&Q`yH$R7v%CHf PuWUw~陼J'NYzCҦƑǕ0DD^?+&o>F`DqG#" .E)Ԓ4:NFm[=AÙlS8.0}ĕSI3rk?y8T꿹MΕ'YuJKiZr[`jq:AС  9z-ڒsW y{㦠*>ݽ<+8?~ W E lUHaXMmsv0@r$0''iwdANlobPf枃K+8geݪ1TqAY& /O3b\(o*;;:`1sS""̬iP;QD&qFBGu3$yMK;SYRN?}4z0R9K$$"`@I-nW_p>-2O֋72tV~%1!8K_=Poķ[\VL[cِM[:z}dEi"a$,ms: !ēp@D L6fse-O۶Ue2d-G 7daMԍey۶ec-K*kZ0Yr˖tӛ"w٢ sH1<INRH"fLǃZR ML𵐰Ǵ'?+㙿ϧxO^?0"n")FMTOS[=>;)" * WΛmӗYtS<(ØW埝s9VtUއRUU Z+{D> }b6^ގUVёyWU.lj`fg}L0+Kq \,0 dQg1`j%6]MjBpU|}-4|/[U(qVX7_A=J% <ťI 61Vas< df+)F>x~}ƀs9?jŔo9xp ߿Y:FF=VA@|{D{@߳_C<җ7eWd3 MN얧ؖM ϋ\KvU⮌Jj{9kL>T!  8l/Үh!^?iϼB{y ^Ü"Ӑ{]]~t`Z~+v~^`nyiO5)#MwϯB)%pHvEFNCvEG~GDrp:!m\z"͈fCs44F7:OqRtk\~XT su"ˌ,bZ̕k"x<gќ!+6Ƿ >C@LA@UfU9jc6\lS,Tť hI/=Gsl$2H- {\ "(j3۔C ou7+ʬ&BCӞW7XnܷURJ#_2Ғ%fvX49kK- Z5s󥚗A"c[)Ԇ@%jDFyD|yƛEDxXfgB|"bC3SGa۶1c뺮kL\ybMNH RiQDDK#*VV(WE,->dzρ /p^s*zZ0e[E4$S ƥ TFpqfNo^y5 ݐ|kOh2!@KBdSfMnvA\t@+33!L62Q;W]DfDT"\)קTA:DBЋ!@l{u(#eu CE t,{"jkt{̬%@\(CF mzNIQLaQ!6\O[:C5>Zgf 3U3POg*sO2GY~E8_ hka_gִ*:1UTc&+Ks#VV.!`*OrI0>Ě9ۿ.)z`mɝ_T08B}E?%XnFs0M/3C_Uu]WUmׁ#䇒і;mR:_ŇtO1BQwAab' d[ 4kp]}N{-Dždg`0 Vfx|C/4y6T , S74յ1:P f&`ѡr0N]/Ck2ev)3"" άOGYoN֗v]׶m]Fs=i#V'XV"¡g֚J/Ă0Bs89):W qsbv騗82J^fc%acD#?;Q+$xt!L|E r, \ɍL\в% 3bH^ Wz|Wa_<l{A_U]mOV6փ#p9,149 $ 嶷+"bu9 !xQ=:0WUն-MJBWFm۪iN[y昌rUk_oT됈62ZV% uA#RЧB{? $['@NK/Wͼdm^}& c5# `JB)n]ZYA/>ί88)"iڰJ/h)0>hr}.}H)хN6U8kݼY3rtFre*{ILLD>|T2'gxV4D"mA.VfP,w)c}s7MSUEʌ 3,\DVð@`몘g +-rh2\mm5$mJf"$ z@gt,,URQfB k!OA!Ta Nc R|(;  # pB ҒP;;Jʗ N p-5aR<°a^Lq[Wakz!Z ۄ_| _,-ȿȞńe5)]*Һ/3$9co!Pt!qA$Χk%]tCƞ">]PUs;/q! "PoC(R(c)wY#ٕu2vUXQ23S 78]} ~_S58KoBxo>}BWZf_X}QrU.52w[HOٹjZp07ٚNExn.8j5POx@S0wO]u2m[$"5@G28Iu з* xEqD}0J07e<:B)@1C*}=&Msa!Kqbݚ0gsy`cDp-W~*#_>ʀ?/3˫ǿjf_CA(?8Όfh%nxm6L߃j NoDdK|:lKU2OլU H")DHhF`)8BQs)%J DCB]H}y"M -OZebڈ]EK Gnpθz-Sd#S%JqZ[4L`$=6dY/k KVAq<]ߜo81-sڍ 'Wˑ9<\r-Ȣ{Mw%+D$p,#"AL*)"9CrŤ)\؛n*zz RaoXI~U9B »3d) 5YF+298  ~dSh\ !fu19<21dmm%6u1EbDeH|+k^mf:_%]Hg!@%218{̌,"4 |( ּ nNj~/\~H#n&`^©*vs0eY>|%y6}Z*|y}4c풬 ϖd;8>^h900zhmbm'@FQ>ۧQbB+l*7jU2>p/1},G"Ԓz8m@\Io4 @ yeBzq(A0b,oIq5Z-qP'1lŀu(л$jV(䇃T yyxQ_%B27_}y}]/65qGq@pr{CD4|히(NKdBm#mB("~! |Qpyn-c4͖:YB=Űit:)UٍoauF+Jl+5%HBE Y/Gq萀n?f/Mz]3о<kd[/9$ǫP a $G9 m{vEӽ0 YMsE. $oV{8(WDNC{:u]n D@Duv^ꇕ ;j$@DBD@#J6ˆNIvoƓƐV؃kb:@},IY8 + 1p\EJ7f_ gɳ{tѾ;as. No'G])DO ä4[d3ZvY@4QF۳~k WD}]5A3Gv]ib*|Mל9pUV6 B4mUU,="VS|l,x_Kxso{}G9 |BDk@ 9-\}UCo42E iыbǗ G;˴5c/(bチ8|Cg߯f/6+Md@b)e%ap""ZvY@t ^ 6?WC#I7Wpz~n<7]z_ˣY7U5.ϯXzY^kJj έB:=\NiMu.Μ>YZ~0⑋\ h L&ъ:8֧?%־0L?t_`j!kxrS5W*!+J]⟽109Fi\#u .cCɯ8XDIٞh b]כƹʓF!{1sz\^v%*T숨y:rV\ ek8m͞>^,^YoJqX*fD,iy!( qyY.s R3d/l_3T{4a4?/cɮfp[dŚƃ R&dKma(#E[z,Ĩ{,.{:>jH$e\U5 j@@eD" rLLM_1'q4GHCJOZ.o>\ޭ?qK ׵uSBHtfN&0T2~}b㿖׾?uřgq픷Z.&/^E,N7S#%& NiY|Wɫ TWSd>t]Bm@Ԅ)&-HBDͥy)l%j!&Ƅ塽O6c=8?H:=\"#^m2[i|畀z)w,ȷ${- 51IPeW$"A$LvmW_X<KteIsK"z]v1ߒbv2>m==v^c̬%"¹Y*靫z"=!"jQ%, !:GԦz u]s)hؚcq }Z- t,=0E:z>VV,\ )9yp= hM(B"0zRb慞\a ZƕƶsuUUih~T:zmmnX/.ZU4Z8\ar'_\ qJtf,qߥg}%4dvmOVL()&oȷdbSkShc!)%$ ߠer%W y[bp~V$υ;"Kh.ݦZ=I.If/i?£X&%""o0\>8.!"QE9%x|* Dɱsu]ov[D_UU5V?UU("|rf@ [Bu`̉h$Mǰ+yr]Q~lW" 0+EbhBz"|GC pUQ5y}_[gnKhsBS|ukBxc>OŁ5NU8sL6,H̠y+NMͅݮuŋ 1dg9̠[`"jO=YQ!Mxu] :aQ{a7Ms8t ]!n9N.G¡RKI![h M=2Ag͸PeOYke/wCdd 0!IC o.>e/ C3JY0ѣ҄\K5OGWG .t|Nr>0,CEM ,qG \5ku(+ty;%j%jSy}U)Kf?1pr:F !]?m[c0Q\uԊ9 omfn۶;x>w*dO@CB=P! KbV8r+ci4,5/X'kzFaV4F%b"rB֔ +NB>#*Ff̥{X5˸7MWMگݺDzWg X~2 Iw+e/"/ty'y0\UU٨7}, HDNá;O\KvW5=;E.~նp4}?><@3YVU4j`fJ(KHݒ1|6'K|~a0O.HNtͳئJ) -JW"qy X]RNLqZ3lb~Mdj$2ƃ 1u[ѯ03p򭭷_gu}IeK\@ɑQFӝԃ\1uƊR؎WLʼnsЋC]& F]=N9t纮CBߓ!Z:@*Vkv[pJE911`TAkŤ8K†:'sIc[{)o_%*Yu_ 3 H9SO{@Lߋj/f Jr>Z< |׏A%Q8 R:fqJK+YەsQ:N+vsf߫~۠4` l( 7l|mOKzl;fC]5yMґ2ĚbΔd 3ON!n$SG8{iNdLWl9lW>/^PvSU0\[{~iSle1 ȨYbn (dWeoYpRzo[%>0F XBm۪9 ڶ }˵7f҃ hkkcq "LϚ%=ݾ yхAP;7ӕۙ^t^iǬTNIv}P:㸲x O ߧ{jߚ_ /1k۷uS[iÃeLqmV]<b>d^b2XDŽPJs J%31TCs'3jkzo6"H43)G%⒊Yh=%4VmLزO\d=_eV]INuϑ-f:,d( Y2'í6Zk.BX۹nIH`xi]}>m A4 u!qkǚ$Y!r\׵hϝĵDT~#G- ",1inMi "B}㈈HǏ}1c0JC&F;ſB"D$3]g|h7M5s~3z L% u8hmYk%IpdOmWGĺFlG,]Uuu="nfXB5ó۶}xxx||DqэRipnӐfPrKs]Z'Mh+kD*eUޓl6>ө:EL>TB$D7 X/BZ( c4-\HC~Lӟ|cʔʂFzJsQܗ>Kl't=#TĔSCa;PZj.0zf3_Kն^7Quus'e1mۨxb+U`q[ijɮ8MC6fSZ&!dNtj7{8 j V1q2UђbD$*SbNr AOxXy>?׮`C>6 KG`,1D8NayU=X0.f!DY{8+g\_gu5b F50שs$')<_@;ct^QvaN,Oz L8 zܺ ֫QѴTU&"ꁕz`\]u}C+{ w18aDbY0 3z)i:>-LV(D²m%Ӈ^l,x3)6\ȕ`$AG({# f>Z\es'yx]>7 MV%[웬d| meUeiPŨtL ]d[N#Y"}tg$r*w #Y>aWVVO1Mm$ADJ麌 E "ZJmR9ڔ˺M$?f[kSҲf-Ma ĀEZ<]*6 bxN՗W;~yk fPmJ.Z~eLl gd5cM}g!~'it]}׏V3frǵ,B9?oq,OM__kΙYUnpifOY*iit]v'q%{rCA;ix(*ș[D$ OTxqٳ J56K=F "\gI6'N^~vvjh $Vltar礬^S1l&WwЩL=cՕVο%궸Q\aȿ;f`0\~,s `.1ؕGGr4[VmH򭇙3eTQ~Uo6 b$sL}}{8e֟WR)ի'CPHn Dr'(}@ѣ yh2b1o$Ww%%B:#\Qq*^3Zʭ $|g0"R,\EwT|>g^ZdI2íAkm{p8.f_"}wދȑ/&whHg'o9jPnZ#*/霮_%tf%+d&K u=8y\Rd%ku4ds9^ +sA c㆗6Cb 3[/NQV7,I[Z;;[ys_G[0 7,oV:,^W=%[/ѠNŽ۶JZP;moƞG 2kT9F to6@,7P>Wr?| 1-,ns@&O yס+:-^jY%&'a)0XMo1%h!̾#Kp^ X=6g:tU?ݸhSz8 OZ\Vٯܮy~.Z[W io5?+ߵ=З͕brP-,i1$Pu;Wl@nx!+d erN5i#Ҫ Im[ 瓠ir-\iU p8}&mWk&[ƕy [!PSb9^x7\YD$+`+*!vlmUEw_!X`U2X6er*Dy#2Y&" QPD6sFĺ _MWn]Pt.a>}VÔ]kzZӃ8vBđ2jU;2A \\U \+^YH B[ƍ~з0g]36>V^j}^ч2N/-%vr6hADu{|YD2i7B ĉtVⲹNǿ1Oۮǿ&2S`5 "YJ9 \OC(A#wJ>ЪD~9WWUu /EdeFnaX{*>sDqF_N}߶-&Hm*AFЋ~rKpAKR5|k_?wg<2bnNv&k78Œ|uĬp,T0͎pIUS͂n^<:[) 뺮ieRD]YZ aaA}oCJUU9 *FDGゴ"K,)9)H#8CسoVi\GLFb-E(+ߩ+ϼYSVc PJDkIreH;O5C/QHN[XGuY&YR;U*,Yk Kk>][ey1ob#&1~%p$r p5:ߚUa($OS8_U2T2\qvP+߾ui*YJd @aLdU68-ʄ"ds[&,eO.HEfCTv\*?]g^Je>Uғ1ۢ#}~>J~6.<'j֍BRL%"DWιy1`}~QQg0khj-Ыu6p1/0HAlɒ%9P@ a.ݪ?#H2.qhgOS&]A,z,K3?sE r3_)֥BN3[DGlOKg!7YtD(e/N&@7O=`AJ#~Yg>*u]̥ #/l O~""< 6Sls=F\s'+3/l¸>5rwu=NA4!K 9$"@Ρ#A Br_NGUqrw`?1*i.:P9ɧu F͢ Yx1 s}9ZNj#7.%l.*#5 y댤>D<<4~Y0㠎?)Ɯk1l7X(H\N,jIϱ--B?׀O;]?ad<+ ªTmj`!#$=EclQmu]׾?1oA)#h=AP=V6$D>S}:sI|>+%S؞guuV'j ʼaL$zg7#{jv|IaXkiRBA%Cmb#˾;Wu]Xҍʐ)e`Mj QZ0&|H]@I4 &=Ld{4c h6HvSX:EkA;a!|C1[,9[VDDMΧө!*W! z0'&:S)Ҥ] a㏜ %ųϹ|ٔ鑼PD>gK$=rM GF"f4 'Wzx0 /\o` 8Vڍ@ώg}槣ZB/ à R-t×qF8AW~~oLKVv6 Oo˺N@0UUP,HA!Ab=!aN$՘ZXG`Mt7c"f^Lbv,g au&{5;'Q4V)3"@q佯kt:X/ HM7.̽w?}]""'$${MAOSι9NmZi4  C 6*8u-KT9IDFْՕ(ra GVg[Z9`1^"Lc5Nb)bO}ZKJsF֪=! 0K nKHq=H9s-BDn^6@DD=Ȫr5*aroy.h9ЬN1S_ x|sO*=[WfW _<9K]‚A eJ&VuS7UZ%B1L3ֶz9Ãi=G %}"Ǐq9a|>S]nO>|A6 Yf~vj5/fK9ɐȄHAgۑ'*yX|'m6}(/j3Ns 2/*g;OmÉǪvz2s̜^d4a!pʊ Xr"륑/ ;$a-̌;]>gurd>&׏P_Лz^0`cm'؜-PiUUiBܵDshA%Q9'$D }/?~l!u]TmXf^4=5eՓQ}NىWU!T>A "z>@Ir*[QYW\2g!| Uj H$G 0,4_eBXL3A@ h@CT \- h dPtKR5cK"gHW) gRVu>{],*0 `Dv+/=EVȴ'\BR9͠|_Zk9}`^b{l6 8]]׏u }?>>*_Nsnfs8N50F#eP%pvg-꺪9Dv4D@C-&1I  f$ur c ;_oS.'0)Z>¨{H,2 `> =d&PV}fɱ1O$D"a脢3\ F8f E@ !35:dئcRrMvLo)ڕL:0^PK<`yE?Xn bj)c~2VƜYBU3!0!(T;'uRG!)nt:}vJUoѾ= (ɨ\|)a_SLsED>Y^14\{^ss|_WҺVm/^% [6q ΡzQ(1-"""o==I8;_CTMMlP 15Օw2 [Pz~5-=&)r1+=aڭ Jȼ^}8Qa@,bcy0CA4rGAr@896+G.ō9p]׻FDu=P]U^E3rgS9^WPʂ"=1HҞΪnEoj]}FゅN6V n:8r*!(L`1@˕5ӁHaXLĈ5% !Gbn!LK%D LkdLG_|//خy{r ^3qRb.q\Gj5}1P1 ,@iA$@ 쐊vV! ?v]+:pJ-e&Y&e:Ϝ`wkWޫ9?sC R@2H`9Lo fUwY*lMGU,>_XS fOK?JQBBW!)Fy$H諕2KQ]A "DB3es[ \Q J1ƀ=Zx2? !s=ggxv9?֕o1L lf%&>){΀4w$#] ")ͮˁﴪJ:_!+H&$ %B5kz1cɣYsx囈^KVf{0l:yX)3N-\Uzc*xn lqΖ3 `d~+d&}}˯Jp#D@"x9P I3 "&/qr{͍ܼb/NN^zlx45KyAÜ8P^vxy-nJuQwvg;6Fi~\r)X staդ5r БFj'ML{与 ~HEkzUw @P=e T>0B:y[A5LB{^[JuTU˹9UDY u=ܙqqX~?}s៤%:R.I < @IvB5>L^FD\)MDfbd8ʩhD݀Ns{K_Uܧ qP/@fx! rnRVB@e PƟFY`(PjY?;Xq ,F-g3CutW^32WP0O)"@!`JI5È֗I Vs_n`S@"F$"IToGa8b}*q=G{x]\^FًwP?ǩ^K&j&ЌP2ΦDfVݖլ6Xab &QF/B@dDFAPXdH܃v [ld[Sm-S>i(`^pp7Icr-O\6Ac^xAbٌEttnVc[?& Tars홙QN|ݬVT"ɺDWbB*fjfqXLbҪsU0S 9` Uq~Z Ё U/:D?ՇzY90@gڟ2+kSu-CByeG\SfL@ʂhdtAUco%С/G)-QZLDQ* !’z#\dwwzrr"^)pc;#nXqFsqFs2|Kt㤧Læ'Ϣj/;$59J0<<JW0$V{W@:g3)rdEX\xSCC]%,WLi5Ov_@@`](B(iD\B-iʀ8H޾\ a"_޾L *!4/SSB[䔒dA523B`"͋SY4/@[ "z=d(wQMm -*_oWPv>jc.l.eHJĢ,E EE4^K ]uȍKSWzY /:^^+gۋ'݋}s{+,EĹ'|!mP" 7nw׈`P=Rgf+n=mM:Lq_vUwCڟp(#fa hƀctx ԵbTj56R0}G mնFUr.f@x+y1*BN!`BL]m?Aܤ`FeYs\' "2!U/ ]퇦^gB5rF;YNasg 0cg\-R^PUSePD,XǦvc˦)_s$lYfDHD@FF"JDJ ,L*"LD3+D=EM2RD16a`ےwvYA>nk9NڞxAJv!7.΂ι?Iu}" ٰ˄HO%Ctfþ֧JTÿ.ݖM+ \˲4ἄbZ!>֐vzjRսZ֣DZyI BD#QT: x6vHOiz~9O `H5I+%@izZ@U6_0cI$H Il/`bQEdW *P#lLdѼp5߿d^txLJx/߶+MTMv{ ?qW{:Gze]}==#^~x+7j{Uu׊_A]P8``xЇ3o,u+@-fR.qUJ˲xvs:nz팈-% 󫟥n!d:#?_c'}ڑ{x)<97Gt9 ܾg@BHuE[FIU<)hfٴUiz)AD!Z[IՄHAJ "DDS`Ad"RgL}U#)wSh 3Lu*jI)TЬϊk>>h.1\˟=S;+Ix2k-xc Ǐz,b3MLPmq"VdrNۂYyonUޤ\1&El]udJ6"wC#xLaqqP$=.Ŧ=>=!^Q *+i"QRߺ:H~x~kbHDJDb"%l+=U.0$0"rt ffR5]H:223FA3 '`#'mc^S6fl?wHM^}]?Tr]Yk?)?tme٪{^dAD8ɽ rz[ض0Ek.^s#dÓxwR ٽw0x'hB| 5Q'wcӸatzabf`y=֞ib֞)ZVܷ{b#њk*!TRʪ(Jz%R}oTUȌI%)3K&"Qb"U 2YFDfFrS3"jJq56|+ nfR@Ui4TcsdZ{q>me^w;lgG9YF~}Z ٳS_WԊAPaLOrwj]m 4VqJU%473-;8M4Mc ͑ j5Þop IB4q*bfrsvduiC.FHq3 잨CːQO+L [f\^ 3;t8G=N$>/i|L2V'[Az/L{JÐ>MPC3l0"fVoX(TQU !"CuѠi_;/$m^+29EnD5[Ao>Ʉ-if(to7vj+ϽOdk4\_cŝ]9jcx7Є`:ֳfO䏖=9!{@Vf؜LSp%\] 4MP O/_BB8dR%'h: j/k.z3rp{mĞUY;]tg@>k3{oU%(j7*Y"64V#q ԤY2r4$\ʲwXge͌^Ǎ ZWϕX5q ".۰|h,aS Tz/Kdj 3SYpQێ6ZG%Z~[͒-@M5Hsr΢ɷK1q.zpǎ1\lT5ZF&" : 1ȎfEnѾ"H!T[%,*)8dh^]_3kDP˚d[oE#;\:CSveٺgD49Vq? P7doǭ@v&siqvY fS萠(RQ*-L 3vP6ug1CW/ Jb =O9X a.ϟLN7 {riDdPh\ ڰE{0)7&~_I|ކ_wԶapeFj{ٴD?>@&؟nnΐsv+`1y)T8r?/:[n&ly?>xT!"*fZjm\V$sFiKc@h[2lx +66!xG~4gɣK%Hsnvĝ޳x:q!eZ!2ȺS֋b)MH f(*ލ$y7u<ՇfflATT" /B ;͎Äԙ-w #bь`gnWpvv}2< szp 6:XgqYm;gE3k8SUU˽|`D5 : eGP{$Us =g4D=U@U%ӐTCu{ޭ8H yȵ,bIi֤aMRЄ q) LTupWnaܡigϪ^j)YsƂ@HIH<rqS"VELuQ؋ Yؘ)33sND$Ϯe. TM^U@p?G忼4?+֢PH *Yr?bExY8s[ѧw{-萩{/g"WO[q\Wg` {-J<*GsU55v}p/B*^ƁIpsKW9~908NJ&۞ݏڻ*@qD h}WdhA 6,)۴@Z!H^^ /SV{ulZaˍB6.x ̌iMjAE!Jff$ d:;  . [w Xs"" )2;32sZ "f S2DP4A^Z%u>/R(h]2zi,̞vS]Hgl鿐;D_{+?հVRClz08bs:nP##IˉJfQP@Pj@=@TIDAT)"hT(7> EJ$b03S㡪<0Ky ΀j%~\-ӧ%XI8#=Uk)pxMrBՅWZmq\j3@QC3ӒcKƪ*(@*Dn֮=NB~L puX3#23dUF&2vSӥ6 "ua׋}AK='D) B1n`SGז&kfoWDP:?P=u~w&WZ)ʶlpe Ddf`HHZ]j~gIDĸVQ\G?xS,.]ݣW7RͦJAb_٣ؔ~ ՍO9!_^9?}F2p_md^j׋Af=[C=⃇STK]cu1f5\';"lbf7ժ!T `rqIi!9B[ߦI$$)@HB"뭹9w^\sV`?.'<|roݝt_{ޢf5liC1~pfW_hnɇU+Q 9l&aSȫiNGzgۮh_6xrfbA8X]TѲkyYW%뉆-1c1i)8?hHW֟׳NW ] )H0<ׁu0lШ:1lrS00MY[J}dž 1L5TuYNɰ\ t[,l%"jMEJ0UvgDvm~O{aj~Cm硫p;|ŞD].[QxUUSV)V(jnWT7ơ&2d fȪB(Hf<4"U FT@LI1`&!;0)s .$̬DHdv],.z3V$#}P1Pƅ<}/H=mv٦5$q7\`.w!}X"i4tN;v룛+6]BJN0 :VU&n߶$Ƚwi63DDo0!#-%ůX֔ntRU9շE|`>-,jcd$3jSJivysD]Rp)ЙVLjqZBsS])2Vi_mǻ;~!a^7H䯈_nD6ղvF|78dԯچ6EDUT!"?2bfj&I몚j*+*`jVG<@TMH1gDH,(l@Fd8!J}G5Hz;~I^,QH~h"0;/58h2 A΍B鍊q;w} nmő,ԏhQaun=J7YyڹGRN8J ,S`32y~'@9%-VsU/Ȟ^Bh bz=%Tcm4ۜWɰ;mC|H`{]m/a"͋S^* UQ-,ϿU`\] ^*;VB5l&\E4lAPGLxf(YKsV$<@VCS/"Y50p * =H V55iqݪT 0wl}9&iY ԫWmKZP<`uQCZߖzYK?9PUD18oT=6tAqW9"r"yRD&H966& 5zn`OWہ*x9B!pDZ;q8thnESY[~fPݴVTͭja$ªR,~"|4yvI٨H5w$&D,RBvVacȈHf0}V{^Ogw`8u3'бP`gP6F=O`׆ã_og3PRWOdPVeW03CD6B"aNSqi{T!bFmɳ:rk56LP*+j)ٌʠfZn+ %UpP3ʙ]#F1B`FDJZ\,ItHkէ))%ˀpxu[96k`r Ofe]|rZ>[m}=P(% 0g,]%T9mjCakpSaDUR T2ےf?B@k29PSzr΋d "K<3̭cwU"{!5۱!ٸW~FDTU`fb&* #!~ȡUEkS,;E2O띶\#Ca3ZM):dbL" ;4Ve]_ȫeb&fvyCr(0\ %s2{z{*|C dCϽ|4_v O')HN=|zlVȫMѭDHtRP] qy<17T ݑsVafjxeԊf& *)F` Y S?DRVaf^P} Wd!0}@ඝ5Fglg}]y?_ԭju1+P CyXLj0o]fDdY$Rk=J-AbX"h0qR*$D$Kڭܽh9ަTL Uxc aj/ 5:a.HK$"˺P5 ^]NeH5j|&I``tY;VLp{ o&JDp1"bΏ,dR U !*R Rճ#q4FWP=`i߶ QMuz5"UJJ3 +*jaF"¨YIx—/ј,QȘHB̬"*KxWpJHEO q_6~i} TxލK׽ o5b͞QI.&6EJڒtc((Mg6+#zojSQСojHLXb +zȈ¸|,-`y"bb>TU`]r$yH>{ɞTOC:s/f>卪b^qۚ73gfd'1;ef`DZH"U [*5ŝċ{\ԟ%@j:MBVN2E`tc&Ds$vJmⲠ͏]VHFh@<2k!q!1 HFLj̊L atru;޳pmpr%~™~>*>$_]&r+[گnD0!1>V`@Ee5i{c{8B"؉$Owz:\] "dU۲,fc aC}U,/uEjYlfqyF?l?13?QBn?eqi;CTYb13S9Pc=)s!q k5AqNP7栯4\R!w-PFƘkkP#x?d@̖ **#1s YrI, " VcI3s03[QwhVSQ0! *"V Nd )HAД(YfnUD @5g@HMYz= f[˒fF"2!#R ;3%0QB8K.!PD**/nOy>rxvFu3lbl쥴FT݅1a~cY6J)`d$j%pHWMR3oubw0,x.9}yn oW"d<QǏűL{riC_~I/ht_(aUU~$7W.2жYILA\YUH !۲ 1 #[[NU21z y.e-*$7ݾ7ZTTDZ4:8E3jX>S.})̔jH&AT݇3O!Z|'6cS~`]ʶMCo nl%s>਎uU{?[!' 7RAb@D&vsIjA?ѝm]=m]89@Çg]Hë_iOl0yJ MC 1""AFS3D));#!&(+; T.ц ] eڮ`K繁ac@U+Ei`bATCD<ʹl,%xֶ|(7CR;"rbB1">OO?]Oůw+Z׍^yޯWY/YV@ٚ$[eߵ!+f롰Z,)-1 PڒD"Pɳe$ dU)"|*%S̘'=L0`\ByZ~7Nk@zÜ;xzh wƾp+g؋:]qTof#FDd׳"*c*f@O!"59Sr)$R!%<5$cqX$Ǧh56e vfF$ŭM {ilj~ꩯ@AYSg@D-,kFe#"0DUIcD/aWL| ه~HO</Wֶ]0AN :v@ٹ4>~x ;T 9.ȇb@f-.6}&WmLҽh?إ)PF>\ SBH|=!-[}6-륏~JEjRP+cWjʦCZrhwlG3hWԅTCn X l ˱Y)/(y}؍DsFU TA!5xÖh?qoAm͢ X}ꛝp0Z3s?[۔mPv[qYw OpWRoZAټ 7X%$ג l$,fEBy`25O%wR͏6ܤ!x$Ub3X1Vw>hJB,]ژILS1폜p/ u!XN~+C@d 4uNX3!C t@9"z!hh؜VvU[_ZnB鶦o8Cf{>#~TM[Y=7z&lugkLKYp4t fZt)P $ֿXOW5_d϶1x^B{2ZllrDG)hOȞF鶃^mW{DuoSJE$sEͷ%Ŀj>rW]f<1`Jm6#tHc%3EUg8a`p=J?c^$ϴ z(l$<ȈKWri^۸VX.>Gʹ9~|-%ϑC1ID>*)I23C4x/R2v︍1%oE Hn윱0,)nEPQ }'yQP-gPcGP"Cֆɹ*ZOdYM h}DSw K :7.okb3y<|+9! Dnf "HFf |ਙYJ * 4Ɲ&PQ:6"%=_o"^^dFP|uZV-y75-BUU0A` ʕ"'L 2ZVIKẢ1xB9!Q'J`qȤRW/ o m(jD%;DPTUP, fԭ} "jK4!ں2/h89owk/w5ʯ[ >7EV;my:p([`{1ȚP#y00^=!rْ]fR""H<%3cجڈ;oU%R금]9 (Z5UKU!`^%\F*KuM=ۓiG$%Cjy].mO3)IY'p̐*_؇t &hYBRJ)Ƹ,so9WMӋ!)3WYVj%mEolV2QgȪGH@II 2oU.Wn+5hu]C" b'?aڅ8{+yX@rMdI^{1l)C˹jց13irmwm܁ȥhN{J 0Y-07),k&3L`f˲,Ҟk\JDxbBJ1{&1x{~O{ }zzg_]g]2MVVJy$UD.!YTeāL2Sٖ%%Q, ">rx)i1ƸKqbULS =Dh9sՊb;q6){\L(HPL Y!sfZA:4$1E) .?1Lb^QK w3ggq,B8h;k (Xm4S*6IVّE zsot Ԭ)?Dz,"x JU9CT U=:0vJ1xRJBZW?ש0 Pga aM~}ձF=SIzOH~H_x|M~l .`׮:BE3'rg<$. I/o/")$cN9Ly)gQ1IMfD`2hyؠ@oqh_ya)U ISaIAD&EE2h *hD$ B)XJaxEMd)ߝ $uGuhAF_^OO?LS%ߺX;]bkhWK4R*4l=wqRjQ)ʭjRɬemnqh6Wv'v8`@prg T LM 1/I)`Hf:!bbLI˒%0m<ܓyb)R2M$YV  y,0lg{+͖c8s'1Ũ~bVpY%Ò%o!M"q7WSIt*&1J#"K*q,%!2[s~U ^$ ,JbB ME`غOrAͽW5(Q5aοk'⦯q\lݞw)ogG^l]ƥAj0:G"pb?Ir˲xp$[DHFjB?Z#<,˲Y1IU%(THW>9I1A`a0aJp@? ߞN'Csupr WS|z_Rse%+|^`5. XU'L5,CBs\ pH13KdFfJ\[r<ǩ/jSҁZXH>ӏӦV9[O? /d;; %ե'}gjgX;CNMQj9oݍ:'d|gj2+"4[N`AjǕ)]s]mb^&-cx^ "2>b H)J*<jQ'c\+Ұ?Q@"QVXt G O_ yGzRg7y&^2 pu?􌎋 _gK>֟xNHU\saia)3QymEi甾)D[r1XX5h,\'rV\hߦѕV1o͛۫X\Ε*AōHEHh̝+ /3˱j' 2yX]ex1',]@|K3V.vI3#zqK0KzUKGkWwPfI Wy} __ j\$"rzP֐ .ՉhPE>ŘgPU9<ڝqd;@*mQz된auCp??ɬv fPxlU]QKSʏRo^0%$SxgH$T  L}`WljaDD2бŠ> e"Ue1Ee@.Bp'g(8!yHsg]~W¥$'8{lw7)􆛇 hRosOi%:Dt]Rؽ%a>`9A) SAdArpdD9n7U4%ٽ/j۩5TsŝʓnLM ::2mmF׎>>M0,Qqiq &$WIn`~؋e7TՏu]i`y[ZC[{CxNvd>GxtC:H]~O_G/R865;Kv\6 #qB 材s^ET^AP1ll6uKŅT= >td8G@M{*ub5= ZEN^~Sן޺N כXڶZݳqU8ԯ3?*7wT夿;!mKY1Ev$*ow#IW "2ϳ D4Mѝ9)@J~u7bfTa4J 99UCP dQEH Z % &RW 4)A&6$%٘<"{/ afs0P̏w5P)i\̯REZ?'F$a\tدoϨ7ɸB:ٽH:U7Zx0B'漂hf[wX+<ВkJZD dHHݦIǃ=qw{ e%hZrΒ?"1̒sdM[9#y1MCx đT_f扼xvvFoմ- >>Zz袕K7 S㣅'a =e!`è"0#"0xjI\u1b h}H0uih3̬`}⪐oj:p ;O[^`xEupE~OSߋ Ԏi J@ \Мc@ H葽vj]+RIțd%3$I =%aʹZ|I<@DHI/f _wm3`OʨjɆ{m^8|t ?5YTu9ϥR$ⲲRm V"m)X XrNCnM\qhpGȞjA0|s$1F,H %˦-y*PWp=u=Or,)/Hȏ)O_B).<5+ɑBsNA0Lӻ@D"-H[(%#t mqd|/_ ;sօ N0$3(3t^N;i =&tw%%s)eZaڞ;ުۆ\Or\߂kd"h\+8No>]=!6sj_xoe{<.];]vjRŰX-GB cJ0#< =NZ˒-C_e10y)D=q![4Z R hnQI% aIuGuZGfꕁT /Ĺ_^ Oqܯ t<X "h~ִh4H3 [z U? .;S^O`Ėk#]f0$Ҡx)& j Ff TR޷axf5.Eo)==~&>jd J3Ó9ҿ2*p;9 E"D:53YCRr>8/G|RzDH)$@SpS4[AR8n;919sF @€D%sK |`nƵ걅9 k/S;[|~zsӜ$ȬWVem;Sӷ H󵴴aշK6dnE,p#D:6373յ`&Xc7)m ؍asܴa&YF 'dRƉi"0rt#(QFr S4zkvH gW3=T!?<;^e_a/m׶sI5UN'oXSArcJiqqY4y;"#%N)cZJy1ibYRz#,Ks\)=ǘx!LZL0Z 3)+ "QLtc< u$w@cq1*Vk)s1vGk_cxb6r^1S>.Us}rymjQ뙉{-eRxN;U4y(O3SԒ@lGVe" ڹ[Dl)sۛ U՟lyAsЏK; m{G]_<^.4\9Uj"5ؤjP{1xAuXD뙙!LYsKn1ާ8DDc~9яlUADRqYeYBt[3Oq&WC=̕ D%]OuPy+n#l3cDo'O?Ӟ/5O?5Sۅvd/^7zh[ggb>;#lm$8ИYP.ҷ%hQK)ݠ@=QF!2r\g@Xi[IUl,z &* 5L'YWqccM]'a'l!|şw_EZb0a,y.ójZu7D 81312!g+1?b#> ȀB!@&׵,9-))O910,2I$BD1F&0Fbà XCV @Ad8Td{mG1t'/9-x6yʶów |__/lm*z̽koKڧk"8s &X;lmaC uOΔ;zم߿[mdUl2ćVܔFl3Z9a-Fi 8T]cf$S3=o[}BXb=JurIWx{hhrJh67ļ1JzD'WYK/bpC 7\H/~Us_*N1e2]TW N2MӴ䛈L~)%RZsSM,,1!0|yDzै9D)F3N 7W#0"RD,q"yL b /o\>{߳羔<뿼Apg>ϊ1o~ #t"k憅aEU5jk2ٳ۵N<=QMg[ݬ@KD$ B1G0Rk{ Kʙ%UzvI5>,R;֤W3@;wv\ ڔᇰ}z?KcOWp04`0#1nNvJ ;"oSb8y,B zĚEDqQA[;QJS^!^Z!=kij: UL$dJD K-Q3|/cw.Oȅ-ʶ-Kڣ>EkлS{4UTRԫ1xзu_l#gZ^[l>{qxTΡC؄c"" mkښvGUkyR),S!6{p&D3Q%Yֈ^O3۪ 1(g'dh{USJۯSEχ=<YW_S:SՐJLRI_F u0Re",ķvď,yYxEׁ"凞pg{ cIn{ppUCjh5k۟Zoӌfm(h3jnƮ1ix I#cB4!HD xujPUi\6ːqS2p$qr;p/v/2 vYtb%WW teK.-d2rϪF*\00i˲Lc)|5!,xxQ,HD(dBie~B4i& a83z_4Z-PS~g,e||||pYI9%Ͳ 檎8~O̜_9toc̳D1zj[ -H\kG1'1zrI3۾Ga q{"t]?#9bp֧[mqk" U1ۉݖd^t#"U;;s1r)'`?41 230YL *6ռN:ƪv>T7AdBɠTܲz, |ϙTz"k/i|U<௝plZM^hvQ̽q vjff"`F-tn1no~~?>}?|R21 ,,"s`s L J~dn֮2 hFՆҟX&@qbfh^j\w1 )$fd 3(o)翇t?>>w~<Y%=ljh W#p[~{?{WxKX,B]klf_ z  #'|[QtMԜcUSJ~`[E\UEu38 ! @h(6GiWB^sWg *#WX"ZQ2Z/ hMQGݽW^$C)g#\1y1rx؏)2K-ssI˲`ZiZyyy $$X,!b?@/e\>vůe3FB3'CsXR|)cߏBg;ez8=ba=޳5txRNk{}p.J{uخ* r= d.FDVEĐCK7Gx<~qx}mC3'uy-Szs"™33V% f8W.Em5,"W.?^nP }`GΉM <@[޴RjE:f^ASߨ1F"pAuVޱD׀3pѨx5-sq5|?bf~<t{<oo} S >?]I3(Qbr{<>[[3,YYlpTi{>3JCҰm.\<;E45|_YO_m`Ucu?ZК&(C )xr[A?ZӪI.evyEy5{66cB) (X)S$Z 5Uy߾}vHCtqb5ݲm PHE:D69xxMB5*cw :\p'Z(6=v&>9{(1Df!b3L2=sMo˼qMo?BH)x6s'ϥ. gاԐ "2("2ar?`10/`Ms'3T40Cq \|vjݬB`YQ"2%%3CUߋQ)iT_]M{y!\?GDH@?T,ܱ$\4^蝀 bSk/|>1x˲$A$%r9M<*i&7sBL *1!`8[ ߿IE:D~G ׿ y^pwyO-1g=(;?7sTf,M,kEz2QF22RaG^A=@[sqkMn6sSrt;MӲ,nVUKcD cgwwrSKղ';B(#"Kxt궱ܪE*rYgmax؛m ÇYr=o~iQ3: RAHuyebt=Y,E"*&&4Mo|x|߿oxܓJvrӻ$BDc1vnmP|ܧqtK DsU t4des uʽM9Efv뻫 JjÚHu5s3owڙzl>ڡ%W8?O6ߞA+TwK=3vssmNo @6CQVDSpQ$Qcs~L1rom#w~ 貈bV*8LrFYrǔ6M,K nҡ75|+z)]'kO2m_Ԁ&{ýQ=I6j#ST d}=/#zQ\킗 /8YەS?+Vu[$;IП~]ri1 ѯKQ28Xx6B@-rH˲ͷ|/?H~/)%b`p2S)SH)q o,3a@(ӄ!c;2-Ű>y"*N_? ˚ %~#  = xѮ:68f+n~HfnUӪ֜WUS]"94|(ٿr<\bS-ES#b1MQi:m- ÃviП}Nfd}^N6=_ҿ]Gk]1uڷ٦e?o"Tbk!ꊊ A(=t7WPZݲ6fmM=WCKqbQP|NNE܄OR`f4OXmާG$I%{ "1j<%^s֠6t>~kWoPЗ~pB"*턝hDD~⇺ҼPצnѽM\\]ÕVy8uCqBD̄@X@DP01EOP{G w`6?ǁ[L=$u0+~ r`$3?WxEA}zb v}!PFh{r\!VU0M0ܒ,߾-9ǒ?߾h~<JFĨES[D!fYAU}TquǨ>ɦe_˞h`lȄfH!!YdG6?noo3=َ D$kZ> g"N90|薄4_fS(y.5WS~u;>̨g#Y=4Q˯Gq7ea!f5U D&ܛ}z$ݷ9ȤxNza)>FzM>Hd?!> ܲ*TBK2al\>q˴6':H*y Pin:6( ˑYʀWJP5ۉtibŜGӃoӧ_>}O>ۿ>/?~˗EDK<!|? k5חֲkɑ׹L^AMzQ 2wCTMGt(e[^c>о5@vڭҙd˝)_ }pǑ"[)n gsv~]ޚP.x%)jInlj6|zY%Z#EݚNdk7t;5S1Y%( NU `x'wA3Ƽp%"⻤[ObLn x;}\Uøj! O˯x/?/?_=_x1 m R[Dy[$rLxAt8X[!^5Nn]|xcn嶯]AF0ZI!v)EtnEޤ;K G/`#{+OĹTłN[==%7 WZ 1,$%ZBr~˯>/_Ͽo_??T? {C·*cוsn?xU"j|{*|_YRug4&%1DUոqAD"#zì˹w$f0*DĶHs7Zz Q2!4c>dB~i^=Ea& r|,?|L&HS-,$ˇᵪ+[L;U dZ` j:yi BS.^lN`D0vBB6,ǣ/>~ϟ?} =||"_D#GfY:^݉1 l$ +:2n+/LW.>*aHRq/"WjZ6:}nBֺ!G,~_tA˗/" @Su/"# kooo<`$M'L`oAvyצ;?L{]S3aD%ݬPnyfAwsaZE|ݱ;0$ GhwI . Oװ6/ϟ??ϟ?<DӯQĉg6-uu;e] vnBEeФr(QďAMؗPrQzn9uN7\kjR"3d@UFa\ i8-nkَpmVL /ېeezҷR[E%lK]: TH ե _sym_*i*@Bi8Oz|ۧ_ӧOϿ׷Y'َ{/^!Wf_rk;c0o1%2u?@qq3k$^']XFB+dr>SG֌R 0/_,(W9"GR> D0fsg)MmuC@¤yud ˗) hFqa8 }CP,nb~Ї~,r<ۯ;.paK"{㆛vT0|r4ԣn=:aKfȣO˗_?}o?Ͽ弧lU~' ^v)|#_ѻ'8e=5)s uhƠQ"}h;m:ݹgڈ9[iz$LHJ.v^2Yg Dqdž8hv vV: #DW8x2X 0naݠw哥DZ-k!",˷WCs0 V' 1G]ڬ}F~#ӧO?矿~+s-)碢uY8| "pbV]Tv i>5/($~a+\4^Dfmϯ,./_jeGiROlrolˉ5KA߬;g #fp/hLhwzNSKS%VXi:i<,}`~)g6ct\i& wUDvuْR&"@TR>(|_>}o K-׋l5w5OPFzPn՞+eNmvdlTU]׫'w/uG. W꥿y}^W<* K7i-4')pO$Y,_n2) @wۙ0_\J|2yFZ(tf<<{,|@te71 9Ws.kg7QYJ~7ӄ X.}S7|@Yp/Qq jIj _ZmاIDAT7JvҎ'ΐƬWQHǧۗ_ o?E9KK\"/]f˕"f7֋Z+(1WN!^|B ZTy>_<4Z.>ְt¶yQjI`,h|Ag]J{g4wc X mvJz~Kϻ>7{NjB(I lܕ,R*6a$yP@n(1@\ qo?>/o>}{`aӃ?VZ&V4M5UdO@vin~~el%oFJ(K^Q,@T+U'//yzتAxߑnBw гY<[ Ag?ϓ*{:Qf)$7K HK4IӸp^&tW|[>GCZ+-EPʛmH P*t **\Y[+d %|Em !G)YO D$( ~Ů1X Q޸OJ)Q~OD aT"BG8\Bª#pvKqƈiW讹[ch^]C|^$|0h `SgH&¢l"G - i1E't~laj@ UM}r$A DZ)h30x7#q|7zhPXAt<ǂi9/YrW'߼˟/V]}\*ymzYiMe25e,{9Ȕ]J,PWqł)tHSq՜v<XpGl# DZ+w+bd&ڸ(~>DDkA;Y犲/yx0CB_;`P Ȯ? ]=Zy-nƸYy0(-~H{ٞ[ Tf2\Bb>OՓ6w:_eI^YhCfv+{V=OOJ*5bJ4g@U&%^julߺ3lޅ.k&%w֑/NkA*&80rni,+1+"L;楲.Sz2F,.H7c^V f  {`>f +nLmSfo`4)Qހ~}Ngle+󭅾/:YfހI<0kk:K5o7}]3.11A{6d?@~xiO7Z2n g>Bn{ #[)\6q T,C`;/m7XJD[vSy7Bmf+6LlnU}L7dpvnr+-eRYY^rk26, q27ECR'YSG!I?B f Qذ_ݵRk.pZˠzYʬ"e{xd׶ ~~Yen]087Pr^qGeQ/R !;)OQXx(9YIu,ep-/18p O^D:GhMΫ@8ڠV~-C\sBD_ R~5yr( W֚ti (xHZ+ճ,@;>H"R@9 J̅8qp @PTR[=D\g}cqBvUTDRq_Jy~tT~J "**L,,RE EiL,m|ad*WH&7{D^,G@`x @EQk,[9tRޝЏ%;H+{bf2ND O{;_7Ys>&;/yV  tMyQ 3)(j:IC0-gމ`;]f`m{#[Vi^iăl^ѱ(D ^͊}-ZdPxMάM0#!=49a,Eom^Fi6R7lp4vDe VJdtH>ClsίYh+zYeDgKk0RwlޘWX#s$ [5~>[6‡s/F VTyU >sZlM'4LymmI!8 y=CZZG\twZV9hP]0컶ʇ`F)/bsa/it״R0:urT W]϶X+^hYgiNJ dhUXǫ 0b~{P9G.|#EĘ)^$9suN%^z^'˼ % b@P_e!].Tk\bsYs~zR>ӰD"Z^fN 2l@ +݇FWf@{|Vha`P_Զa'zo.z}"h!d'~7N;}5Fq0znx jNU#lSuQ#07Z6.+j`TƍH+a2>$" 0NLw^:=0v[ũt6d&8*%H?SWL|-!@F<^̧TsbxZ NNaSSN<UQizSv_H7zY1gI1n &=.Rh<8'ҒkYzܺ,75R/Rhґ5w.9 Vϓ(n? /xƛ,~uyk)>p8N!L-u3^_kO ݡɺ`Lnj|%mB"Rv.e %=l7H욫eInneS= _=}n5Y_,csefb'X;BT&f,9te*IF咪!&;#iZFF`.=涾ɸ4j5?--)(7_[lbv ) wqQ$55@?XcR2̉Dӽr=s7 D r9`8Yp[A0ﶺ-3uvl>k!'3??;/ŎhvW\ B_Ħo_2h>|AX0 hߖWn=|1KF\n.$<E\\uj=Mf׷N3Vj bH*<}mԡ0.V^kku3eo-_hlA:"V|dUlE]Ve3 +8(s cSTҵ1'fe:?/ܡe=I{4_QݽJHngΦx@9 Y>HoViP FXƸ4?YO>m `ćW^(Z"w6حԭan;gzŮzs+t>L\t;[A=vYeg# F$C7˷x]֟"w{ \bz\/[;cA[n~ зVg76Z(Y~Vck!%qŞnWk]dK /^?,!4B*I3FzK59v0`=9GSYตEy@ Qxq`Dd]|NeY\Py'6 {3D5-E`#fPO8+4E S{욡zSN޹fyJ0NH?? IαX㷞NFϗ9/JȜm9lHS}{/$ū哛_;D{ |0BF'j9{m AE׀_ݔ']S\ja,!b& o7琚tM$R {(Z-o.H;KžP[ΕP|=] ?(p%S~?xQ 0ҵ} ʷ#M; ݙD$Xa[Q6Od1 'Q|&"BŏZvs')V%܇Ry+Ӓ+m U?.qk5|(K?nMEV(8cjE ;b Ȯ zp݂c;aOqlܭ".ڶ+J_"fs/" lŏs$k$aοEBL8TEYEmWٟTG; G5mxBn*SҜΧ9uI}l;dDtԳ>?v4TqB4v4}/)>/7]\3#VnzW2ڭk,6\,\T qjӪ L2M|<f׉3WhqJeڱqICŌCHpv1@٤>qg=x<pe;hK~oy"W/-l< DHXfn$U#G)o\[hZyл܅<+ wM2B8#zW'put_ڜ?J['B* A>(w:g.W9wOط :_2}_P]Z>OIn\PaZҎ>[7pT"H{.v}9/wr*E79goO z@:Ya[%`:O90Cjeb*d +}jQenzctz"֩iu8V~P3T'6 1X@C? ݇*&/s9v!Gݙ76ADxi :7liG̹,Og+$r8MD4 / *t#4VR~e)\|Q"}|/c5riaS\j^|wpLyNDyR5TwwX_u=`bl%,}$RF$dӓFK)>@1/UgQs=d,ÀA0Y3ZN ~:<":{hY̽K֑kO[;s8g߁l(;zl4'AG=—=,AiXh[F|%i  ׻N>^_<~skhX KiY'FEx_e&lQ \p7.+hq#rݬکmP3 MJ^,fE57Heg Rn+=V˥K"gSv3<{iRx/p6|]MO ] VTZ8v(,Zhl* /5;J]&c3F Js7wxHцfۭB__w^NT-C.b;޾x vqtn1= <4ciּԀ ^;H4lnȴH*21g_)Mr0DxX}*6=6?G*EZ/ s S裟 tmk> :gbRk|dĺ <2Kk@߾Pk4TnXjrT` `L=v.| ڷ/&Ehqe=ivMӶ{7kFU ,tUo0`AFHw^Z6CSnf~Y{5Z7O"cꝩ}Ȕ 0yKwx^O(Q%ū$Cq"Lw):X<'O 9f>_gf_HH} " f}ݞ\T'V,_ZP=>Oz {=vΒ=Mg>C^*<;zԭD݁h2*HkgbEx{BZËVd˼ՑX|xjQ"ka!b(J?/y=]+cr?~cleW-^mvXPOZHa,4+i~m#Hs=4P#}^FI,]@8li7?q_uKҿNq4@D4j'" *oǧb\ۜ 8tgy-Ji.L Næ~6XG6]ÍPĐ G$_^-XBZ6׀:Hӱ!75s|g}|>\SڜVK{b7z uQZ7H֛m5E* Ab!ƌU*i, '$I;\Ea\]+{8m(o(DmT\2c=}|w|＀$lKl2Lk= מ[VAyH$"#fƆ]yfe2Mf[&B;v5_ sw)lWqG|4{-L|ǏUCe"(lU|G@+]`HKuoB_7}U38Of/<>yʴ\89Qi|7G-:M˒ qEyK7tJۙDwG{*'A+ce%.k[JWg|Z/GG 8;E SޤBܿnu|v >YB, b~^ũp&ܽ7usX3(d,He!+gD!fR|?5٧~U|(4 ?ӥzEE3n,c8;k=H8S'|̜89'~0-_6;AYU7Vh&Q [)sD^H<ݏa/oU zÐ94 4 zW BTMC67Q,%<.ܗ4~0VOHTG*&k|>RygO~6_-A7A?ǵE2r|̒Uf]vm}O]#hʤ.Or/PɳsإoI͓yg{o }\ IX+ 0Xd`p- SB_ B5~0{nnJٓ9=+z›ĕ2 s^AдĘ[sk?)2L-~ҹzSTgrzO tDdGok F]z4VRc~+y7a7qN$i1JQn8[$Kbf.H&CSdY,ϖ~7KG{+ެTD0]uԡ3Ge] BFquP A5&%("<u/z Ed/ R\=oTU; \8MFǣ7l9RY5^W!|=0d+MQI Ԏqe; l߄zڹTDvW*] \ILe99޾&@_Iárz+<!" A!NH!|^3kY}7;_\?̃[,g\kOړM3;ڕar[,)7஭]ve:b?9qVDF!- n[ιJdc"oڧIZRhEwL #ʖL@^zL[8=oi{y̌i&Od.fo/ !H1}fOz>- Ҏ9 8" cp~u BOf;T@bZcqk8/lB`4n@7 H >t=a.W^fkZ{ZRSh̴k&]o=D_m9ݷ4jzp}rRDͶ<]-)!S'12Qƪgbj@@TQu5NmRQR;fJ4Z aw|=|xf{È=hGt9sUxosa.d-5\#&6H}9!&+*l3&;)Nx#η+H?'rXe+αg=dPTF\ԻLy"+@Z0yީ15 qॺLa_``N+&H nϾ1Rwol ys3+"b4hmǍ}@?q'Yۧ @xm%ђgOq +Y\8s|0?CTr@Dѥ8  6^0HhR^7 Xo+j⒥ʸ3 yr|wɀd6B96J^]fGW7 +Пm](S%8"F )ڏf6҆ѤL.aE_`$NeN]>~.Pr^%=w3|W^"]o/{5̓r.WEKt^,g*0`-gYudٕAR5p+>]z뇴Z:a7 =]G騥4MT5ۄ}Aw{l*D̕S]gT;v^G( Z* >rzڎIIچ5`Iz*dkTʐ' ~]/=-Q#ڽb=ѝ`X* ᆾEyݻ /N&غ+ }scvVJ"B4}:3сV[Y@;v>u-4OKzan9GȄ? 3zChEԱ&R< RNrSOm 7O΁b67J]cjmR:6Z+¥Pu@<6]ܵ$5 #b]O*GNf?f-b;ɗͿ뽝- W9YXb2dC^u2@`zvZgrVIrnX2&UU߯XnhWoԻ yr99PM5c>{=y7 ]J={POW&;G50zr@u?(a>(`K+ec񟊿 G)*%N_;sn0!ƲB_(L"Rp][lV#P H!)$(tw<#o8"r5N>q6bP^dG6L"C0Z_=0gʔJcsHwYj+XW;wziXT[5S:-ijhOOؖݦI[$ʝ[hSu k}JS\Aا"-b_72ĒLQv ~,"|ZlHfQVɠRN4SN˝д[m]蛸8@Wx{<>KJ Ih}@/B荏wM"XLXV̼`9bj6}|xlµ.0U}NCi__>5g6b*Oܢ}z{{<^}Ķ1j^ wԖ<ܵpzmx{/t u){ x7ܤҥYxO-ffy6 zp˲SS\Ӫ; GF9 GN 6gx}\=piCZ[3"N cF1acJlwO44AvICug!⸙]}7w dxNDҾz &(P}<AŊA k3~u_{~žB~9 Z,s+& [k0I 28! K^`K^zL l.:d:;2V^ 2q ɭ 4tNۉ;L{f$秱\|S[ν bFl [N>i jv.fkVukie[%V:5>=-5dt-17R"+Z*BEM"9@Em*Vߩ*ROQL{{<dӧO>}z<x(ByD.B8T%L' Z=r>\ͥ60[Ym,c(@wxK(6>r1< YY[tK xn0;{"*ju@~q1 R  Ŀ8r30y:^OĸŊvغLce J r"f3ؒl'Ǖ6[݅umWu݋i;{. # Q |>8(Zjr|xT+,`(ըfS9Rn-m(x=෷RʧO8t<I&>.0 c2(+MZP b~"Aaa"*i-Ca,{Ւ &@>#Bb;؎z Qߴ 0s;Xlߪ[p)θElcB TGqܶݥP~RlmTO@EJSD!=iAEeHEN-Y03K%4}S b.(= .@"W1{?[`NDHk%;TGRaW/&Xaf$M4nޏ)lGI#$iiWcWm [Ț.Qka\zu} ^ 5c<4il jA?ɲ8E_"Ԩ¢Bokgfk3p&>2]M.gw&PрYjZ]ѥBtI-tN/*  NfW`l$ؿy;&ن"eL>گ~;MM܏9Dqr"n qux+U+ :Sոʙue2Gl9zLJ'wdav=54"؝!TIPe[,ؑ75_O7*r.^C]Hav.Ү|ɲ]W3kߵKQ1jܤ)@zmO+#q[KOg BtruչQEnZZ ERρL4"x1u6{}}J6qDkoACsnd<pMhԩntaFTu}{ORT {1eۂ<|1ojߍ{ qд+3i8R)/HrL~M 'qf2V0%[k}SLHZq5nWq{r,r51!L}SPD'~P% /:ւ L[g&}ȼd'$$]f?) ދGzvA$z4aD̬mW> ߐl"Wx3\A'+g<Wz3ȝhq7_05nTL1 joɒ 9;@f@̓^'?8q&ģ%ED{r ʽ ߱ULAvJ0)\Sye ܱ\;+okcaRGN̬.ҞAaZp=|uw?26T](4Pې ?7Ag۠yfj/ѹtc K^Mg#lh۽nUq1E(EH Zџ W l0 ZD"wd +_P8Q237um}_ )A  }1>!x)HȊ_/>gra +dYVH6V;]z pN 7GuWlD tݫZ6s mu*l`GƤsq+x)|Q3{9m*HۂZae+IBBK<\(Y xߜ` 5wK":.^A!#GbrO1bi( P֫m@+805EྫjwN<Ǡ@G)ð@l2D S:7 }$UL\J!c`ˉ@:rE}c3l-[_ɰ]ܕ]T׳6;HRe)bʕ PVm33d<﫿đ8^vtA35Zpޱ'hP~o+,_Kmq~S CX񒆋9*0e9+ izE4"r!!nuJdeJDdD+4zKXG"vm!c7 #2 TSAjOʝg vёahxqJf,^l];R1s]-g"|ifHl{\7BMq\|ǧ_60wh72\i*Dtצa{-.aX_<\p"D[k 9"v f 2l-oIܲȣc0<>}zdGV2l"4ʗA8U̜m$FndS}*}ZƢ~HAbt볼ǢQ-p3Tt,:wk$7z=/@'E ,hC1'g3f nQUsuRY{ Ww8FvC(8a &78=4\ Gߗv7±T xfhNV͂UV4REi"|);ntwWtS.m@rTEGt&>iC-bv5$ֶ/*-uf4Op337SXT7app&I "57AyX/ ZL ɴBGTw+M[s?Bb:e1ˊ`=ǭpDV'86ȯʖ6_1Vd0m>}_Bo( Ȝ\Yjvs}< xxγ"*$;] +=oc_q ]HuH(6wy|k*예\#',9ލliGqF!$*Rkz`."C=EksG@QLsdh.xqW40y=:25 YltϢjq~٨QEhl3 ohzǯO!Q巓YNk!1m^B.4LnWD&OcmEΖԶq :^IjnYO;pURh@a;Z\wJOA!1k[D<>WW,k}.Q; 4A=ثN3Fr(Xc&k;&EmX_aNo`my]$O*|alES=mX!cYG`+~(ܯLZ4F @pBO93(z>[!<%+1 `$LC2[ )-D}b=5@h'F;X0V܍9o3͵9upxǏLۓH$]sT(A#㬕J; |j5Ke3c>. {7o}Y'"/'A_Qo^V9E l6fZA~kG)tRfrC7Duϗh ] KV:(\8db/X\(@ t/,%G`|Ҥc0 tk*Y>|^B7.0eh1U)r:2-9m";^34r"4zڊ㍍4U%:Y6'f>Sd@E)9ڮpd8XԤvcu]åږz ,,+b}aVdTh6qOEƫ(cYJX/om[:# 2p)XߙZΎx+*1$1IL:&ǽUmپ[hk?ӆoW/?y)o;='(-58,*mS9?Z-!!nPM-5z'GbN7 n`"=c{IR3M;6-hø+ "q9nA)RYAſnJnZ;b4Z3aaӌ6z{Phw @}.M4Ԁwh[j,tvIֱ9ŮEmϏj@{6oIЯhV]B)K n<Ů~PÌ61V=j:L뿪{Nv$8Ps~>R?!AHTYH5kV;9{m3[:a{S??NQڹ}l4 XnU+ُbx7yee5z^eFE"7mfH]Ү-6Bh@)Ò{Ǯa6fhp>SޢoBؗ0N~// a~j&ϬU]I{n3Ng eߕw^|S}@{W|UWI.g.ĔHAHoN-ڳ+-^zL*m;`+|33t$$Tyi炈`f ҜAbzn@b~q4#xKf' e7)QsEV`zH#nUE.f@[bfʼkn8Q.tˑQpy{Lh.C֎."?6FdBP_<{X@ 3.+ii5a3rL]a,UG(t1][SLtXn q9 edfXiԨi%TTz)z'pCNuN0xffk"b$iz|6v6y>f>Ϸ8xꈩr2QK'GĘIkq|$E¸7k(B{ͫ,˿[iG%1 }(~ۖ-y ZY^bSךXv(8ݼ+7Sxm8+'\Tk3}Lzzi@dH^-QgcȞMwA(F^ڴ%4 u.LrZr8';E$ $GԆa IؼɴIc4'VsPqtmAۓNk5G͉4 ?V0r2N8(; W+ٛVL}24VNvեO38]/6 3x,%drO77^"AM&ܩc* ŋ9QΗCDC^Z71ܛ;44v"ѭ} p%@u׆i(ak uC!NZ+Ie>kߊ]~QF v }umw{4">%}9ԿdffK^Wl!Cm{0u+kj@4dJ9I1\,3Qg ]w%$_nϦle=0%WPAbS?D"]b5vJXsdL^ oO VU|MMq(WMDPwM& mδiԃ@[[䳻a8+>l Yk`: 0g{i/|;ۼHw$ٙ;X Ryv "?'uu4_eq_J^̓z`hT]_PW x^}xz"RBR } zv3UTUi|<2ف轭"UEg+4mR6*բ'POsLRDժkG3zp!tO! yrFD$RVg~*Z5Z Xl[P9qwBVy-qj"O&h8D7_!~f e9MfY YJns:wA-y#)AԊ/Do*B0r)gR*0H-_]G_i҆zr71Rhvsrmj}6|6caU]bnjl |Z5fqp3ģtߎqILDtEp4fN6q'N݄?!UӅ)uo!:@y|!5VnT0[܂U)3E{eBM,zp`Q2A_ǭ>$-A)~ LCY_c{s.I߼_&鲊J4¼(-} _ڻzRۓɒ<'>⣳=Cʴ]ш'Y]wL3kތ8M"RaZ2룺^h11cKDws/pf?\ J7l1n7~T­h:}*S|\"dazU^zgTҟ)ۣQ>|0Ru%rNҺl^=]"\>ӬO M-Η |ivt.5n ~)ә/"">

    D+3G9LDn7a ;,%/">ZM5o 9XǽƕqWŸ ݼ3<L'Dꖥ4B/y4x5)P2?KTn:ءY'Xڨ1 t/H6h?ctEs=/dYR!.WveE!ˎW?/alxg6puw}kvtffSz6jm (ڎgA`?{r7r"q&bP=8 )z$ 8E)朎lRYok }^/f,Ĝjg_Gɜ0Od۬)L8/38*kf@SO_sԓ0C~VJ}Eikap_`ge_~:5 ht飖0൲-Rp0[1QbX"`zp]‰80P3}*s%"EU"mԀcaW[_`ďp5?c!v[nCSXaրy΃S qx}QO\Toi ,8n[ 갖o_Ҹ=`9+0gx=o\-M)(-'?}*e:,|;RmKqCPD Wv J)\PNz ̠C98=Kzg˓9=2wapShYR (8eׅǪk3e}m]`\הwMcY1=CƩ- OFIG㭝8,Nj1ݿn? GۭJ*Vɓ"諎W>|jĕ~_>Kg-]Q$_xZ'I3)bC\Hpלd6,̋TA-eB >Do|.w6 *vC  օk?I{Nae/3;/쀞t"BuaB]dj2H`Yϗ~-Wk-nįmMwK- |jcאR,PE,7EpYͣe,$㥴*+2㥾7PE\ΪIJ/or_p[8/jocsR*_"- r; -ð~`;#T{6-313ǹ@kW]>~Q26.7%66v1PXW=wlúi6 xpK?+ &wu*bb$_p|Q Q[V { הwEakmEj,*zDam[B3k} t}xY^`;@]S68̭fx1;Y׀耱yv\׻*^ΙWM6ԴZbp7N%fPOGaaSjF"gn ,Vqv~݉440Hl4lpgifk`Q@%Zwb锚t _._-ONKdJi]<_'wk8)iW8;g_W6iX{ꕉa_L-׋q}֘<|74,SO'knJz1 } jRoFmp?%,Q,MU'kGX#-v_wsZK#.i0Q{{_>N?fC(g).f9wA3 {bX!;?eR[OȐc8w)fLlp!v4 ->9Oh"+ő$RNAڢð~Jn s/y7wwhmQ'!qyӸTը+$e{3-6~[NЛlEf| $E[/'i꧄4'I|[k0gXߵnf]榘g~Hp?B!A,^Ы=!s{ kxQܲw<K,+%}("T/B>\B8fe׋4zckBql'͵4T[y^$"Hˋ?:քf@η5ѡ)Nt 3]!RAZv 6j[w^rpO5_;9 y[n!E&UDx%R"!"B&%$D)r,⺘  A\jb. 9@rhp})S.il`wqX<|-s8CsqaT1f8?Ewpϲo=wBOӵ;2FL+\sYDV-tl·Pjǐ>Mհgo^w ioqh"/v.@ܩȊkMr=*aV] c1o@s~X_ߞ?^3\d݆aSah!!g)n5K}%ܽde;ˢBQpKK)䃈'_)#3/;BjZR d4dk71<2?giV-4j )=5 M59-&L<w%2/'Ѽ6ˍMel-7}^Ο,d2Mf;TXarye2k',s_⇐A6o˿ԌDj3G܄x <; >uv@=TX5o9"D>Մm]Y+ [@r^K-*'yHqDvӯm^p`-_ }X~>S :ϙ 'OFph"+J{um]I-9X-Bh4#D[<5o6O!0CC"0:tdݻ$g A\1VbS#&3sã:Z[ K_h5j;&>;zzb"Ma^fg.ՄZ q=4^-?g02M6$9r9oslZVV1}Y27q| ׻d[ߢ2WyK߉$Qnagm)bdr.sujP6,+s%_ZnJ=FnVF氈o^ E:t-BlGqx+׆zw 08[sk8Ծ`?p˳K{R~%).=eY [0 F|&}̝,e0.199d)4ļ$ _P#JckRÆ)Fvc=`ɧ.wv.\Ɖ5g>XK3rĿ .-e൭Aed8`cH!*p3ٚqf ؙElWc>k^}:֖uݬJ]:{#,0Q6# SWyd.V-}]an?^_}.rPN::K &")((q)h՝0M uEa_Jl >.SqyhR=ᚅyRV VhC v30(S7FswU_K=Œe:gO!OEbbh?' ZGh%K"Kb;&GbkxnOڥk0e ѴGk , Ta "qGr<"e.wؾmwR 5 XJsQ}, k,BQ,bWs{;˥&#R;?]LաQ8xٲky))^]} u7%dc.کׅ,skӷr+~G DYTtgGor:)GQLGT"jV'25K eNa#)/&$a,c5@9}0T&M'5PMuҐRAV;8bwVC-WD'K]REnYrj%pw^“ Hf^^j}^GQA!GK?no%O[wю%1p!@ChgDH!q4]b^ٞ| j.BB6|gh &waR`.T} 24rV߰faˬՎ0R\3Q LLR5ah/S+̘7 !yW;w`6hp3MOz!~d7X:KeeQwa?e2rL^ٕ5OŪ`ݏ ZQ_No׷ Wk=_Ӌ&s_W9܌'m}[9mLs<:W()cUF= j-GBF=7#$<ц>re]m\- F-.&KfJ+֛LLTR%֤۶ɚC}j; yV,yk[ jOڍRl~f{ eʀAf5ki~ ۔s=Ao^WfYrdʀô۫rp,kfv!E>xw)r!ZLi_xfd9UPv)s l V(J;뻕.wf]KVzR ?DXJ%%StPv7]XAkT=ϳZaW*Q)_ؕWjxMQN[]ܰ.h CѲ@ٛ'Co u<|xQq:|/S[W'q ܵVBttOKM!@tFm=_k C|$Ud$V }ӌ2Ӵ&)vj.Dvn.nqJSO}`=SSo/3Xy]b1=P E\y!4,=NM1+qG)*<,g5`aa*bwS i /er{f>J ^J`zqyIdavw_0skMt`Xa<.5Ue1/K5QO>I`ngOP?GjO%wYzU5|f ?D[A6ry2B~'qhz;*?N^ċrUܴöx:eyҙL`́f+H}P%ݽ;vh!L F9.Rvf|RG[ۭ2*Bkff:RU>* pW8Ԏ**vlCY zyPiÎt4>9v0=} *{0bCÚƱ];IED9`":("xvJ *L8H3Fa(xQ)G~z UEJ#t&KU:g(~,",'  v٨֊zRY/Uʺay-FQ@L}>V|0 ]FPnHl!Q[6jDz2Ss j bHf^TIa&-}ְ{Kd&^?ӯ/l\莶lȶzZ2Z%_Kn? M0#p,jWŝ+e`!n]kJC$inR֔v|Wѣ농ymX;,M'Ta?(26Ow)ˎnKc+u# .0Q/& _HeГs|raSؙ0C3bi<[~dJ)z*&I/,^q ڴ螽i!u]a76OI6N1Ij=ov?y[2倲27 Z/jSY8ȔNAt>"hso ܁ sIț쵲K+PZ9}MOk_}CofrkڐJ)ݧL o^{,Ft"0;6`<AXd# xӯEoZ\sHY%[v>N2Hv2fƏ;E׀ԘP(rm ѭ .d<0~1*tF%wV[Sa&IDDJ@p~DnR2cz/[AQ߸9cl7^wW2ɫkk8;m9˼Ej87`z3$ -%+$ݼRMBCˎoCɀhn"~$) H!cye&wL%`0h cSO z{&@u -1 Y}Spr5][~i`^[r4,(7< l3,BQ9߷7GʯlYV%\'k /Ͼˎׇouz:20r.A sRZz#" oR+-T?sb/ᘆ{cWـ,д'X5;TeEJ~|vQomznAڙäkFWrlCGP?0X9ϓDxk<)ZP U`:]dmANVZOwx]I Ri3 ^q>R#uw*}V554}0# yk#ۑȈ$IDK[ GIWܪݓh{O _Y-O7IDvnx{e aQhKb%p.$)L;< Cy(e.Χf!2fgn5O^_1bw2LmKDo_s4tn0WԦ'Ke@j%tuEJ&)SNyG @1'/ 2iߴᚪ>s9J~]Ї? xa ̯ ̓e3^,Ni 䶙s-Qv⼴H7hHSei7q5Ttϡ" \cVnE G.ֶjqi5/^lHMv{X~nL[Lexca[[r?1[sX PKUtߗߖmm:qhKoa‹YԲ |n3s9_z$ĕ9B?_.dk|zeh}[ d}䲜Ӱo=Dfl9f9@4Q{+Kcb܍$thW ޳LᎸ`C`Uʳ8TQ>kf;!hYQ`" >`9K^W__Wwi'Xdoy軖_Bʿaԅi5罭}/xUܽh/12H2AߗwKp=0n-\&]9LD3x/sF; ۺΉ௸X<0-U@p'=lg.`" =4rDр=^g )3DD)|u&䯶%4ĵ_/'yL~హ HM}23U!r䘙:\Yϳz=p܃P@#nUv$ޞSN0/A4_y9%`OdH 7E$E 0K_JC_@/nKص?Ta06eX! Rҿ±f;7,akp,< Î]]@M9ΞѽseQVaa??laf3X̟qFl{e%Cy{(nD\`;{gYAp wL{tqGD>}L֤_hP0d_;%8<3=`\֡ 뎧|g}E__H74ڰ=OW2Ujkl焥G8BVx ֚AHw_p 01A;@Z2H1Q~Ȳ6l4;"2]bѬdk3AsOi9CцL{2 mguUo֢."yn}fYߵu1"r#puZgw;5ԑο+&M6}P wl|y|@yzx{ƘXElY0?OjWyvj,ª,P=mF֣Py.AQ8Jwp9 "Ѓ !L<x@;fcml?=9Ffaju-Q0DhHOeUL "v ocZ"SP9JigSRD.@ (yE@,h|R":z0[Jz81"0H"_dZhn|'kg/+\OyVJ`$/RdlPz_nO&@DPH5tLBiBX !܌C.Y; Y3n.WIGcftKVk&-u_O^ZվaDߴeWTƸ!.2PNbRe п Z̠&=(@n%*qW. b"ptNt+q0:VN0AkCz$05Favz̖{̙_73FWʣMup鋾 x7cgyh&i]56(sk!-]O.U ӻ RR<{GRN/ۼjvK*1ͶP) 1 8R&h&-)pfjd]SLncG;١=Dy l9 ;kdL>NB`3,UU2~V4АnQnVb¨yg9|T\{{@4 l[*)'۸"6{}ʲ˟YP8"nʦjҦ/mښ.o o[nK\۳2bޑen$X͖l-ޅ-wEN}Q -!/ϻC _BpT1>cdkg\ɺn=61HOJH`qI%Yy;->kQ/22b+:D̅Ƽ;sOIO|WV? SĆAB(?B004^5T/B 8Q{{[5m{3v3sp64jsn^6G%6x3HLc/P㌬eA!zNo->|GJ8D;jlz0 v&}=2vP?GN`L]6 MO˷0?Y'm3C89yh~D\-8w aɵʛ:Kydz@ߥ 7L ~օwjv_';A!h[%ׯ,[4>|/Λ`4=ȷ(PDR+f\ Ha9T=ꮨy|u`j I)cN3rWZl7< N 7xV')M: XI4;&ʉH q ?uaVcu.'L~Kt ) NO>?-pi(#ؤ%-Ya~ Wu9òQcKXu˷Հ^_}_"gϻ@z=w>&DacpFnu}.gJqEsSWmyP|:>•)h,/cQ;;j_ ;ݍ2[PwiȲSԩ0xXɖo刕DN44lČ V+@,LZ8 [iր˩>n _.w!׀Be‡/?<&hN3u!= /eA/kB~*w 0d 6mza[תkwD F9I >53ijs?N(9]S*@)&Nb IAJNUPW7&C;5= ci3+G"3(]QT3GmKQ-΁ Iq+eV섭 C˄~ =zN!-U$@z؇O;.lNav@HBR-4X9nSFyԆ7#)5C)jj& !!ƙ"/ 8zc䳞zTrYDjK(c0Vw@0LC;f9NBswK+u@7#Fz9/Oo^˺ޫA_z/*\J \BbBYm O}!YZ^4ϻ񪙩'2[Qn@mN֭*,;v1AUm1L#@{cZ̞:U+J?_d Iff|}ńOr(]h9Z0M71_ډi&v91sB+ 0+ SA1qn 9 fIS6y5H p_Ydzx_mx>T_AB+w~ݳ:"d0:lOd7aٚ1J}ZD @k9o*kˉH %"$%knM01Wl!7zk$ zZk=)genW:]nIq37L^086i6!9v(un)k%Co;5 "oy"W'5J'|%4I!6}ȵJAmRMWG0bkQn  Ј2~\Xs5:tgp_mDwʗx>{aK\`0ˢ.1}[K05wqkVSёvyDZhջ~iA݈V!~܀xT4|݀F&+]2/;/h.x0 ЃJ4,4.' ioVl~ǼfY5LWDNp"4n:Id<5>87:Z\aB"R,_A鮜Ytߋ~/{A%|}EPpd5W\fx1թI ?b'ĮiBrJzO#Lnl8@tAa2{ } Tz !swQj`thYJG֊dNk;ռm,OO>H]'_* /Լڝ'GGVLq:kqg}<r$_g&i:xl۹pۥ&|%{qsMCp;jf4N~Jd,~څ!wi*=3¥^|ᦱ7Ҭh-jMfO8CE?j%zu/ j5MXil%sL>1H3%YUkm]딋9z"&׀@USC/fF1LBÕL p,KxځG ٝpؔvb h'f{}O Ev9H/_aX=X:|¤?UH`{Œgہ*RdF\=S@i!bYcPEa=^ :`C l h7/Z*0*T TNr8 VW0qV&**,<+Y>Ud>rowR.Eo>6{FR3j4 ?f )Rba:U :*B,r^L73ŦAQ$C)$ YO"*t'T֍rJZQިPtaLBr&:.ހM@-c3~z ?G/rϳ~~r/||~*\t!KetD]g"AHx"q XS/Y2|f<-%CQ. #m=3[l[0Cx+HDCfoӠb~/ zT 7xxq {l 0ء^-v5cm`bg?ȝyEbvG98ڤZwBH&² P8oWd?^㎪_/gږo%ӯb:{Opb.Rmo"ACǎ/?~y:J'*Kl.bwOzbդY.$5M/h7/·k߆`bvwbŋs7k椁+FH(ۙPC+p/ax< b ݷJwJY_n/'ތ   dn%VA8^[RАUxqWFvV+j4`xVLv8oҠ{c n"6汚'NcfJy*2T +&Gt\uQU_7]pn:"Gp_fPy5=m>4o}~۷3NQU\"ߖv\oOe6Pډa#1o%@u~~=(NNKPofXfU^13N iatu>wJ) %LIjJ3i50ϱR"ݑJ)9q[)OoFY-hSGLr+fS!V$5nxV 1k}$(!gnf^u!( րU?JN 0pZa] 1ؼYme #=wׂ̑*C%meKiD7B^:WwGVCv!}wޝ7^P *r v(՚0j }RQt5"3(sBCٸ<GhBàP$xxӧOy*S)P[}GG&l(P uVh~K)f&8«8ؗ M Z3.*x͖+]j܁+MM?Կ^!"#FF+x{yt2tbDLik9u 7rjY鼶'Ѽ.~,rH`亠#a^mcնESN"K8(yT|vM+Cp7Kw"Eq+кz#W Ҟ#t@b?h@0[_#iYH-{z)(a]{Ra}g;E"bAxj0`JhQlFX Bxt#BYO4v%!gaaqde9nvG-_O7qݶxIRUC h~,>ytms"pU|"Z}WdGH"2w?wHz5:n=j'Բ8e=mAK?m~tluǚO3@]hOZ嗇.ɺzŧrhAC?+Ϟ5Y} Eڬeǣߚ52-[%z|PR2 (޳̽yv`1@ݶ$ ΩK?|}17('3{>ݭsfj† BUʿ0eT&ӯXfu2c/r%1]'ޝfvuyJΠt 8ECzq}(2 +9$"( Bw廾Z6h$+N@L&yVKKQ70>a"{8} ҵ|H֒@FJqjV<]`N+\2^ Aʤ BdJ ErTd\@).%݅*o()cvJc@ߧ(`x pF4`_6S":Eu |6 N{=ś/"0E=̹ꪥS@^9OqnhҴT 7+B0gJz j#L'n7m 9UkjYjRfb(no]} HQKlÓo~0]'+-=`GeK}=x,랒0lvRv |;A&1Z]:̈́o&U,r"f0Zms)e_\Jˣ={qx֪shС1w~v< fHwӯ"qh}z:{J)>@' ģN"2ӖBDq}B ՎPb)X%fQԇ;m< mDm/ BMr"w\هO6hML|`*̋\toJ$g"LgT W)BHl\E6ӎ'מΎE=5fNg2߶VU!)_˚-0keA.woݺ^nW={|Y<>|$uNw8f! a/;3xRʨ2 8(QUydSeZUPUaU z"vY~uܮyپO^T4-L<9ߘϤ)UhlCG&J㇍5=<U wy'ZB棫;uREȅ% UQ?^7Ҕ̈́Nz&hB`P!EgVNrdDqIobܪT-FXm/}gAku"bZ䲪`|=Eo YMm=5u4ޘGMKs;DFc# IWSdԏoe߬p8Njt3ۡj4I ~f<Ɠښ]5_F~E$% Nj4:&DTP-{ )5直94bkYH T?;ffHEt?GލtLκZTJvTiu/r`3 RV!>82y>Oys25Ok^Uʿ{: nj<o4Qa[]^o_OˏȕWcNXTE]8qRDZ E2g `d|y-wʳNQ +{/ + VfFG5{`.[Ak YP`:~m} L!F5f*88>??<+6UQYIF٩U@@vlgqa6 xUo}6k[+Fu嘮lʺyqU/D0>D#BX(Y _Hf ZgƝT;"D|G*BfUK2'Ad3*X+~rTjeVB2J@PnVDbTPǧƿ!?X>!*M.Nغl vR4VF=@@b+RaatHYGz?sK:uDu fooGx=<퉐8(,D 1z?Fn sJߘ.aRarv[R+df{;tec=)­.dn7\] O׏Biqwfyŋ$RHyk,X2<ۍ#VS_ La,G2k9%1)F6n߳5Sutye8? `Vϴ75|_+(~qOIN1_0>^$ͭr\{vGTfWV ۰ Dkj Mq!f˵c3)-~e6/R<'T0<-et&o;.#t@L ŵGRCaUg`|8B<Ґ }u瘘]=U;*w7_AS"x(>1}e\D#'y2tW9iuR$ɪe7Zxr8]KfiwJyO{]h a۶-sjdVO{Nt^Nn84L3 /NEL8ոΒ+&I*u`Kex*Hu֬$?w=h'K[;mgӌSeޗhr*1YUk7j JãShA巴:,%OWu@uF JgOڃӦ;TV8x{p3 VY6Q[ 2Ǒ]-Q0X#DdPpG wSji٧/nxkx+&k;zd-QU."(4 K!g D¢ Z}̅upr>ZB {fyt^K73>r-&l6g2a꜅;ÂSY[q9:J[nR)!{xqDǬ yФ " [ԈkUk2sT3/#S$x?g1LҘSc &s]gW@GӋͫA7I[2S)y`lDD &ʁPR%^kS* 5 )HJu%QGr:b㸌?! oZ?we_ = P0;X?ZЯVЫ'2`b{X?#_ظߘ)6ڔx[SiVicLУYfsy5&pt&J(jqm5T4m52kVv2("~CI. '!}:?e|BO'ݘIy qbCPhh'D{ڶm_Ub?`geՈOm-2l:L"cL2oJSV L^uiu`NR V]aUu@ ͽ J5X͢@!}J7P\7-~&c@$J Z39mLJnl`%rl>Ehٴq:`*+5,a9Lj8wdwTB}d *cKUMF.Te+-;[H"(0?)9 X!-DDHXubA"ʎ8(iTƟ4y>_<q Ɯ/hBޥVǪUY! x` Hi0v+KpwkIS@p6ڈLi!Iv)̴ TcXso1$·[#y;OD?;&&"rĺA_ӂ~2%(X6OuG,<B,j"#l hr /K-SZ (G=G0ON։.rzIdw`yճ5w-3ȀZ{ys炻+z$X•V9DK멲2}  d>^RQ mՂBQI z06MC)LQEU[/S=VOpkC Y1miame+ʸlYBٙ-H ut ďE2,|]EhLszИFK7~ SV'=yYujmHT5[*cP)n].ςEUS}b/K4hV5r{9& vT5~l&٪SfbtFʪ{TZ2&d-m%M-MVkկN rʓ:OqFق9N|;ڔc)be j9 ٳ>"z.h4Pj*]] X?Nŭ&ct %T<Nv|1u'˫mjpV1JXwK HYM0/=ǂfZhAkf߽I~__D~Cm btjmsƳ9UfAcbJcʆI<8&ߚ %7O I`<\f.ѩ(z`'S@Nh mU@O ڽ@XEgpuF$]ˀ)Sʔ:=~!hNI@\ei<ҭr^K#u|JN跗 ioWtUT)՟cV*- PAx(IU\yzWô_WrRT+" sB B =*L1H9l"D<8*rQCH 7QHG -@DqD F?^!85];L5E{+_2m;;<[ܬ/( 2 ֊+_̈́ΞKkEvx^tkuTva> ZJkXNk)CD`???+H.2~EtQ⽽O'ØKGxG8b)}1l:'ʝ!:hK~T!P~ďg"N>Z/I@IH6B~L*'Ta^[(Qwbf=i' m@qb@ź'F-b3_o2ԵhHӦ^UlPDtQX |e֐#*Kv@f.tw uҭi-ctrX6X1u[UpΡ- R 8H yէ=Ȕ: wmێ!鷲t+_m=*tw:3؞\(Mз\ nqgvHB @1ED#TUӍ SeN I"!u-/u z˗4-jq_pΕ.)?]`1M<{m2>W[ߗW+ ONɵXw;E؎,"F -ic٢ftQ $<`'*>< ǰ-%MvqewmUQwѐ;ŒNk AVs=.E9?މ`%}LZ%GIIA{is\`R-azlƹ{^H x `7x<)y 8}ˍއ5[,w/RiϠk3w%sY)[.=u~K~Ș&G& 6R!P"M] yvX!eg*IKͦoBKꅱpNa@Wmd7ga!K]}i ToŊA/Bf: ?_K]ܫ r^u1JS(27 C&:[F̢DBA9O[R>d򌆮uNC+]g9~;ñ=zj<ۊZ8?~{Z|;\Bߧ=E+y9E_- Cn& L ,z,56pʃalsG)١"G)bz],E @>NibMj&ZQ_U+#qjdmvtb*wwmc&W&W~3M*7TE jHf̘\xԣV=R5L XQ_!g <_U菃Wj{α@Ya3!ֵwY佯|AWyaUjMJH' uɴ2j6!ǰYaY c^@58w ?,(aS!ֽXIOXp:H{II@O[WƷnɳ &"(EUv4_ilڣI9ĵAgv }-wpq呂uQnӃJZS:]ᦼ}mzob/@]ɪ6%j2teL]5~<:bc6{ަuSw1 QՈHD($8ٱQ4Ѷ⏚༱2DZ=K݃VS|Gr{N=`.HzbwXd#BywqM~M 9m8E|$w2VqULXfajߢзKPq0PMӶ7nO69m̈J<o3ͺ؉k.^zB;-OdI{s2a6+GG; 6s TT9y_ 4ufHEWj֐});ӘӥBZѣݪ M/~VO+p߂5 E⋙Ϲ5QSW"y^ 8Ο-%R4U2$U\Eo@RiƩ4rĘqar7y6R5)+tÕ2WZj92G Y?3uqdYOI|l,FUU#UJh& t7$Zjޜe˸sS缓n~ʂ&y(\&H)r']M,BW/5ظ<p/5]5caV,_xHHI$q5)GV6Y4EXP a5#.E;s?'7CBRb6\٥Idd ߢݝ0jС '3]8T ]hy`2]C-\'4S(0B@Rk?cKHBf=fvb'UZpzWx<g539hrݝ _~~;ʼnU߂`nټSL%~x{usoMT%Mo%(:΄=nt$"FkRhy/5w5CQ.+2 l8"RKY ڿq :s%Pˁa,QqT !qU( ݽZ`f.1X{*I x!0k I=KE;[JDv4/pVsF @I5>Aߎoƹ;'~R4ְ9Y<zޗU+V-M h\Ǯ{M@z.^Q]zB/38\Î;/0yU^I9 @[vsN,JXG OP(7@"( A@b@BbM95EIlѺP(f"v , 'F]QM\Z]Ny ]eG%TjSd<-|g M-F'kIиOrh^i _Aߗ[~_7ӻy["Wvby, V"aA/?Tk=Mv>&2npe+dܕA18zQi,lxQ!ٍ <=2p昢o' qR08s9`B)cf >DΈrA,'1o!UVe b,,:1 xVstywZIcޒM+纋#YPh;߯)qA_Yg!" - "X1b:Ռ!zMZ"bޘ#3S"S%<26F^fM$wl0O{Jh­n:-@IҞI{JmOЈE3m1Q4Y CB`iL1ߣ)*;DrޚFp=2=ԍ<-.?I>N[5Oa=ϹISOi+}5 _yW(c}j}Vr3e4y(P{7MqUP1YqM' bPN gC}cvL}eu"ъ&o9z ) G1+ }UU5Y`-Hw$n埕 LWOFkP֡ t4"E)/FU=6V[d3y "oQԞ}7B֓r6nϘ01Ģ؈Y{Gt<Np[6]<Bf]p 6{ߋ/٭\<ܻYW ѷoLnCÒM,ByCT]PdHB"/9Ĕ.GUPhk@92d U) Wo Vn:Q/%Bj~r1V(Q&wycQYURG E.p:])OQ7/5` SBY\;cx <+ D1 GXfvI+9]m zW%zsWw}JMw yͰ!~Ǐ19 훶T :2AtU ]IFF.`#YwAݔ*+՜Y>96Etiri,I 9⨟,?e~u3^e(1}(i7i[=̅U-cq8. f(%g-OXXRXϙui[~p/ߕ~]_\|OکO}G(*fd4q PS]%V{ޞV@HXh VQI7-3_T*bc#<|#lD!JX͹36uvDzDRN9#b&ǝaL$cs""m|}s| Iq Z%; d]`'+rZQcNן1ԪOA"u{(`=] bΪ+@[W(^+s7Z[}iٍ>83dYGf[MMDB{ZuMŜb,@{e!M>f;ϓ䨝hUBŶ"wrGPgn-:Uf>$UቈQ^MԝOi'sq _wy!u9M\1/m'WywiAK@[s{  ~BzK[X9PqyG 2wZ\kuF~GmD4H5>괗sӕ@}"βBJyi\@[V+EOc!ꠍ!b"&<;X"~!(@?mT6ܗ,J``b!D"S\⧬i`pfiA{_(ǵ嗷Emhg6Gks`?> <`F`mdo(cIkTIcDY$ѷ}̀Uz1y#&ȑhyaWUOggd`5&^"5?=W3я+Ц6\|NK 93sh0fVshVS3<ޝ"aI~3^O+,6Ƌ>AiU爻ʗ&s.|i"9{sq%#kIJUìCՂ ͡UCRWcQZh@[i3Rqu}Nb9M^%3"d)^t2B2 d c36fszЬVO7YD}1-: r2a/{ʸAɎ.ap.jXβk̬X+vsZy&c #щ w!U='Unc6<]\OA]fšfvjⰼ\>^}#{6~Kp_2ѐT2*QbcCTUQbԐ]TB ԇ D]TT9zHG@5An6Κ<%}u fMo Giw=fw,svנDA4'mi+ C׽ې}IV J xBl5=K>@kO_m'fL+. mO'̿򮻠+r3neu$̺? $h|r)7fq * V7,t8' WRbb!t渄,>@ XIO@]jK3`abeP9-C x_k˝@ޭ~9 S؈ФsW 3WSisjxhu 7NvEپ1BSz,6G_YsJfy־Lo93|^U+n?}_xd gBtt *R|0DtYYcԴo#u=}?fD 0ؘ-m80H5'AuzF̤H:ͩӸOcɫzjЈ[)S&o"kyWU w3[E>C 5Mu`؝D*˽4Kw@p'}*sV+rdh=)ytA`x09>I ohYݽJ^O`TøQ:~=SQ)"3fE`t!gj ۾=>Bv"ڈ>m($2UU=R`&B)Gwz=$3Yjtz\=,3C(`sS6B Y@/X`IDAT|"8 %~;йVkNv0!i`uVuH9 5OgRT<Y>nUf@2ܚN~^h8N=yw>nsE3_";`/Ϙ9tyym4fWw\c?KHZc$ D "bX)!DDmض}6&U|zD7Hxh٪i 1FfSMOV=9 aW%oD`[$PO2 dO٦W)lfʰK4UJG3qL!^ׂ;ӹ#V.JHD9tH:T!} S]%i?&VT>9&E֘L%D?_O<:~,e(dҵږoꪥIaVv ZWfNu<}{*}w{zQK;Q~~~"1{ 6ObH6#!0;mxf" B(y2b2*!vk{M[-Ix]R0$6.mˣtTb=jJ1/Rr]ILl:Wn9 h"B,ugT5)I}]9aYrN4N/[>R[G<%<ʀ=/@f+/v t3=25}Puh<OV ʞbJ%aMJ|KcC x DLD^ +kY0%&8%^K)nSmK)%L0Զ5W*03`mb"4iEyT}i_{7shS"JYA@/ZMK!+YT^!ֱ*3Bw΋vŦؗ_Уkh&1;71طz֮(;sPӭyo|ѿV[3m(\a<[7@!"Ф]5'rJ9&1#O1~~ǏGa1Mܻg@UOQ &+TrsQ(0R&R iBXIwftʐ{II C 7/]:88LrN"нHT>1/IY+Hhdῒ{r;:*'vx)lOfO@w:Sd0NE {E=SXgƾ_^Y􅚟ŷϫi{1@ʬz sћ0fo~%XAhelAl.#ʡ퟈KI%$bQulŁ8~|jlQc欒"0o ٶԨ@tzmv4L>CH%a>˴H.5 1i5EfŒY|VMnaN)` xq~?c2)'+!(궛.L懊¾QA1r؞tSUhbB'̴^}HvV.n)M-Ʊ85dn[sg s_8͔~VX͐TԞUuqDZܝ{s AcSx{2BPQO0ruWs xQy?Qn'<5i˨9?ٜv] l+.esq>ޒn/%\ϭtOo "&ՍxUf B`!l$9B!ۃUQ(LZ&)AD1b+%H+Iz@]96?]QF'muqgHPMhJtiʲ%?/HQȠ$4ߗlD8|-aͽT` mC=D(`biwYЫ>j';0ԥR} NOYO\-I|#U+H|@''/Y,O.K2S{qDd-ZKkmswiF6@d7@DE%rH%F==x`T;JWKym#dXU?v(i.=DL( LU 0O BQV[o!] 31sjMǍҧA !X`5;#kâQ>#%-HQcHNmKjng "*edg$jq EPN\_hL cW\M84(-*[T3Y33iY4JQ1#Qz̻0vCqQ;'fh VFLJHVYr/Ip3|cO2^krbΖn/) h;Rlck(? J 9v.97&d<{}!7!꼧ڞZߟ$Ȕ@8%h;ͰD.Mǐm}?m agfhntGO?E8~ r%|B mSw TUR>BJ`fH5<$5zE??72ΘJʆyv^m%uSyh<)̢XJM<2kghڗs_Q )f\h3PSftNqW[o|ZWU-h#s$ ߻w*f?{̂P8y8;ၘ) @TD>?FNVU(uk¾Kѝc,jqG^2{7ذ %Pd _ ٞSpO:|HpߙF4}!SI9X2D]Ð!Gs΃*ylPgSoVX_PSqّYbwK1oH)0Idw'bz6N2WJ#.t#֗\٪*V.@ÞS0;I4a/G޶=mDLUWlBlZdVUtp@fw[O@@D9SoG4%kKf{QcQJb;ւ~ 1^he$E ]E$*!"#u['P'GWpkil^K4-ϟPx,yx-Xr{ܨ(\Rf 2c<2Dou^2q?#;ߞ.\8rL*ܶf\Def.eʷFR08 -;"!&Q(P-MR9(xHRu WV#smVPQp7J9hwpK v^^TWIXO\4o*9L0v0LWK P&DLJk=$LrEӮ:X~~~" >sA11 VſBX{%RCDD"(@̉Z  U@}SG&yw!CqE6,ӭ0\L`2d* [.4(]{u4Yn>a>pzKyP.ܟr @b+P"또EKaAgI K=zqzy tOЕ{pN`Un˟8:eh9xJٚp wT ,H;s}AF^tj~(ȧv-0UĬ&ͪJqT}"?()e-$Kf8_'rvCI(y]cm6L[5 *mD Ҥ+)m3;sap47"uup^oF.~1b*NXC5ݍ_mX9'oG[OU{3Kҽ#tDsD"ID߇&D@G!X7#D/ؔ]ji !`ʳ$N)T_DeᣑdQB؊:7x-K,5'M@:8 *Q'nN mق7}Q"yU}F̂O'|`x$LRU!$6؄}!oāx˨D fa(*i.YiVmkJO'+o9L7W^җSRW~,W`ӗ^'D-]\PSU$R:.^ :Ƙ;L!PBd1V zh>-$:MpsC)5J#"S;,&!%"F%fsJ$b̴@:p"ӡ 'O G6T34YH6i7Q`+=Ѥ[Z_Ya$(TGqvmC)AmKBx !_Ѷm!-ٗ烔y$z+#`_L2<]ƿ4qtgLhm|9wwSxN׉ݯvnS'?{9B~٫Ӗ{Ӫ-G/* S{F1y)f`:TӔn!׼\BqrC0+AS`$*T%nl@)pC=XQFF2'JQ32-ido&/Ѯcڗ!1Rf?\8P4Uq;/<-*֮،;@3 @MWtC[ !FDqE_;X$ZLLZ{? Tq,\-+\3)ORynˀo6kr_oûz'b#YH*h[ECUDve3=cV'N\ʅ)(H>2UŌ~@#ؠ S2Q5V@ږ~)` J,j+Rf0#v&"sFYDC - ]T|Z<TaL+5@ɼr 2S`{a>Brfn&78 1"dC#\0~.Hs}yOtW,5/z_zFd̿jt7=vU`5w_G^/x;[1ۥ9m-y!%uƼ UrPG$?[>l{{tD;z#)R%.0IjRS 8EYZ%i>d` TX!([o_O˵]#LMlBCzZ$9x<[̙@U'2%@ nFx&2tN514,6> z킥*6B)-"B:tN^ ܮN؟ X v6 jJySYCPgbQdx;3$D!5#m^j| j4mvXg(Xe[^H _2#C1yɮBع ډhvqY $ʀڶc3Bwy o0ǶoàlS_sl& g3P PeZ`MlRQA`5DwEc8-9 N?UXk'Չj^|CRi{LtGP?>.RPT 9l;]U${x<L`sR,($"U !?H$eXVqA'b3>qme–_1ԓ%e{ɚ??!ͮi"]8;is\ڙ&F 4|V omQC+ ;j H ͛t$i,i RTqk=ۗgue"_v}Nt?Cwq[6݈!j|=88I.䩧[BZrzpL#NvJKwWHDDrC4!U*2 ]P+6Ԓi^l A4firCd=1p(&KXh9tڶ Mϖߦieh<8ϼoD B(ŝEFkf*'P}^u/a7oңؑknl+ܧ8{1'6Jf{- zU"td Y^rjd6lL9~'JtS:l?3$&Ty"xʒ=Ji+S=S6oϴ'%W4<*5Le80 {9ZJ L{ bEMiH9EL\8 "ˀ9}-0m \D}g}ߵ;WFAwfEchdy2I] l T==e.$MX G3iw=LzA|>_VFD6uҔZiSx+w*.!8g]Mݯ!gF*a^ůCOfV?䩧խ+C1apQ5BF kxYcef;uY$JzC(PоPFQq"r"t A ؘ͍J!;Պ*(Y[am{PCy Lm[t|0rtvXԹh@9ʔ2-{=|qpԸ!bβSNC[:11nԬŤmv_Q\9Ғ5BqJR)9W$IiJ:9AS]BoOKO=7tn|A/9WӼ1teOqf7_@hqLU 8-霠:- 5Zo${GOЁ1a$*j$r`SIˬPyڗmt<2:iL{TeQfeҌFv_3QS; 6Wkk~Kxn hKgy3Ȳ< V8w)-/{>8#sA٪Us"&EټD߫Mw)]۴WElp[I597̲{Oo|'tw{Z8,̀pkٞ < %_ϞhCY=i˗<7)B9BU^iJ?zb. ż{I5TP\OፑE6hkpyTSUU!I_؏ HD$ Dݶa8sĝC`)$[ 'N&wJ[ `VmfH=PWO9L `|k2ݤKw!暞L06DY^$gMm/JK6Nzp|arǻE(΢"PMV {-K6c|aߤJ'faxҪdwBG֜ҵf"%M]Sj'fUK}t1/ 8_6 1pxdJyUUj+)ed嶊Wx;FQ$Sdy?C`vI)@Ē\ N·S\EJ`fm2rCYZmGm9h;ڳ%ܯ|KhX_Ѡ@P>,r}Q%Th2];1ad9yÆ3$;; j3xgx1|_=ES\U40|~$/;+`Qm_ \E_k)`/p7]^PU=Hj7 S(Y6o3K^gZI>¤ZlOB"`QU<i8=4%b߶1`Eȟ;TFY#f &V2Ŧ!JLEm!T>T$ ǿjnhWHpmF)"j>}pLY$;Th"[H,m-*PG_|JZItnZiw 6ѫTf rOLjtAhp+lBux$z7W|0R9_U6c-3\Nn " gi>Ш:&)PF48BbKtEֻ(ѻ.zDOxٯg*]QꫜU|@Nl#hDl ѵu~έt\|3֫Rs+qn2T=Lx3bI-3*E`Š%be[aXcwfP"(p;SɻlJ\4/fC 48,6{g+{o_W/pNt ͌6w>HA+VΞ,i6mЙ gKJs9]%7mNu"/w|P,^1Hd""snD3=,;xthlS|XmībsXL; ɻ@Zl)ɶlSFjV*,ŔTr#o{E zI z1#YN"kvkXؼJ+ѳȭ8.wykzONmu xxK@ >s=60oJwV+@1б3!JrP0N0$EF$]5Ssl* S)( #D%FD!JD!p}aBrᡗ[ߓW-?N] Sq]ߴPW\gCАp+l@Ò^Mi3bQY2{2R1$ѕ*TU~=Wknɹ͂ز~OxB Fs5t,Meu[wt283S&c @ 3I SA"JԢr1,V_NjNno$ R6j9Z% ƈI8q7fa1SԡoRe;`參BZ1Iw7/~}ʻY4 7v})\=u.l X9Unw:3¾ozS5F^)hHy@_]_"dTִ:3ao~{PFLvyW_rfKq eJHbҍ(Q!!4ċP5.d,WV3Z&"&+u ucuM@Q35DDĜC-(qح[:U!BdB'mqwoz{WZ|h5IgD4Hc%5%qκ%m, Dժ80gQ_ϷWXǯ5zKV9Yׁq<ސEqjw/z뽞9#OEz Z=c; Bd>q>+r !&Pqȼ=t8ԹG @7+zff& g" ƻnDPB'bR!`ĢPMl&x,ln0wk2}V#/7 ׮p綾YYQߝ {S!ɳVkPM:|5w$eۅ٘ю}X_#W_A Hٸi^ctEim|\sq 9 Ŋ =]kLFu-QBضwUFa捡Qm ʑ" q "U5[bQ70krj990o̪ltR[RYda&B0@IHX-E,q{ܗDʜhz=6wLN˴[䪞7<ʜv37Ѣ 7_D\|1PF#>@ܼwUR[_N̫3 ;"^KI/Q}󺋵n˥vj28<N"HM:1IRV[# J|;0\*H\uhADL۶EB=0k򨡬T-VQ%R2YѤV\zgJX&@6Dm)O2Ī5`-laJ?h 1v![xt($o=@Vƻ悋y:mtw'yoZURº/p9b=`j'P>Jvh'M!'|eeV8Ɠy:8^ZQO0VJsΔc35C˟$ ҁ_ԣb2\mXog+GWIS]-bVSّ QP  ~N{yvtl'@T)fgL^$wޘBrB=푴(IfLf:EV,RfZO>/~ݫB3Y=Ii+ljv?-{f2"EK,$IQ7/Y ?qu7}M_o:z}rd^?1xXgjX7&4n+G'SwÐ-?R("1[m> J7w EDì>~(1u34m[ضc #m[cwނ/LOXJHޔssVwpȮ9R^^S F&`4g J* ;կ qR YbAbUcaCǀ]󺜮Um%[|?`v]2r/hAL:WCB0 ɯ2`|3V^cKolTr,@V8$]@Cd WYrK3{ XYKBmo{?hm¶QrEunAoj-|:Vkiy}v&pvZ2)_Rªl $ Z_‚J_` =s%Iz<=!+n\֙)yukokָv%FI9wQ],)W*B, 'I"V JW7 PQڔ8pۃcߙ-c۶}3.oA&v +a~p)4{e3+ܞ wR~"#to;׿2Vlu:9)Qxr[tz|]KsR%p&O6 ^/tsO?%=H>V%"XЗ3͒?T._y U:n(Hq b `Hce7,kǚtJق$. %RED@`̲mvw__۶n!3WD7y!A[Tx qx.Qfuz/}lEmWx]t&]].fZ}Զh` eNx# N5-:5MS~YdO. %33S%=NBy*u+mm˃*F5zcwVD9<أ=:ffs؎0j5Yv͕̂БGb~6ƈ,W|o6tM3CU +y{p/޶㯏<x߶-m;n@ pg.o=YK9΄WET?PހRܠdPSO0|2#DT  L~œY1_."Y|RE`>iÒE4-g1ɑI9үuaUYӚE페jmsaPع‹F"Ev C5ȃ<EIqHEČļ$N$T2mhö>=>>>㯏ma $ ofp[>hd"|U{oɊ} VI tLDލA%V7[-*>|Zn(gw=GA g:f{0}EtxgLFicS\ǽ]՛~Z=tX;.V4@| owHQ\һ+\[EgSYk-l+&@"U%`@BE}c iSGt|B8|2FP>?cջsd8ef0g+GE_xis. 3.גw 9EnEi}ՌZ|W(B5PU*p;j~ogޮ}tiE)F"aДUIU8k;]ѳx)76n7nq}-yrvwwnoj:i?/|iF@uӸoƝ膽Po[7#@L"bD%3{gD$"a#][8OU%öTm ƈ~Axc-ZQ_?epf޶m0U3jJf0Esz|9}$nfQ׬S/RnhF8\o3STt`j;rCw%D\䇏'M)S(+ë]ifWȑ\6J:иϾ HaΠsv1m*ahEނ;qqOUz`10om¾?}vޓmcBvK[#s(|\=){xθ[5,9Gn@vwO'22Wj|tMFrLFJY̿bu ~*ӽxbb2OoW ֞;^t%54,3D}VO[f𡭮]fo{dU1lq8`т4@l _80_۶_ 5 ";gm6۶qΉƵ`cED7rጐᶻ,z/*~OZ -+;꿞ۄ\4{v9[Ț} < [3mIlԕ5w}6y!Xa-/SJQ]/gBa`Y!haFifVzq)`,]jSh OJPf$rU MD 83Ƙ(CcR!:Q1o̼׶m=rBd{)03#ّj4a4zĸaKdsW(>3m~7{EŽ|Rˉx;U:d D"R1d_$_ߓwNҔW<(U0>t,A.R& R V)pJU^tv/bׅcW##]4)N#|sd|5+vؽxL`aF/-f0!n*:CDINcTf40)!e[w=Z,g,fsaQ EjO(ٿ곰nK{߱2/="<\ 1;_a6Xz']FUd0 U $\ӧPPVʡIY(B Mgc'U Xs(s%OSpuZ뺒丁m3 6yoHZoHw%#!똘6V..68ˡHn'wO lFߝo>Y$`pqGD:7oAwf9E篤PƫOM.^ͻqOcm'Iam6{p1RF/DT.ytv;|;ܸ -1|+#es ޒ],{=}SS0xbu拪mT¿넕3 \Y6EU{u˚&߼B25\RR ilg/uz]cSU˸LĊ]M,}M7y4QInʡϟ?w:xBnC=varX[@ =+<ܡ!(5_Fk Ĭ[Ⱥ =Wߍ2ZWһі_+.BQɜ"? 8+rqL$I Às O1BՊS=NȚ~D2~F6•NK;oxf5;n, K5 68 rߩznqkSnI7WNBzo&310vMDgdN~Z)ev+>^ģ3Bc:MjIrMp󟥈!#/5`ފH8a/O)l+A` λ^ ^j^ls;}4P&>jgHSoew\[XyN7MX0+]#B<ԕמROG}_+{]u$TUU|)=9R`%4{2^ten7L vfoNӚ)`WsRZAKaɬ?ute[9`< #|x,R IĴq43\'8+{ם1G9š~KX{oth- )v=]}0rK<폋WH`0ɕLSP̪q>e{k\֑/]= e>teg6)y/~Hw#]mŋ598JQ֪l֒$* C1xKv~ vDuu -20 .6 4-vLfXíC+bTiGOtO_u? grNwIu%=eh˨&g viJsp'3} ZoU67҂,JYeߛ[7iva:8Tk o̕O*<NEQ9iTZi&߬W<S}qX#<ȯn{z O_y E/ ,J#U,CU ^+K*Pc+B5,%DZr՘K/D*JWwi=gާn?}ji#A,B6,E*+7eZ`~ȯ|0_{ϮtWRZY Jz X(~qL҉ҫ۔T[CI5dZ|q]sJ1d|Q5k@Zǝ׳>NLgFeYP2Vnn=&U2:RUV ;D#w2W$fHy߂*49TUoe>2\RsEies HˆA8e?N̐Aqm/x/?2&jWwK%V( 'U =?="RxQUɅQ"VKQUn(e ?}/_mjZu^SXE]-_7\_y_d_H^*oe;Yo ^Sg[eJU'TMn=zUvAܶ|}/CR'<'i'!]R7%w^}+mjkY' ڃ1Zj|wi\$@+uıb8L&5+̒Ay.ZTY!* f|e>k/9'g7w Nl6ULzFoU$'euU;j \рfD"z &gTw-t{~s%|E ? ~~Z6e#I\Dg<3 l+˂.3Q)fu me?$?Wrhn_U|wߕf/~漆W)R-ۣ썃C;z@3o<Ύ&_!UsZtEXticc:copyrightIXOjtEXticc:descriptionc2IENDB`pkgdown/tests/testthat/assets/articles-images/docs/articles/kitten_files/figure-html/plot-1.jpg0000644000176200001440000005303414614000564032564 0ustar liggesusersJFIFHH@ExifMM*i@@ICC_PROFILEappl mntrRGB XYZ   acspAPPLappl-appl descodscmxcprt8wtpt<rXYZPgXYZdbXYZxrTRCchad,bTRCgTRCdescGeneric RGB ProfileGeneric RGB Profilemluc skSK(daDK$caES$viVN$ptBR&ukUA*>frFU(hhuHU(zhTWkoKRnbNO&csCZ"heIL(roRO$FdeDE,jitIT(svSE&zhCNjaJPelGR"ptPO& nlNL(2esES& thTH$ZtrTR"~fiFI(hrHR(plPL,ruRU"enUS&>arEG&dVaeobecn RGB profilGenerel RGB-profilPerfil RGB genricCu hnh RGB ChungPerfil RGB Genrico030;L=89 ?@>D09; RGBProfil gnrique RVBltalnos RGB profilu(RGBr_icϏ| RGB \ |Generisk RGB-profilObecn RGB profil RGB Profil RGB genericAllgemeines RGB-ProfilProfilo RGB genericofnRGBcϏeNN, RGB 000000  RGBPerfil RGB genricoAlgemeen RGB-profielB#D%L RGB 1H'DGenel RGB ProfiliYleinen RGB-profiiliGeneri ki RGB profilUniwersalny profil RGB1I89 ?@>D8;L RGBGeneric RGB ProfileEDA *91JA RGB 'D9'EtextCopyright 2007 Apple Inc., all rights reserved.XYZ RXYZ tM=XYZ Zus4XYZ (6curvsf32 B&l@@" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzC  C $ ?(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((kj?x¿moxRˏ\^q*c ߸ї _5a|uMvo,xeH)+ d_f]|Ӣ1gӝ8? /T|??:_CmXMg8u So+/RpFόCIɌ/=^|`x[5=?gxY]mwڦAfaoQ{ / ,$=YA0[i-m-Ω=bOJǾ2OwNg{&8' ǭ~Y>X6 \"CpH<֕QEQEQEQE(((((.mo䴽. xPz O_ॿ? 85V?D 8M$ELꁶC|GȽOkpDLח?ߵ7?>#\NM3L{65ϾXP5Ÿ\3~u'Ve7t?xVn Fr)YբٕFڿϊ;|7~|Aͦ[j{ E,L+Pmem- QEj/Zt߀;%9=KO{K-dP@B'o3^K~|W1Mr(̊觌+~0n9g@QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQE_࡚߈.Ꮖ &t{{ZH 0H?!>)/z巆**9mdFN4tO-GPJ1$]>|'m[:CsirtazXaT5h'ku]?w W6Mӯmܗ R*+=SQZsO{ំ7J`<nk;8Ĺv:=J| K-:v${ȤHd\($@ClJW]\7`?PEPEPEPEP(((((&_>59M/>(?m/Y"57Tӹo -gr+]Ѿ<_Z wH+*LB9 +2m#<a>:gemšx]+=KwnHFҺXݔPB񯀼}zWYxN1dq6[kϴ1R9Vb0~? dp777zďq87rG2Fr [>((/۟NsD~a~s'΀?Oh(((((((((((((((((((+(g_05wGLcҘh?!o%+G~mJ(((((((((((((/۟NsD~a~s'΀?Oh(((((((((((((((((((+(g_05wGLcҘh?!o%+G~mJ((((((((((((߰+Z*6?)ѯ?e@Q? )]ur?ClJW]@Q@Q@Q@Q@(((((((((/۟NsD~a~s'΀?Oh(((((((((((((((((((+(g_05wGLcҘh?!o%+G~mJ(((([>(x SG ϊ&N mtK5\ʬ1T$*v*B04WߎPG]CHbK/ksNgYTd!c Kijrm:I.I|d,3xU~_+~u?;>Y.K94fQu & +"W_i󌟪h((yuS|)~ |59 [UIđ2"n Y5"?bI|sz_A,xjB"Э5-7Q8ԆQ\RpZ( ( ?dOo?~'9"y((((((((((((((((((((.ɖ|UlS }_D>*6?)>"gR~ȇ蔮 ( ( ( (?_8I{ֈ隄~\s".e} V>h4 ~|!>Хk[ u )$goQ 6khtWÝG'X6Y[K %>gh![.ǏZC⿁-CL𦁧寋d3VKV0Gb >Ye_xk爴:M^J-e԰D$)]H(±';'?>k$/ok*ȗ F>V(̿)`v?f3w5in m"3B@YcК((+š--CƚOu{O?!k!3[̛BJ|gd袊(/şGE񖭥x ./Ze[Gc4=OZB0n9g].K?m?t`={o3A,aRˆR@uBTo77O|T^]l|T: NF؉f Iܧy?l+^cJ.h(+ ?mvu{__?cm( ( ( ( ( ( ( ( ( ִm+Z=XN mn]RHH#֝Š? st+OD[ȷ;s 0qٗŞuzeţXZ<}Klః_l;F2\TPEPEPEPEPEPEPEPEPEP_D>*6?)ѯ?e@Q? )]ur?ClJW]@Q@Q@Q@Q@(#N4Hm5n$'-z((((vǟ?!6vڝ[ڰh,sȬb +?K_ſ s4i4xkTՖLm$-e%m!^<ִPEPEP__?cm?dOo?~EQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEWQ2ϊ Jak(g_0ClJW]\7`?PEPEPEPEP((((((((WQH6 n1*sԠ((0n9g_s~ȟ6;:=((((((((((((((((((((?e_hQ2ϊ Jaȇ蔮!o%+(((((((((?*o|W WTծtZɶWFf=7bhoa*i:_υ#&/;HrpJ v"$G<Ѩſ>ەk ? KׄϏu_ _hy3ۺAbGY[rćQ׫vxO''L!qkGkw>*זzo5m#din5(X4:2Lj\((/۟NsD~a~s'΀?Oh?~:7kDy_@titiEVg ss3-y WuQi߁^L"\k6o&0Pז,`E@ TV~gQi1[\BT ?0 tuO6{_?g(7ƿ{S[|?<,Yt@Եk]B8%ݤX偉$p+^ז^! k$>-)m dj[9U[(зGs?V 7૟-)$Q\oOտ"?H(*  oW?[SuoH +{ BŸEU[(.ɖ|UlS |{ |1(3i&WբuR`%6K$ o $g0Q6@#$.<Qx$~ѻʞm^qpMQ@Q@ُfL>=Mҭ+`TtcGEf~_!x__'BVĞ[.%s< YHPYCmQ_=ӿ_?e߄Y%a `LP#B+3V 1HДWW 'Ətuz]y!4' ]3+e~~٢IH)0 Uף)XyQEQEQ_6__-Bv_wWw_xXonc"(^'Ryc8MO~οcTh~'-Fڏ`7!_ed~QE|Ek>24寊]v="Fd޸Jgf 7۴WG4#Eկ'W&>u\6P`̀ȀA iEQEr:>7[Inb 9f aTrNWE~OS>7q.| 9|3Hu}"ڕ$xvMH\۽v)Ӿ~K"} Y.[NִѨ/HRs}A >^]վ8?p$i:iѳ̹ĀbP^OsS'Ox&C7L3VY0;3eW (((((((((((((mONzmޛ%գ/!hZHXrWg4|<% 4Ƕ wy)@O;|͎v.N5_?U/_}B?YxgNJIb.t&&8x yW6_^)ρQ}/Q:}\g)&v3 ZiMjwyVoOsq_]-coxjOTMqߕߎb/O֛῅~#|au㿇: Λ3Mhհ]bۅ'9kWUеܦςF݄"/)e+07J0ފO|((h߄|Gt-;UTѬ8eBmʤ0k*|?-cƃ''yf$KI5#_/)/h+~u_ Y_jCk3\E׫>N{v6syw")7;FH5:?\N5emo-,GxN~ux;XtgP ;.'K;uD??f_ ~ǟρ\jd5kZ7V~TROPՋ3}8/( d׿ҵIyu fS_ ~.|Oxuudoc3qEz_]mҾ5O)K2YMm!vku4k5juݤ܆xZ6؂k _k?ͅ$z.&d3|k?κ8Kcu]S,3?g ;2[%^TnĤ|̱oA r_ǚλxO5O M}R9{ΈIF*Gj5o^zNu7(G;K`3| $ljF]7@~=OZxLIoqqe2G%J\z95#gV}_ #Ky9]rېTXV@Q@Q@Q@Q@(((((((((&3g/dx^5=;&ȼ,{ܾf+~ϟ~|(?'Uϟp7aeg<&Jj(C⯉]6iq=ĈeAY|&.|Öd6ay&\c|J,tPEPEP^L~|,?GӢx,??~s|޽f>!|>_|{ar/"͖6=B"Xo~ Y/ρ4wEijeqE;<kE|!&[GvgF?c"=^~Z>- LO.F>yfbY%$h((|s|SxVzh]շ>nF-tp+Ե~+o|7m> WJԢh.mncYa'dt`U"&Y=Xo.AM:8e/ F Z((OxsGoukv$x1A$l܌uۢ>\Lmw `o/t? =֗_zǖfu$m̧݇_a@3Ͽ|ED5>婲ԾtMYv^^6?7^/O#?<5m=1̉fܒ!3,LG#z/Q#xz^_]\== Kq#ƌwWQ@Q@#*ax ";ſLػ^'z<vV%D{Dg_|~ yZC\Cki0OV=۫;ybO5@3}C^0í'Zu]O2YY?y"T61:i%!thc[KvY$M}Exwgcyg;EI%yUyg}5Q@Q@Q@Q@Q@(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((( 3c~9]kB'h>Fۥ~ߴO k'lj|ez-a";{皁BI`{EOfF/ƶ7J#引?7^7>xbO薘]^J"s}\QAf vWY_c_GY뚥jkk-uUgX)#,G7(OK-W’:Vmey6{#vt4QEQEQEQEQEQEQEQEQEQEQEQEQE((((((((((((((((((K#B  |@to~ $NωY>7'y; 6Nzm5lM:uE(N *NQN5Z;+jV#emiKg2iiAD oV$mn>S0S?: |Qc+ ?iaD 4#i`HBEmZ- &[ǑЦקd?a;~z:.*s৾׏ԼG>[ 9 t`Jf__W..|lfBqs}?@1w [*V8~j߲yxgO|Cxj1!N@eR;ÿl?~"/৆3q-:+4*Lbt<ѡ9D#?23/Bja@u?2Ѭ+r[^Ghz|1ys4ݷ ,@|XW@<|-M><7X+ZzIm8p&+$)&@ '>A6x@KQm0ܝZiGfc#ռI'%|)^ZOůYejfb!epQT #rA@>2oWO㻟Il3%NqW8V`d ڃ⯋?j.uܳj:$4F4$XPs7◍ ֬<%+..O᫛ŴO tI[`?g ~4>+yzZ=<ɏ}c_@?| 7_>4~zt?Y[\Bxr&hWFDs$ ⟎5έo|9vC55}2&^2xп6戯C@4QEQEQEQEQEQEQEQEQEQEQEQEQE((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((pkgdown/tests/testthat/assets/articles-images/docs/articles/another-kitten.jpg0000644000176200001440000011760614614000565027510 0ustar liggesusersJFIFHHICC_PROFILE lcmsmntrRGB XYZ )9acspAPPL-lcms desc^cprt\ wtpthbkpt|rXYZgXYZbXYZrTRC@gTRC@bTRC@descc2textIXXYZ -XYZ 3XYZ o8XYZ bXYZ $curvck ?Q4!)2;FQw]kpz|i}0    ##*%%*525EE\    ##*%%*525EE\" {{,hGIve#Grw*Wr1Hw"1.hc&"]R:4tR{Rܪ!R=w4bSʮF.T`&NtN,=+ܽȎsB#h \DknTh Z19d̔wƎI{W{!G91Ɗr#n^ww1_QU_Mk'̖wǎys\+Gq5ʮT%0ĮFSM.A#o>AH␎^甅!z )ܮ^F^hbWUA #Bΰ.A!H^kb)B+0ƍ-EU^j2_ůkB˰.AE|!Hr1gsA(X^j2^ܪtkFơ%Ms20ƐR8{9s{xbj+y⿻U=UxְmG˟>\0{9s{"ċr5*^Tht5،k.|EWAHꪎ1 )(!ĎzQ U^hTkՕaa2I8W#Qő$RrcÉ3Q/*/4ZjFjʟc2TŐR#׹œ"IwW41CKWs-ji5kZŕ>lRH1R<ɕ"IWs(qYʮUNe ]5%d&#YoIe:TG )$!TqJ"Ah#B #9UF׻k֤ d8Q_ ) G09G9ZA>W9~zw**)*!k8s yB^^Sʓ&Tz (cW{מUQǁYKEQ|o >|v )yɒr=zaB |;9^dx5TU5jr iM(T B]LR#X0aCb+ȶw;]-D6d $q,=j .\#A 1zuܬ ֺuR# !|.\'#sA 0؜{ǃUMEI ԭQie2\$ys8.xҿA'>Tr{ܭXP C/=Tv+g%ZYΕ-% fL&A@>q'/4+))%n/GΙ(|V3s4x.\'+=BDWp?UOCG>(tOMU]ek>\1I6|åDRJ6\{E z._ʋA2W"|L| i|q7eL({ bLse5%{枾/GdD l)dAfJgT hp BGyt=Z`!VSR՟Ϳ"}&ѴGk=F ,Jc:h(MUΙ*A9(Р=v?0Lzj1}沱{믞PzɖՒlAɑ0pUY.T# c[;گA~HD_~nՊk@lҦ%I$ϛ*IB=Р+UdJښ^ .7]miVGi5ôUGigEG6\#a@;:qFb!0tj/=&f/V+O|rG@C_],jw=qd24H­a/9=w=$H[};7K7[m̗6\<{}uu|dg/=ysE(YSIY⟛r>G`3WysWn8ߴ{hO"l*W=$&'5Tʊh w= o\}^)vwTLϟreSտf>.A3Q^}95}eE< >w{^]̦i>98/Z;OgGPiE{,ښjp1Ryϱ:1y%*jm?~k|SzuiI|m} ?ʟJ}c1,*{j1Bty_SUgEd|=|VNО<[~ko {ɃaraoqG88A4XqG!{sz:e}Hq ::Ϲcxd(5S\C{L^Xcyߝ 1igW"Qic}yŐc X5a`;9͖Lj)Y-.^WÝPJas;k/ٞ!$t@9;yȓXD΁khj,Fz&;KҚuA`}q̐5!…81!4Σs 0%dqQLӪO= Uf>Fg7Ky_:>,:Hǎ0HI2!T@Yq(4B玗/v*\~/>{ٗVfElL GAm#8Q;kKCfk8ޜ#cDR45I?Mgw- }Ag&\D`@a0Yg}w:fDGj5TVWVAesgѤUH.tFRà + fKA!Zʤ3#USg ێ_c;l9˜SSD&Xol=75vonj1W#@H51,e^h?G %L\6Hjv{SU龧0&"r5sA ,JK73 TOB=vIH|gH}^/|v6ǯyN׾c 1NG=#meFs]Ĺ% ze*O|Wӵ5N;cͥ~4l8B6"7y#@POGvst2 7J04+ko6KO1fl!86"5;]l0E(U}'V˿4YLR8jGyW:mkrcBx;#VVÅM JNzGy՝,n5lnJxJq/^F#0CB81j`>JKI=3-6W>\)v35ySeE|?7֟\֣0bD&0pbUƉOB_WMSGu!m%JAOAC $ƥ|[Q1` 15d(ubŋ-GUA~bހזR4<us;]s*LmZ"50l +jjcmZ{rcL<ۋ":AΔ4iya֞F5c1 $8HH@+)t6p͸79[g ly6rkFmmNkyh0lj *xlt'ѭ,UmiG`Gd)г82/#$Hc(*s:8vVjlVʼn|˫qhkYG]g6:լS4R1J ""r3Gΰ{B{[)g~sy&1j4tUU\C*Do#FƣXֵQyWjGY-LTt}&I힅6 Zgkia6YOȈkc@ךakp2-ytS{l}C .?AYAYVsIHo59kֵ`V7-E;PnZϻz~Cu/"D]EVvSLPDF"w#ZֵkG >lBJvuw=h weVQ܈kX0B#B1ap쿒Dbkuv7 O{?~~m].|@ϟƈF5c1G,8UTՙ 6tO/> « i6݅֟=;}f~vmpVCt )7FX h!G8q RFP-E͡eop u3s`sNDF5cZ1(q"Įng$K<{u}%SeSu]|医^o0qF:tהj#Q`ш1bć$Xbg98DLƵ(.~Gzn~Smj ;9ֵ`E0#4z }&CҲuWnBVF齰6H95a8uNDcFǏ]K1U3={W]f2[ kai/DM* ͤҹ0QW~rQ0xB#c;>C1JxFNj͵z?y6|0lb1 ?NFbDGB64Zh~asÃ_Z*ovz4[+ R\5N9`B " т4 *]֛IYMOQQNv5zݷ>m 6Q?IڈBB0@ -<83=>&\%꺊L#+uoW>ly?і`#b>h <`l!j՞1K[_YOUmUaڻP\Or*1" `1! L cXof9uUuTy<[ n?DLR9`C1 k0cC11x%zO+v:J:R2=>5y;Ix}ƴhF 6a&1򿝼I$]$HwQ4F2J#ǎX>FbB,#W^vO,QVRex}>=fŃ] hpFW1`b`Ǎ>Ee"n(Wy{[K) 8pkpF0"ȜNNFXb pE4z3.cL,~=uv绝ʤ{׃,85ՐOg_{GF2|:1j+&@>na)p$euIlaZ67w{ZS9F7NI@ `ԑU|U]vD})i$[5(PzɌQ6=z:Mw3̄! ͔eFӲXg0I \)7ߤ$;Idžj7 + %͊/I$J"S݀A͜ jRH`08uTLEQ%0`ˋ5i:wR*3e sroM]&zpX6eߢoGя?"2t sa\iӼDgq95g] #~&2e9\^]=ΏPT Mn,8 6S(/>eWz߼&xqf4Uw/'=j-:>r݁=]}We',|F1٧U 4ʾ~IקN9̷ֽLGLe#N˃yy)Uw?^:Vm3ژVלoՙWvytB Лߙ\(1:G-6>,=l aeS/QCwծS@Yeq>ݍt g'):eSmu@H)ګm1E0! ]6X@u7)ݰ',$)DH1=YMꀜ l*9a t;e] d 4mkCt;(d焍<3C˱猀n/@Ҥ x'LSw]*nrA[<9W7t,l$t3{sZ_W^3[k;zލevR|U]+{ɼڠg 36_O|gE:bL>~5O|ᶒt=1捶1ne͎Dcy{@]O֮1ʽSǞ6~<<K9nٓ!(OWsOuGF&]JG}'KUmɖ-MtoB"%Vպ\Fpr[4_W~Ky&]2m'z19Mol=m2-V ӽyMPJuNcIm+w5X˦G$tѦ6^96Sb@ yR {VJRۦecJLEyLSÖ)BtgDZP5^4E$mYܧL2ޢ0IV]hcc#p;;"*/|7L\^V۠uBg ˇۯNl*:phtȌ8Հ7Ml&Uλl$H\;R˗PUpP鎥:8hLMɣp mٚSd*C#<ǣ+}puJ 6R9@e#׳]scꠔuך$O5i,Q{9)T(wDD[mӠJTULӌ`!n 5/4qe 0(tߥeUVM>L#<]ʌǷRmAVOGL[qx'^z􁩇vQKmE'EyĒI>mW_O6yisRH4D[Ξz昤I !ZMջßMPL@ M*<8Ѿ4AUNz:eKB$ dٰ)u[m$20c֚D& 0@66>Igu#1B(gg`008#~Cpc(q aG/A08A8A z=6cCq0!P8pb`880`Apd\|o=6c0``p0!a8L?111qpzl>.  >.qcapc.>?bbb`= qllll?~'$qGW67`38cal|$1>b+c 0`08Ä6666Ȍr\ ?Abc 0`>... 0}Ol|%rL>>6qL$'}&&.)C. 0`> 38Q>qL%'> LLL\\ 0}F  =\lll|lo8&M~bbbb}\ b}Nl||l?6>I>q111q}6cCE \0zS0~8&K 1x 8. 0`̌T..... _CGqL&gf2c 1s$qqqqp`}l|||o8qL%1'1q}6c 0bfAS)c6>KL% @8} C&.)Rq F>1OH]...... dz0~$rl|a! MbI+N7axL5\\\\`{8Q8&McJso6Լ旖XaMph *Il>&"#Jhuzڹ+`pc}G2\$WvH Ws!>A[B$)L\\\0zl|||`~}c.L% -?y]v]㈰LRp1qVdҪV0`z8qÆ`,\ɒHkss45 ~(mk\!h_8T׍=9jk  =G6>>>6$̆S)|?^seo_gKw4%uZ8D?j2$Wz \Rp`A7z$X2LLm!洚%(n؅]RBI;Yp0I 8LR0`=ll|loK,X#J]fs5-A_e%%3چSjG^Uyiɉz8qI$݋;H IW + ; M񍷌EV,ɯ{sXM]SQ_mZs,!pWbXnݻr80ab\`a׸]i]-t-o5{Wȼsͼo5NZ}y=S!R7!sس3r8~ܳ D f`e&Lն7Uy!zYVYhnmOȬzĂP*'+ҹZy+Sh5zó^@ORO%Kn7:{ں; 6GK=nUÇ~I_O >D%W䓜`:d|ד5|_`O0Z _૊cqs7Mmso<{CO.D4hn귓D]\8p!I$Yd2Q(J%'' YTu*W FuC#HH3Ç9=נUa%2f^a.*tlݞզi 7/ot-bwŊ&]c2֫SeJ&Dĝ˳3;H\$Cg8+"JY*yF(ER^[7-ITԃoӥt1R -gz+,j>$>:=pT+VB0]\cḚeV۳:U{956fHj MU -]ۯ~n~Q%Ge`I%z>yԡB , b p2LتU45r$6$e&5lbiO)yʺ[PItr"ʲ%7$660`Ap`:*S u *n !Cl=tZ.MB]el֚0KtjּKaZݻOxNk *,[YY +נP tlPB3@u!6*>/Xca͖A&mV~jPCQMfoqf̀,c 0f (S@= +9WW^j+MiY: ѯZͅ[EWOj.%Ib)': AQsqʸi4r|R,vRD16(cZX wDbZu%:f 5#A=q^B zxd1)24Ζ^w04d5zZ7G|m|_Ox}uihl&CEfN=qUT(U0n6B} l#$2ZGゕ櫬|gvZ㥋OC)mF 2lYRdv$deǮ `>7 #G DYd%NIZYdT^GWNޞMfƪi}N2FIs^$^XcЯyz!aF1YQ&FʳxbjREMZ~x+TUO[S_JDruZ#IO|*P  0l(ѴF>$ ]MvT%m hR]^ LX(VJV2fK!Ϯ8q7!` 22eɄ*[+FiJZ4Q@uC0"""lF~\HV*T8bn{ JҴ+M#_+ѭIW۷`#Asd.J3íʹk׆ydjԾ Ԍ&+xUT.Gr n+m"pRz 7pasC8&IHy*d$*Q ։k[G*8*BݝmEnvK77Iqᖜj8p*AS DBdh%YdyXLH>Qp0` kn --`^MM`*AAd!u(=()2&Mu0('';UTTjնQMJζZ%H*C+)q` 2c3I,5`V!`Zxk#|Prp)Fr%g]oSoU5hQ C[kkH pQ&Lf?3*Q\՟qE}SE$:e)N%g]wOsQ5XQJ, *?bXɒE341؂ػ;y/ګNYv9ʙFƶk!-[:ۺky-^C[ *UR8FG$2L8EdXNAIKsOZH|nҎCsݗHJ'bgKvml]Ku ĘZ_Z64SA2A~g$2䤇3G"SQz[_Z-5UY'WF8s3rXnio8ND.jz*v  YYH gq L(j9jEv)Ak)\Ȗ93c̜V@Y#MS/:b%㾈  1&PєᑤY )Z ]m\2@Ն# ~eeGH]⵮x8ޛh 7slFAAR61|>38:LJ+$#ڳPl*4sI*nܮF͒;oY'mi44?5E^V:## VR#}669,pDoivf2KT=-|Dbb92Sars!U<]-RxOJ8AA*T69p;3V4XU-Yюxڰh]9uu+ L&YTeue -}˿/xo 8  AFH:ʍ (4z)g)vxV͈' ~`Ѭql&IU$C)k56>7<-AA2*A}|&Fvwpq/(e +yNmxR5UVDN&Yă9#̤`@&3/pA!ÄK㙙Y0E^c\eRMsne8C(F*!)'Y?~I8pÇlbĽ.0 j'bK(d ª ZCn) bX]pAKɖX/'?rc}gfig콹o˰[ڎVɌV -Ï$a۴&F%ĞLlG*L2EJfD86S DX+Ì^I,Mrmo׭z uVX.ÏF3nj@&Iݍgl6)ڭb9dU@b=6 e|.d1ٹw<הXyMQ U8\YRGbfk,bڵ`Ǖ,YF,d!גG=f$LrA=Ln2X( f-?Cߐ<}׫]؆Y2vE S$# K!Fy$Mjmf=/]ʲx7h10Z{N2%>N˳yy%fK>ݛO%!jԧce֨$^a Tbgkvdn;pZ&Eŧ{vͫO`N(2|Bޏ% ml5:cM-^[Rgx YZJR'kO5$f:5YjWdX=&Itf~oÇ6>J!v<1 AO4~KƩP>,<=RIb3ʓ켰O<ɱgW{PI,%fa( ݤ[g< d&Ia!bYGYY'%GuY3o q!eN%(׮ZixΗuV<3\;$9Ԭ@^T) %˷[݋ZYfirdIY^7y<<РNJx<,Xfvbŋ,Y'9lb(DD^5Ku%yH&aקku=y<9xk*  yGF8}A`)qio`֡jW]B|vov|+—W=gA5 +%:JCV  ½:tS>b1Fc(P I%;R-#ÉUY\UPN:bםi՝GoD|y|v= z|M:tקVR&x¤!qqqqz(Ta05WԞђMmw=o]:/+>:tө^zסRJh6Hep0`qqq^zt1|&X4:ZBN:uׯxԎzשRJ*JCX088^8g^8ԩuuuR R]]$XdӆÍ0#8Fx^8838AVWFGGI")ÍF!1A"Qa 2q#0@BPRb3CSr$`4p? %ș?`c^>KEe~iIua7M`}^e=6F`ҩPT/`ZQ:LveĦUj'_ya62ďs>c=")V6\+4qY|LBZ[=;89yN.9tU= ʊ-2bRi*vE&k޻)!K %@%lhx3G )_mDg_P'g 8 Cd* nzۭ1UldyψB|*Ji&h>#eubPL ˮNe{# l\u ovEM`TZjpKdS9 ʺZZ󛂤[j·Nܤ_.&]@-k+Uыx{O u}ԏ{-KHwv.ŌZ}L6 ,Pk5RPQ?Ke"8`D)]wXn#)݉h/_$B!Uc5],*KbNLn* ۘFuN?ؙDFu~ҠhĊ5QB9uWnU*QaUd'=HwU}%I<Q)OoSif+7hYWu*ᨾG}9zh6ޟi*S=zf6}zVDG"X^7^!$1!cc1BLW̠P\.GIxlA-[b\FGb ۘ( <hgC6N*~֙ *;R^!oȹ4B@!FFPAi%} vJH|+T GSePW'֖j8_CzJմ=>=*b>r37+UUzyE;Ys򴨌n #f^[^&"-MX7 `h=ø!Cc*Ppso8) [,5 p\A|ӨNb}WC1 Gbu7[MWevT]o%)󷨚NUf# ݥS{Aj3)vn }WHMZhf-J(*'Oij FŶe, L m M&G@D Ŗ8׆[OscBT\ F?l*u {d,jfWSTr `Kq5mBU^HDMQJ}y_1(j;8VFNi?ߕv{;2JPdyR]WeV[{6Su:"jEڌa A ̀z@jILN P BEzAm>dC,y:e 0 ZDÄd1X~[MAq|>vosu R=3,Ӥ{m,J7K=FJ p]]rjjoLTt ځ* *i0*۪q+vf=iM:tW#4FnZHoS2XK2:^oT5N#+oD6c~ZTCNr C(uFJy Ii,/J)1VV;~1E} JB>PbWb $߬eh.9h R b0%JZVɼ6JN VO3X^ԚoiHSѽa֙}9ڶ ۃ{4L*.A`h)jPB.u_5ݛhթA*x>bi[[IZ=@]wR P.,=|J(ƣ5fi 01PPlhvXӪWG(M&|;Ŏ>th\Qy1iHFaoѿSw,*/\1c Vo$[pDyߥMFn13]/djay>F{m2&zEesP8&# ĸ62ܟÌpqҨJgR'#fOBco>fi补uj |=@> zhQ:d*_Y+K5:o˷tԩOf=D`^[X3#=#l܎~PkP.Fl" 3k+sɰPR98à2V8bNQA: StaڇȲta+ҪթUOHyE{PЕHJFW}zGIs}vIYlkQzF ?)xŎ261JiB /Ci^fޱj5JYjR}OUxjjd 'XVXfPg*|`e:EjS-+-J}Ʋjh5HDDWڍ>KI ::R TSE\ޡEfp!Xm~>N;|ds`t3cBU!OرSbpD؄ ^^_XiuKJoC?-bGzMOg:}m2>R7=uT.VVCS㶡[K4U7Xqc4ڝ= &f<#^Щk` pV?6t;AGC~֔_PaͦZ1OAG Rz b2/5jiA^B6u#zn7@`L1aLWaz2ѿ.5|M%`RPڤ65-EeF' X\ΪE|;/lme gKkP,r>bRX8X_} za{Rm)x+'yF™_> }YfT{s \e "MLZj@\5`l0? *`7VhW5]Y<@|P9zoP;&D\o+#t7Mm٬ i~DfVZu69Ρu,ŴՏI9 iJ&%jT u)+Te[4EZ'̓ɟßV1N"۲8žbͦz=@Wrf~=ZLƦH'ei/vVaQQduS `Y6 CC E @mZvtV5]V+ije52/-y+S-2K;zJkS`^MR5pT֙W\$Oen[ZGxYM’Te`mlBQN!(QJVwWX6EI]\k{!‚K5]5 WiG܅="1M-ź^h|BX/ Rܣ2WAPǙ]\R+ MQ EQu13n Omٔ ڮ' J|'L~SI7넭K2RCҪajuN$ ?R;j1u:馦hVS?{+4Աt3=fj)ޞ2G4ۣQ+v_j>V@TS)bř.Lн4qj[BԨF}QVTB mۍ JzѥV\ogJ +[|SZS닋_ٹfY 56NRpllZU=g`}oHl@bmo=axGp?R;uȔ*R;V, yhY/J6ܤ3Wٴ)] Z7 紎-Dg&ITb"_9ooI3aqP%|ʕ.L^)$x6 [D 2-Ѓ*|#iUmR TMU#P⦐딲]ZT\yMIi)5Z&h?ٖ\!^-^Qh%H7ǩB$ԳRGK5 UHaɽ/4}vU=Gh1pͱ0+ɶfzܟmaiWR*3ޢioѩ_!YOH.iBW q6 pq O؏D#A7ذ>RJpEMϬ>-o"rώ2uP׊ JEGE 2i_Ċm*#.#[%>&vs. ¬ 9)>:cA[ )CYW8jU5J+f ZN*x߁yzBi .f_U_PnB!0^R F`majh˼YOT‘Q.Np`cUPǨmܘi}ġԠV𷩵Ri D,E tծ:ZT5!VBset$X"wb}Hwr2hLiӐյfAOPBp~Tݠcp,~cST l*ԹPּ A_^+  ۈQx]BE4.>`M54ڕj)l73PR^iT=D@o hJPjj͖=  NO.f&RCbL joJ+smnb5*Sjm_a5U<ލG͔ѽ)lLӷN֨ܖ}B+QuFߵnHP"jc4ui (p.p,䶥C1n7ӹ`f= JB"Uk >aOHyu3Lo`zZi7l[?*15X|h|S lz͋Gwq&ǥJ`6*g5ŘSmAJnZvUU){N}ԒO%o:bj{^GLzM} J*4֒PǙqs(WUB{)jjIU ABJͱ55+iҗ-LCU.pn7\ XMh\f/n4ڟieՂzCj@%mItWO8yZBEڢ6:z4odE<oUyi_? [#ҭ17yw=hfͺDe @E}քaA=S*=n`qkʋETBmX\;Ś J./c{+ԦnPg3ڐ`1+ϣkYyzE.Xt|l(7c?2 .'p Ԛm-`ZuB1jQҕV$x3V7[En{i5QZNj(5Qzbki5lU% >S5kl5&jvJEwzAPu!Xl%=#&QY";Um-J fwR_*R*eYG{cnUV}m7IIk_S{dQM(7O|YQ He8$@`Eѯ~Q,!3`6pL6b{Z ߬˛K%C{TTLξK  ؠ NzPP.iRCNS ]{ER\`) ` dmpqjiֲz,e%jGk(>rrMAh4s'jj}* pcw;M 颽fZ@= 2p 2fTTcn\}XJ\]ԝ jj(# JM73g$_R6S DS[ GW?SNekA06C!?j11 "nb'&.DlÑiv qܻr[x\:Y[E6iMS}VtWGDj?Puϲoog!JT96Zk'(*tӮ) S[T;_X.fqd|Li 8zzHNAfXo!)!UgU=1(v_e=Kn2|a̻6'0d`< tb(?]ߨm*jm_ W下JT@BS YiJyQEeb=3ʞPSRJ_>o%WaMҽc&tgoAhQmFVkߐۙp3hXna+8fKqcc2 SD y17Ȋn&ǸmIXa!Ǩ6B(a`U5wK%ɴQ O(a0d?93~+w'#2H{pV?Aǫ^g*nEI̙jAF()KuTolB^Ш͉lPL,ynmqcJE .A"@#Ӹ0g| flG7XI0nn!(ۭф-V|*n^kmiɵ@@&4SH筥 f'13mH4 d!bK,m/Pp;a%KRiP5`{'*/ /(!U7wBC2Xr|k Q+9L.X0l`g,E>XMɅHoRP%)i^LZ=s*1h:f/*(2-{GP`pi,e/yp faMs :Z2Lm~TfN}Lv| )REl%=gȟХ:I-s(<@E@# =ḨmvGA/a爃m`O[CPTJKN`;VE[ڒ0kz3R-ko(@/bZAdw (Yr nטI%^=s { 28.JX{@%ŁeQF6 ݋R_,5csqct0*?p>$"Ap/K XK/xn/݉`a&[tSӻ?v( AῩLƲjB&j)BU997Rl vig1TffI A!# 1V4ɻ8thiĆ[=&; -;!{TS@o(9.T[ȊIX˘LLAyR mЎ?;{69 j&{hYzGKb,OA}xwD)iS*SchFQ,2LW,oJGa=o_чH 0 >/UҒqe.5*gkcדY!]$# k/y8il:E2p0!T߈k0OY}`0h0w!2G<*"+[)񞧁5U}K'JjNI3GzCuVA5: 76P-k锓"_xA6/Y=atZ2=X0%JULpJZZKtS)iTXsʵ{Zr׉N;. ՗u=Pz•=aRN'֖ކ:Da ̴ q u~ }z0"@&Qq5l~LAnSeBy`CSSۈN>nOn}&nokHcy3pA߶\`=!LrM^%*Lgm%CǓ)ӧw#E}Mv&ȣ(%:"?80GCyu#KK:rbxX 0IoG@/ܓ5V2Ó*ۓMUQ]WOVgNzzRALu*FժIjPtQ`XJj8Q*JN?GbQ;#rn%EkyzC= {2Jr`&#u`0 􌧈Ay&bA'X,<ɔ(^ $h D-QPNZkEv 3ドUShoň nhuw^b^^TBejM̱oF`1OIcap!3m939 Ff79Jj9Y #EcUɛnq[pw($ #*6I67&D @y܉j/8{|CE'FS`0AOL@`7Z6s  =bHHe}E(0~U1#= h6=& R2Qy x^Tb%M8=l%B̄$EĸxqCzb1H8!i^Vc-)MbVOO*9cbbX^k(#s Yl:F&a(zGEf#(B~!+|^rfP^3bor?hPJ xhyKE>eǹ61XX@o݌/V6J􌨖E6Jn#pLVhT\Ɍp O 壓vS~ yd2vPa;v͵w9TTO1R5l}LΓqnEFfJL$ ve廈x/q.J㸊G1Xs#"H oei^VeD#8 ҍKxGۏp%lEdۙ=Ihdŧ{-W2FC~0*": lLE B5U==؉au?0e2Xa.C{v `p .@oA(/)T+8|JɴHu}0 ,P9mʵlɷ 8m䓑)v~+;K_X!G$E´Cէr Lʛ* ߨ;XGkFq2޼#TF^zehqiB@jJ5@n"H|@wxcWW'헊; D [Ģ0.V ^i4T` SY\*?*ZYǡ5qyJFAYZTJN.1Tdu0E(|㜱%YkIojf!-u~b%KDakM8~=GC*zʄc h 'KvZ#]J$nʬJn<ӰZB[Ԕ+(.+DaD`|?j=fW Pd^ZX\c2XxY!A<6i[@|Nn/q T5aYQBP.zN:۬S%0bSۙ͢-/G}`# N7Yգ}QԒveU7 `fw8+\AØ>ՙec)&/KzFlJhI79dľG4Q-5]H,l)ȞƱۋtYM֖m=X Xaa,pwϸ;x1RhN])5Q\X+9zʿH fnwnn6NZ,]kkZ6brm`!UR0&52J)ȰhdH \^8L iʔ=|GFbTe@a"9$!w wa#%4:5.}'h}WzhmPUSDj`}c"g6CRjPQo M:Z: x&9!g`- (:'1xbIFW ꒣Ҥ/ $Ǐu%,A.Ӣs7p{9v'З\@cXH T0xX pe2`Sc19f~ZLq>O!'Oq?ӈg K10fa- @ eAqoڙ6˘okK z4@ DǺ".sf}_xm= b~YOJD',A-m0ܘl ĉ⁌!07V &\˱̶g_HC3øACpf -%9a7'30AyAA;k˓6&X⁌!~^$a.]& Cc>\{\,\c\am-ya2E"I2L \ e ˠ3˷v wq/iDjn"AȄZcb)\s>?1!Y| 1 7"{b`4<߸ߙv "¬8 c!Zg90=ÜC°0_D$b_~ehZ2o!0)ێe `AɛL6 fK/̱׺{ikLg@dE`p!M& b/s&t{ͣ0Ysh;!a0ߘ- - %baP%6N2@هq92`={o26/v c19̷Ywc0;iXIaViec7s=ۄ.KֆBD! #/ " W/a M]DQb(.I3<^xA&֙"q/<q0Cf  ApDL˫M q )ctŧK7ufQs 6'Q5b:wm5ք0`0 X F.ywp#v;o6kiDJ9 =' jeaifֹ,AԎcløN=O#S Gbc2@74!][zw E(,9 [7H 2~>>x\!q^/%^C[ss16`0 M %O+ &ț̺F=cIŢ)91¨,LE )" @jB 0Mre;R Mf.SvXFXr1*/!aeBjERYj[jUbR`_( RL\0r`_1&xLx4Pnf_q<{+ YQi9SS6 3oBaWax˃ & KK9Ogp lK.g]D0ՏLvs掮JN]IۘZPB2O# 9n bh"8K70--&iS662_V> vCMGr&וk̨jqi&X|@7n3jZ1p T`/񙺈k #sX1VJ;^VXbBֹ?+3S"$J ı'JukzB#߈ä>PBGʁ*/aq>;h.8>ደ.`ULu?Z,6/D_OJG DJ?J tE"wwZ;{05&WP@Sum, U9 J݃q|M ca1@t qyAQ}a z{|T\fEQ)%-S5*yZDD@A(b%0(AOs;v1JQY+f+Hw5ª,fRihDXE=x{ޞ;OHQ/{^ydL,LOoɩ+"DEnB6y|GWχd]1HG<)V!oBŵ6&?L9Q Ji^PRV8<䬳Y|myB1ȇ隱TK'ZTȴmn٩?-K=,Lׄ-K(+jȮM4&$ŎX8"6i"ԓ~+iͩS"YeOԏj" )$&&21՗NKGGR2qN)Jz FFE^/eC8(MH ԐfT摧QR}u HHԒw ~T UL,ŹHO %%,3^-VHȡ]()s+K%蜟"jIIq=Y<{PX) Xq(4kKxbXL " 89 [ЋLR(tI544%Y|le^ŊB^$PLHlV,T*FlYbbI&HSQBeLL\a ?X)V"Ћl@9D(쾊ذ+(: fÍ=闾JCE -@i,X\ f+y(= XCB klYYcXd(iL袅ۨ2)1G؋/|d'ұy8E"X}s$K lB샍薛E=-<_DcC=|shR$"ђ+(So- *bHM6K*FhBdhF^|ˬ{%DU.F2jIR䋕NjHq-:ԋOJ5445DŽ.8*Ěbw- צGV?K8j90JLM ",R#3Ӣ:м%k^E!eQv_L&GPSM5]!xMpV(hh4$a݈Q]/*bbj8$!DX^X~QX$+g"{*+k$;%4MlXcmo ^V$K)dCRe+9'b/C#Ð䨲,,N؄9B{YLHQG~Q5>&Fj %<=a bÎ,R/ch鐘1 3h,M G;Sab8HiԶ=2H-,$OQذ/7C'I{hxt/FJVf[<&\,%5{[cyHiDɈ$"Q?M{rD#Tqf^-b"3Z\j+oz5/ݐ%efXBN5_el6^+#Qė#CӢB²&Ņ#o^+!mr8$X9͒|&Kղ"xI}߹(ذNN$Zk(e3g![az[a1z؊1z]oyYӏTk+{MԎzIbڿ:b1XAr -5("zn#(hҏ6H,P4AP!i}>Wp(Qb$&Yc=rBGI4ikѥMȞC[Dz BC$9rhͩ8JUV=qoRk(EHRBp%Ee11"XJdRh]*l$ bDD4 B%-5tY[,QGIt%a bcJE|CP^:WRR~I>G:[iONdRo46ԂtЛOzvגTԩ2Q܅@g:6'Ӵ}.KZ ;WCJ5(9WlqziIկGjk}N} B]6KM覩ІEa"(((x4$Tpv=IMgSˆׁʗ_rsgKzzzwlӕIKJM䖜#ÿElDH V/2ebe"Zw=6+^JMMM.=!Ƈ!HOm% bFB|Bbt6gU2"r~ȩ|5viQ2)B)h<&&X yCBi#uTP Ϩ~[,LuBaq(AUtq_ DWQ[48$"-mG_]4!ρ̾q/%2袈XMП T)Dr,bg5B, ~T6UE^f'B:Yy_$K$k}""- K-ض^/ .I>6XS9/}`"H|ؒ(q)}DYHl >ԓ,M1ĬYx}DBYHhT,d(:ɉ4V_q%cem'JLZLbe!<c)h !7E .v" pkgdown/tests/testthat/assets/articles-images/man/0000755000176200001440000000000014633374223022062 5ustar liggesuserspkgdown/tests/testthat/assets/articles-images/man/kitten.Rd0000644000176200001440000000013714633374223023650 0ustar liggesusers\name{kitten} \alias{kitten} \title{A picture of a kitten} \description{ \figure{kitten.jpg} } pkgdown/tests/testthat/assets/articles-images/man/figures/0000755000176200001440000000000014633374223023526 5ustar liggesuserspkgdown/tests/testthat/assets/articles-images/man/figures/kitten.jpg0000644000176200001440000014335714633374223025543 0ustar liggesusersJFIFHHICC_PROFILE lcmsmntrRGB XYZ )9acspAPPL-lcms desc^cprt\ wtpthbkpt|rXYZgXYZbXYZrTRC@gTRC@bTRC@descc2textIXXYZ -XYZ 3XYZ o8XYZ bXYZ $curvck ?Q4!)2;FQw]kpz|i}0    ##*%%*525EE\    ##*%%*525EE\" ~TQPA 1 "oD@DA@A"" F EEcDD7 " " j PQȂEh" "Tb((QA D*""UU@* "FA@ 4TCv"9@F "*(""#QDD@ADQv Wyr]KD@QF(55j UCv {>{/V"+"A L]^~CXh4D݀(|B_FRJLO>m%|Ķ7=]?]UW]:cXe4AvK;6վ8Līy.2<#PG OWxWu =.7d%ov-yDwn~SyίN೭^lkQ Fpbf7C@Z;B4~[$> `_8noNײt9Y}o0FW=涨3'^hy[\Rv1m(0>{Aύy5 Wb *y3c58(WMWk؇o6=:/}Y hD7( =S)Ǥ(gЪ댧;XGIrdZO}1nA)$[=Wmg]Ӕk_`zkW3Q35ԾcZPPM ( /LM;͙uK2Ãfl\IQ1+.۾]=sɍb T7H{H7TA dql˰x"zvGwms[RݡKʮ*z~c<UE@V( sUعPzGPe'4c^hp= |[p~lkPTQ@TCt_Gc,r5V|FͬkY֎=Sy"M{.͞H(( nDQ`7\o=G7^f}ݤrƮd\}_V7" Uy+EcȖw)yqw,J؛$2#afMlz7ͭDP ((YO4 g1qZpϤ{u-ܻA-+KgA4T{hn];y#S>Q`tFSҺXg͎Dt8f oZ E@ (cs q:K)wYQ6MH-o8 y'>syZҽOK0FsWɍDh@ )踼߈.v|Ӧ~ut$㳾Tj/П}X}#&e$A;㕽~~h (H?(pWuUI&.: Ef';ovvwjO=cgZ5 2 +įHqU8Ӛu\#VHyk,OC{]Y3Vy ("F9f+i=Ns>|vG-iD_h$[\_NzI" 宊rgʹFu~&ISowQ?0rOouH;n3:<ƈTAjnPC=24͉Gz\;L-Μ۩km/ɾ/{o//&D@ "㬧+[H}\`y+vdj5nizM?1As}v{u4ؾO{=sMZAvA%'^b52EDDD{}c|8WQmHˠP??l?I ־BmEͨA"WkO&R _f,'5{n.r:n7[oZwџX:AшDApU k+A7yq*Ҹ0pj{5nɆmfƣ2;dvlcEA& A '0. (WqYhr<4c7ܻ:!m{?3~u^<@"""""5kDžlVG_ +>UxQ)W9%RS,,ws'|zL{s?1 $#Pby5w},! ^vSs(%QYNʉk7[ݛ[A~ٹ4IP5`B9C4[Cwei +)vE4X>3vsBa?F:Q/ E 1#5tIW:JvԯyZCsf%VbbNV[u~^MjpDDֱ Q5P(6CD?.h9.:IbĬ^|΢PV#Ʌfn?/v́~~^lA"cZT\(OBuڭ,ogDq֛:[E_g7Ec,Oq9b $cX5"/v1xȴ6#62Ghdz\:@lK Hw}V/<؈֌hA0"FF N۵2? IJ=? 'AN,=qY9mcԞFQ1D`6|0kp Uzt2J5-d;,\b]uzx3ͪo#Z (yR*6ˏԹ#v;㇗eY$i|bnKvm`0DDֱF#CM."}*LT:mm wo\E+]'鯡c:QF5b5w5Z7EˈpHm9*> dv7O?5Q{[{w@kX#zXK^Y3҆Cˉsv? 6@q"ͳbj"r7ɺ7<#KkQkZDS[ k2 jPuYœWYpVeyK_5{u%gj^`cAs:$]-`G`pSŭ( Ej5]znaK*s[`2g F#֠G9k w!>RlS gz|oU`QjU!F`ئZ[/6ڀ"5cZ:xnN1MePT8ő2V:Y?\Hc;_On /_wWHuսo k֠K AiG"K,[UqlZǩrw%*,]Զ^ש;w5-FcX֠Q^S\b{\tTP>2_:R?OYQJg%޾~Lb%" k#TWg$9,Y6U2qؿct;/Oiyd2)']Yx]-Gֳ-&"#cLm$nV%SMeYpt/֮M d`ɺvư{]4.@Dj#QmD`Cc23>@^쯛{}~M6ʒ{}l*!<};e"@@@TDy[\\OR 9mko8E&Vưuzz,>wM( yxch2AjhsZt _5ac{W·6fU =}WVM QPxj#I+J;Ec2*$n -hڽs]7736D`[=gn?D8+B[9%4^#u&Zzʥ<2k%l#AG=ZZΞ3?w іtq<]9WCV),hcDK*^+bǖﶙ9pDGq+X?WXoʝ/Tlk45 yMrc%TEL}7oڳYNa (sSʦv6Dzbz-~MUW"jZ9Nh/GmNv^Gm" =#GOrOXReqZ:m&un [Q)W{7 WiI'=ܝObs}}^F D+7q\?Zls/sOᇮ>k'/*믤g~x/6}VȻ\]ek+_Id2Kx>uӻ=s9vhQŒ>\i-:K7{iXRMT`sܠ+h5QA珍|yހ~|r]n -pW\9UAA"  *5g0HGGե5DWWEDA@Db"#婮-:ļeY* h  zUxADDA@Aj5v'  \ڀ@A #ִj"AUQ9U6"" AcZ""(5 Usթl mM1a& Mpq=6>0B]2V[|)$g ޾a[:Z} 3Xpz̵v=0g+YoPgW|vXԓMg+._#Wsmf%wO!48g+8;(ǃMmsՄ(K~O#Fn?Ͳ>o`4Vy%ޫ]9\ G껐Rl l2z,ݯU`!BX??Kp櫯 H `B'tSf~A۵NL1+.^s'E'&a#F}Wm<ҷjDsl,erJ%qRcc U5 hR+~t% L% 3>lج5cf@rlNZhӪB8Mʢ940J.qsh7 IEh Tޞaxq!s*5[Zim3䦚bS*UUP5ew*!e{)Wz@L< Elg(֑V@/7NͮKVRG ]˞jHfUn9\|Ɣ]9x.Wȭ.}s͸Ev֔%˧-`G䞫k_v5dzeǒztt:;il 9m͂c!EΣnD`!D)0"*V `1$ZĬb@"&"bbah$+3 @&, DWv"@_-k6_K~O[ \=gqx`{zM*rܶ :ϛ&ks{=߆~.]KO|Ã[>x{>_C=[~go?7G]<_og>w[?K+{9{oc2Vf#$,$)WG]4*-#&fBV1 q($D2!"P@#1 2$03A`BzX+0vcOm[qMhO)\7X-ђm}7ZCodݦFi]h`hKb&&32&2g;|s9#pngb2}r^-,쬸?^͠*\ꮟ핚Wz,_WwXg^f-zWE F$;eyF1,{1%.؍YuV-ϳabC EG"qLO cCRJ[J.,dLaZZ\m6Uk0H5?ySL II+zOʓ$G}C*J?jl鍫6ftc\PnfÇeP:.p#Vɒ. t*w4~qDZk(Њ~jV@Z@q֩-š|\XwύVGgOreuxw7墎ov ŭZN@'S9._M ;[9oi?"wmez<]"Zh(UU5aW©)*4Ɨ-€~#w>UE8 B&[rq%#eO $82qe*{o=M&L]Bß[\p,#AuN.v`%sjk ;/<(sL'ga[~ݓ>bJ >X7E(:vp' ƸRø#y.\ߡ0^Mcwe]4}RJ9V,W8J}T\0mP%u%Ai# 5G~&ԳຣZH'X A|ZHm /Khʻ)SG5ÓRvr}|jUo5dbϰsvٚ-gH@OeI5酟=wp/e;+4Wv7Wmy#;M gnQL'2捞1601|$Y2.oUXֲ&H#YB=;>&i M^ u'բ\gUJdO-z|ڹLD,H` T72y ]fKA6V龱o^ḫ퍒X*܏Z7CLdvwl3FҐA}\~}C?,!l^h4kׄrYAo_W+?3QMbOR>h0 ORp6ЕoEa]B&ڝ=DFU}- |ZN䣉 f*<اډ^Ll{K5ܮSR*~}"y#!⬮-\:3Z lR3uAiRl8T I]٨€+Sg0k~I**gkkw:1)/_ci"C,L"'mp>' Kl45q%Գ$Rho*Eu(+ |鶷:4T}C$f_n5䶮Ix"˘۳Xgfc-0!I~u򱶄HT,3&/۳4@Eq?>3dF]aQG>-SQ<+2_rECXG9J mqM NNW 6i"CVKE#2 c@\RxrZc=8}}__\V["9Α<)q&̖`DN0C,-YO$bR+f&=Jcr,ҕ8ȎЖm i}XCݥW!>#&J&q!idLˀ!\CYCȄgCS'}g"?q77@F/ЭLJ ",{g39 WUDOUc"N\6!0;Q\J_2ڕ+%`m5vzӍvLX 3<@ "J-3KE6VDerCw\17 PBQı<ܪc ~FqVθu>0 sNd[Y*l&M2UO;.32Y)%_W~)y%43s;fybh&r "$GO!hAZ߬.91Avai ٥gg fхjܻ q65|DAgf1]f-,!-,Nh^hvD:g<#^iVV! 9Zf> m)yd-ۈm8;)3q]E ݺmmk;]"n صCa t)b$<Ȓe+)ު%BK"kGXKFc?Έ_rt H l8 @agވ> ضl{T3`.}+]JYCIu#=Ö1败HK 0†fR0Be`K6JDsbӚ!6Q}#'7"}.5bu)5',0UI #xς:nލ]*5nbW; jnZb[‹Q܇ۅf1s<%ߟ\1bg2 hzgOE65Xz8T%#Wly"F!mOr3`1$vC}./צt˱XEjJuϢV7< ^'*eu\ŝ-ˆ,=s&*J6brC Y5 ")fc:=56,%<c cQ5l\,(J;eC"$v91"9ALNk0@dO 1\l+ciT(mI0v|pЭuUQ?J NçjSR`|$S"oanʢ"E ܥjB\N,N{$eM.$ض#YIR3,VSW^-hJe.e+΂߰aA܀?Ϝ`aU尙0~p}FIު^%*g@& s]¥@ذ5EZR7nï~̤֤֔>)E-d,[զPPO#iMEqN'-$66`bވ2$~_rBw99sy`H}e}hO"8,* P`תEFC[NGؙ7ĽevѻAjZz6ͺϛl\]uf$CYwoQYl,dѢ d2j hX;%LY,gެAfC)(j9s9sH aFNB¯%Xx8 VN ĕ >SD6W¶rޫ=A~c{kؖuA)de8-&6Q),lK+6PtݘA"WY;<Ƞ]׎K$YpZ{uOؘs9s9s.d8=m VdJ3R]eĭjnQ\g.4_)˔e.׹zR9`(M6M%+!WdXJ-A2:LJ$!A-DN_oSIg9s9sr8!T^/%Yؿ(zDCUWf#Rcń65a5\eSjEV]#>>BduU!gRFhzR1 0Cbd=c+Yc;PB8&>֥LTul> RZQQRLXapbU,x5[م$秊\J{FʷbeUf"&A*/]lk `0ؒ[2ԭP̤JTve,9s9s?ǜdd16![2X&?DOWn"}/6+Ȱ`,gܻybnVפb=kIr:SZ,E;3}h6卤a6 ]IFWWxZ )oH{x)ǜ2~IJ3 Ab%Vfu}bl7M&lkk6ا,DL ,^l5Wmt@ՊPCn"{Sal@ٙ'V^'NE?1͟4{>XfUSn*5f[ڙ Zr.U^\}r[ o^$  k^g#`J!C%!2omm, .?o&NK'-Aq6 "O2 ei#[skzԶ`O`$e QAqLm!׮)7f2uc,EX*nJn5`C+YBُ}ŝ~Sq0+TTe_oq6}y? g] $B<r#I@F)k.(hmWk1upKc$ aN]eA˝C6&uv w)ַjV"z&z Ky7f =ʐ1MΔAH&fbf y*ȏYrya̡ްv"+ nӚAOhqb|laţ)E MUdsr=d^|ًF@N[@Ƌ՚T&fNȚV":EIjڝbcM<ࢹIݷ01`0JnF!Rϱ2S^<|1wvy%RUZ#5? |~Pv,e XXCKc ܝ(7))a]Vq:Gȃw >lZ#\L?`,"g, 6jmVe5?fB :nƷvL il\s%X?RaV+ֻ8oh/&SյXu1,& L[FjaMd*pG5r-P)Uf$F%ɸJ-gs3+R9aLN2&mkeUqhI-B0{R,;Ckz6E R9u A{n@uۘUlOּ̫{"]YWH=UaA֮BukVkUaj`LS-Ef[hW`)ݷAINec9s(( arg]&\$,ӘbhEq BmeΗvkQZY׮":) eI;Vrj܆aP_g+VçK~6.ygq).ê-Y{Sm㓱^\nv(Z ǐwQ\s8̮2kzSq0Yb-b'*k_+5$Qg_ i XI=49's#K0Ĵ{ |q-%9&YG1{n9_T6O0xŴHC,*]bl*ܰy o"]TZ,,R/JN6WY&.gqz0SE:}8Ȍ8q&m7LZ`^>blyk9M";dHesX۞]0H- ~H޳363]snFeNױ Hhٸ%FMb 6&p䰒z6u\+R+` 2 s[p 3$  +eYi?+kˣKo%XMGnqr9LlA$8MCOcam ,`53fdS31,R}QK]\ su3 #]1WR'B*X2>AȰµͮrݙT=Q26<J!&P&Xʈ:S&7`>-ԛBq{& K3}:s>ʺab>j͆XJ'h9 a4Z0hC$qf3SeSݖ=,eϷ0 rɜE )ZK9|ƫPӁD#"FBc 2 sBXZCkOZL =U[?UXң\AV HMǗ{'uemyl#is\肈|dd&2*dxi G8ŞÌm~=zLWMCι83sM"ϛ6shfұ^U9``tz"bF{mc^qSiO+Dؽn9yOo|Z'fiOQig$bq?6-[υ\7vF7-wxV{5onC@Jڼ -e&+8hL}f+^1Xc!Q#:\Ƣmx;8PH2G$c=c,3Hޙ1XfN>kU+*^][)*1,* "8)ιx38qg\mH,yW-eK #jеOu]h*ڎW¬`xyk(xΛyJ<:mrR3?9o9s?ל99s9s9}sF!1A"Qa2qBP#R3br C$S`@cs?|[U荵wHp?R?of؜b0}UŦx]ęBׇǪc;KKswuuiD{Y6=Т۞5ePuWa2xm#.#CdkwV.$` :T6?n<u='qy>Iś+&jgx> pj3;vY* 'P;8 pas5"'Tkw7 A?GBLQcIɖm FC]tQ"z'puQxD"P`x/-[FiRS_+Ԩ&FF]f_k >v2~9D&*9,7ˊ|Ӎ;aq7ߌ&!UkUFKD v]y[ "mG4" )!E'eU]3꣼8˒"%$Zچ-v%Ibѧ|y;](Mq1qw皍΃M.q^3ztWLwֻm vgt |e&`|cCl&u} 0?izOx^ѡĵOy`3Nc}=OQ!8C;|\Cv#';P%QYZ.QNER߈X":?ě3$.Q|6itF㱟TTAٽ#0/5T,l@''tlV\)kz^ .BmidZrg6Q"Ph?RyBsT!ip"ӧȦ8'\&M%ߢ/P`ȻGȟo dsuDM}ߦB^zkC@kN5Ic@v9ivLu5^ r5Sp "hlW c>i+<;V7K;Eu ˿޳T_b2 e8G-qrt>E= 6=J{&Y#qA÷|4U@ʹwO7DNFqRiig `-r@^˲M 'rwϴaVRkir5Zdq<ԾV}ώă벸`&j4QI{!}!^tQݼy883(=a\AB&:jkL^To4^d7[](q2pFZ:TCsO¿52Y?xwX6NV0Od-glֈ/|HV~hU˧~'kc$Qhcߌi丨GݯNa&]A io ƢH jm>s .QNy\5VtE/i>:]2= !L|S]9mQv]3-Qiո9k4~ctj6b~Tz4y],8`5CSXq\|JYƎw'8F泩B'`dn:ƻNpts? j ԩw%>]K)?a##מ(UwO j׸|g>݀[v"CAqݜ6T鳊2KG"> s sXQhyE-Ĉ=9,(U> 9Ev txsFʘps٢IU#K+'Z"Ne ȣ#I!MR=9!p ' oPWАAsGBa"7Ħj t͊5jd$jyQ嶱D9N!:.]:v5MdOWju?a< N79 AF8'5[7~`]} '|7ڻPs{{O:z[? x.ha9쁕Μge={'KuA: Zz,"7\G*CvQ9փSZEƓiܶt cl8 cDgFz)8S\`]ZA꩜Ds2ַC & 3ISZ+6sx,ԬnUϭ.P-qtC-n̡%2g䎠G䁤 Ĕ׺M]τ|Tx m9yqLòmZ=PLAeLGDD@C Bfciy kG4G,=8=Ӂi73X=ISoL'*4ȩ&$ןScpMJD3zʤqkqa1N8]d3_h < o,b|P4#haѹdUi1|o+N Iԭ}W`+Vh~F8j|fҝ-to9,ynG1 E 6&ɝ6 G9Zk= X"3A13#6D=:E;G$ >(Ϩ[&m~?4k5qZ [FLy [Nd ''}cnw^tYdƫ!81 kyy+y[UINS`d պ`#泩_ܬUK%_g]Rk7^jtMiH ,4G[(T9tݕ a?Nk}!i aIK@eZdܕXBF=Θk[T:Q.#=r(tSu/'S}U :TϪya9!k3Ѫ\:Jwv֎n໨$&?u'GNt{KpVc@X>ȩM{;six:bI;ewר)1ȫ7vgb  ϒ9䋆:ss3þ2WD4 -sm-&:ye<#w n D.h'  z-wZ= y`-w44>)-MtX?&?>Xa%Rj1!9}5Uʎ`J>HnJ88ځs$GD{;vpK0U2 * G]Nuk?G N*&ZwwO%: +hn vaޑLm)"\rui@*C m@8Ժ0ot} exAW!̀x~H49)pOf;#uR<6"Dyu1ZceX5DVtGvce=#PUOc\wb0vXխcv`%PDÈ83 a+Z׀4}YɼX \pdd1=Cy8:c sZ$G3h}٤D:w~H"4h0jQ29'Qp;~Mq@  ؆`C}S=Qhs !H_ƧnI#Q1?NyE޻Xz0hѫ"h4Am`9pQc녒'&B?4x <¶ 't=ϔ9ܵuX@1!;ȉ%m8p1lOAU-E*F'bP>%U}I>klzm%8.DaqϚ9]&v7 'V4iac(mT!&_D1WY5_?WsƤ7椏\Aѱ?s=j"^xa>Z-eNܡ4 "z\'lP@ Z9oI7|̦FO0ާDy,2lݝM9m#KuEx' ,uh݂NuGHcHNy L0 8* ?Aˋ'S-#"ݑFi i[a!07Q֎dʹ NOQ(BwGǡ'ᶋxNe p1vȵp3yO[|HMww][o̦LW'y=dC}pV8ҿYc}hG]ᜋ~82 o7D>j#M ʕf<Be`: 4kCGieYY 2a kn!ٙJN?! -ZgY*{;P殘!bs-m'xPApR˄i|5V磀$S?E뇒Ɵ`߄803 Z2iWԦ`k Ha c sm )ҳ? I|^ꁸ8V各GL'6nVʍĂnIR فn$._5J?ADwS.*x'q'ZL~4UuKzv8"~iELb=C{1s=LDnOA:) #mG+Rk{%(ΫKA^!:8D[R"@# q77஦Vsj"AR6?ܰ~hّ Clqۚ}U₃\OQ!8>*V~hM;h>h+:4!K9D>KU dy~j GI3z D55KY&>Dhzv^D8j?eh;A%SHučmdn1n;|ƅ`:+Z!p_D{0pG~:;8OѐAʁ@'DF$JdcGN%)k" i_T)AK$y}J7E3\Ep3\ ~Ϸ|O8~s<܀yn3r j$e[(hܹ(?"CCFGn^s ,t"!4nfQ]Fx!|6La )w GwGkioi4馨Ō'uTܡb]$k0z( 9(zO-T(΋EM(TF9!E+e]1SgkUi|– 8~&a 5};9m;x'џ'uLX tOm7 k]CҜжGYpTvW9\5IM]>#U4_T}@T7:hW.aZ\cӒt}6'g- }6!v"wr+45htꃇ  ?f+(jRXZAEa -ܮ.=[F6ӪD,(~v" %Jx7V9v䬪lq͎}z!\ `ÓBn;tMez._BZq'nN gчt<ky:sW޴;Pp ^idB-PJ.:,dX%C3CĠ7o/] k?@k?$pxNɭh+ O3N.v~0$k6GMu8.#kT0 ?|dowIJ4lS{@0~@t;l3͇%کwZ-iڹէ֒>~ o4{$KڱAhu2ɏO$\<ܝ:!f`X#E ~J0b)\L*HX\Q)ZTx޾OE/U n:1>qAgxFmX$éG!%3>o>>>tOqʩ*xH0 AeL<*7sOnTjWu oOXjS .iF|3VSj4Kc`/h Kjm#1?T`߆~!~ŏty#/XeT|.?_UŢh걪S)iGۄs#g3: n50 WFct|_KD*i}-ӪP8]j_"e1i_A\tvDc#"E2sAHVf;?ҝWA)(͂8\A[ x|x{ k\x5-|ԏn$ X_; ۊ,/58Z@B C>2c|EJ;YWxm>6 ;PcFָq*.LnSs0rAUli]<˒sa!Fr>P$ƆSY]SkoSwIBs<KP,өO\5GQ?sZnGMS2ٝv?zH>[Nz-NUniY,%V @ۮ;K~}'n}=\m vq!@s+08x8h.* %xpZ`6%m"H5 hVΉn܊twy]QLMh8T]!۹! \u7TpkLftQ i&5xE? UPpޛA] :${ MAa.TeJ:DWemK\zDkb6HFE =y&i&p:d&=NFD޷;_B@ʼCP4Ih`)C 3W @)*e5=Pqo]nҦIG$\) Бh0N.O!rCza$i~Jw2L l:ZUsMhs]H,>u{m n^H5Mm[0Okݼ;6U{=jp{#:\Ҩ4A眅Tՠ*d{F8'57;xc1U@x]CHFoE+Vdp d5q - 5R{;Z:#eW4b& %I!R_j]xGJ?.$6@8 27֖5) 7&(?8XovL;Np"^b5OK" dQN ' |g wZ-UݚNeG#-Uic+^sxEԮ:Cm}G$Ca#MtsM Ntkٱ݈CI^*{#UT"r5k5(I\"J+U3ehЏ݁("n"WvLpK4k䩽xӞ[hپ)$j-'.jGsZ&n'L&xu͍Ahտw8p#L?P2A>X폒@pČnFR=kioG6tSHw\鹜+/Ć8dKTn\qi80s?|ƄgZ}ߢaCc`t+-ROEZZDP Bc ~(o<CW7(iXTpFo+9!^aWdGp@8d[m1Nse`uN]w:(Teg#"9/OAeJsBqu"Fmzwj1̬i [ts[A8j-wgg@]ibfy¸1VZ'Y2 Box!a&T-Z#O@fƜs6 T5 GFg`UJͱ<9UR^91ێ"0XM^A (hmZd@$j1#`8Bvr-hmv? 86p@HKE81w4a{HG1O0׶iy'6CZZXsJecQpQ\9  T8 ~%mlj:O5 &V !(Oz}Eʻ/Nj#4ELH(t'v`9]r 5r_o,.!7=`1D_~4uZ]t)\ *{/x0zS择8OV|tEz\Gn0SCSK/alƕS9M{U杜T۴}P p!4@!e4 e>R?4'AȎJH'}nv a6iQ.iDXU)fע 8_ɮ9d1ƪQXzmVw ʘ@2`,8,7V}P<%C7 `΋!)Ftjo9#Z߾ǪgG"N!;*h_1㎕[$M4~-Uk1kxsSDW'(?n8w-'y9;V\N=JnjtvӉVd!y)pioeV|Qy"ڲ҅% \71C % {Dj<逿֏oݎDTsYP`Gy P?'Tz.5q)!շklA4羈i3th}3]@iʸϯ5Z-8{Lo~Xh!Kͼ)~m?cZxi]a$s[l[{Nz.p捭\+OEdabUoZq貚3`3j?A8pSTO1*@&S{*F:r tkIXjƟ%W1[*-3jbƇBgpٸ%5 85cFr .Z} 喫Ki@8IQYV9 @:m a"ZzZ)!rN2G{ F-vҏ)M$2PcN]z.hcU$9J}Jcx ! 2D(K95LwYfFQū>%גsA әD1({-PV%h[hS#{5Ѕܼ\#p#et!2 `9ʨ)ԣR5Bp: 訢VO4Kϒ NN-kBˣgG>i U)\9P&©ih!?ѫφ$7Tg ծxH^!\ x'6w䆡 H j !`&42ri;(f6L=c s_S=Q($Ϛ`nzXщ$. mULP6?cQ- hO*x<($;G)Y)Zkg>EYQBLèRܷpӺ{ c)2!~9F;HɲUnkP?(?E- ݦ" aW[2¨~EsOTliObe*= $F5zU GDZtENkvEm8(HMnB/G+%`i)ĦϹ2ZQ8Zu” @ 082P:_o ӣCih5U^!QRSɻ.qBFŽKN$PkQs<;E8?hMq~F+䨔@ a9ϢpĎyp4h70 iS;8D pQ0zaX?gA#-5Hגo6Eahe0!> "D#D Z,Pvд] cdHU4J[:iП?![Uy9 NdǵHxSU>!Z KvPjC !zYDGN&4'?aM#Dz[ Y#Dž4Zj!>SFL  o2'( :1K +*[ P'%jA-v?c5GiZt(ۑ[5Q, C*ڇ1ݟcyg;Ear讥\4Rʒ9G2?0 kE/42g(P>)EJӋOV{*hui@GXY0ZcwB'uH{Td,KMnҿipS a7C⅒)kjqnr&JhMPq5$ ,k‰qD"CчJOTB6NrV>^Z-r$$IdZ[~K㓔9YZG%۱‡cslP nٜ8)nTgp ESl d|Hdt*"\=V\'CB h- XX &6QzqdثcEw=v \NJۂ$U;rM{ vVN@Do]ꅦ9eg5EM2 EDBl Q62ܠ+ Os钪S3.]p˓( vwD'Tq+<^V\J:j7š$9@2ؕáVQmHX٢삹vS.SMVįJ7eV\9!GiL++At[ n4"d|K>jXn>yz?fEhZ*A`즴87ݤD7)lmW[u3.<>W*!1AQaq 0@P?ǯ_ge,گ~L?RJ+~|ԩRW|W|T_D_ 5+COϊ*TRJ+TR|J*T_Lrj`ƅێ!\"qI*T*'¥J*T_Rnc|9(Dr1t^FÓ<˗寸 rPw(CQs\Ce~*WJ*TR|:~XdFٔWOʕN0~bMuU @T'qIsD1cM3%a'H0{-"+&g8`h0@Z-[-R_jЂC܁YgyE䢶) 846 @Jh11{%GUEXqvic*s:@hǓk$kULE/գ^awȽ]%)'d @JX`T / 0R4׉ZB/(eUe\5TXj2.ͪ1[ s02!V[{È6 +ia/Aĵub \+MB} އz`>}(5/y%g;#4?7 ӊkP \ $V{Ax/n׈j}#̴,) \bRHkG"k U^nRZ4>qFK)³B4؀Y@Pe_L⠝c!p߰Īb#AWzfUkϾ|AȀS4CGR^a^$2R咺4q|?0>kѮlQ6_JB֗쐲;*Cۆ MJ䰩cܤ,`0!#Z5ٕ$=%{U!X!Y!mDO5C/#$l kn q\-t3O-S^ЃT& <Gs'%&Nzfs Z8?i"XjyieuB̍6T[~ G]d2$lK~<@CuxɄ ՔxfnU 9kX[#qLZnf?d>7I@IAV36hY#{0yU(!:bSc;`:K{Sx@bqR mN4 WF.8Y*jy"5V0Mlr{1_IY >ڀ'gx LSq2ZУBV~,-=F@^ lhIG,!x?cEebpey] q`tkŖ@U^YF`Q3y,z)U+&=dAp#d1P{Q2l ib-XIt_`f*^WY)Gcϰ^A8.S7Zf1f=_WмӜ 4-c -W~̄RVڱz#@x1i5@wTJf-U腏0Ѷi,|t5-V/Y Z)~+=k54, * pbP8}O- ۟au$2*ĪH5q` 4)Tc (}aܢ %֫ fഅnGmnY",XTVE/\Jk*3bK{p¯&Q)n X i.<P0̐EW/VKR7bOd+I[9*(ZG{w}`d)#5e(%4vΉtBsruA[ wAhح*0qGeFglJp(%We׶h0q梣k' b!;<ADRѮ7XXt!B#]Q Xx*_4DFs.u+bQ%ucgJ穙Z,{m+VT(bc4 F0$Oy>01΀Sp":g,H56yȞ 2CO'~rϒXu ;(Jɭ'/iskODh:aj8wZ.OK x}V6b~e(q譮^콡 Јjwg/x#29l47^S4.:;NpJ4#d|ffDf.*5 6l^`  1~n_|˱E:Q+l7͊ԖxS!FIvkI1k) jneZ::ΏZ5 z25>|[r=KUWEi (d?K /ưy>e!ڥאJ-jP%# 7(r]*eP4Ah9`\! !pFJR}!+Zۦ9mGo+V8F & _ihYdzL$Ͽ;2=ăs4HY +X?i򨚅g<]f^J)e  >ma$tٚIH P]n KvAOh: @J=p*Dܲ9"LBB3XTiTL.c0H3fmZ6EXuܰq0[֍t}3`1j.G( eUTcN\1ꀸ:OF^X)t8 &U`4@_ba(*~ܿ*87ѕ]+Մ@WT~\fp1^!ո<S (F9{d#(0)lZμybBڌ[bղDfSPPUR]PBLjSDhsz]䦏,ѺaĪS釰=S:YTd%c v\,uw0cd|oPڃ!LX@<GAsPb(VbQOi6*8k,dշ!fLHN7/'Hm,P 䥟pd#{ ?5Uj!0`J[Ml yfb) L[*(UQbPh)|5EywSxR 2,AʣHt 8ZwRtT$!XRiߨl `x@[cX)V;J\+3ƪ t 8,_,c~l P)JnDһkP7+C:ctV$TcٿQy  Zq,$6)1n|@~Zqbl虅J^Ս)#8.k"I`⅄ ]ljjrU0)Bo(mw3L7edD/"eCw%ۆ#J`ňWDJX\{gf‚")4ėA7×lhU;`/F?Y@0Pū5p=CCwM~hxR[hot)1V* pVhy2vU}=Rw|&Lo [ #BoIJ٠ݎظ_fe :}hFjoEwFG p skt\Y|W0ֺZ<]FmU4{HzU[K@v&}A6D`|`cA^ۯ(o;rׅD/KIh4(О"78GC1o jhSQ&OΙ &tc9, ܨcbcLQv& !u7L =n`b뚁9ol])a g,MPeVy pX]!"!Q_d:Wf|q+xJmRb MmKbg PeEt%Y@[WPV PaG6E;Xc1+HQU[R"A"eTx/ `@V 2Z؄LMY:a´ڎKq5IF:Tr/L wQwAȸ`xGϝr.:Ϙcjny [ E<:Ǹǃ$™:ec9f_ڼK&ع\ D|?EŮǠ>[~Bv, 'nП))\h9~e vҀf[)zp%ԽP8QXXJa^~R;Xa%!Xame,]eEnGc JbF}&ӭ%$ñf@k'f(oֽϻ!#|.8]$)We)#` -r^vY bRg/G鎁N&۴rÛR؛`r"ʑ^_,LJ$Ox )ri{fP0FݿDNХotE[x1V*jߘ9}us+?%=~ecШ_jDw{E t=pLQ5i+RǁD9/Hl˚hf ꈴho'a^e2YJWCoyXL{"dGڨqMca9` s,CdcA0J6H𦖏ҶyEYalش 5eKfkelUY%S^Uq W~~ ezQ@8%]B;P729rĹ.|0ba\4{b gs8`/U .:ŀvBmYja8V#(l+<=ķ`' k>9Iחh|\IJ}TH<֝GaؘP[IǦSy'$eB- +ehtКjv) ꣡d>*e*ʚgM@mC+ɹXu v>"/bTHi)mw@Z+:@L?@ i@DKp}_Pۿ }FECQx:^/\ }Y5JVkBޗ -c0]t&*W_鍊% c dC|BI[6oq5Y F-*b|FO]8K+F 6a-orZY,-zb+[=%t%S&4_ǔaeX  T+7z'uDXZ'׸z];V0%K K(xqu%jS冫\k/%\MpqْO]}2Vp/`+F9 uEh~ [:0oVz$ L;+3iP ʼ^q%J ri"񺱍 `vQc' ze>bwľ̥oܼ"|bg/YA^ h hKhɉ%Iد_͜l(" ps |d,,/\GݪނXǓO,X-P:9/&~<a( w?ңR9i*˦X9{ccJz>) j+ה" vVhSPLS v>S." 8 q)28%Z_C`>mG %֍)ZT4]8M㘰̵ hȑl!cuqM=yP-v{>o,v p ø@Pyn;TpMk9sU&3|-?ʷ(@ADK!̪Z0 KS y& VbV--6<4y>a7CXD"uVฅQxD! !f)f'gFnEG MspPN _ea u|$i QFtj^ [c{MU4˖pV rb2A"D5_ZZeEŒ),в=~K=KY|#0UJP=D!h5 NLƒ8b;\x8r}{\@8pq)0&&ڱπ/CFusq\@[GhWC .s ay]A9Q- ť׷Fd5S}싀v.%ȯ6#@X5M|IW0[ ,ip#c`xqRs42t`({Ƣs Vqth-"я⬛ļTq ZbTFaykÄzaa$("Pb?U?_Zcj.ħ7TFJ+Lxl>^'%x ;C%Ψf[  WQ -$1Nn2{#)(LA1.eWh<0r~CzjFU6BJpS(z ]leZlRRlS0.Y⚎Lan3ʆl+el Lv3Zaśl͑sz4J aP6&/}CW]!WG2^`ut>2D –is^^y&HAzS \ۿEq6)P'SE8j qa7v f7S=%W Q@}BpwNJd(TǛdFBRa7XZ S Wqu)Od3'B®*Ij  # sܿRQ wș-r wz<$`6<'ᶌ0,oɀWp%@]!@l3M T$O#g|C+c~;U esI)N +Д§R.,~?j_g\.3rUѸ`Vm PN*0x "1)wp4+X0AwbI.1(%R3[ 10lGRmI*cQLjJ5_g\ 8EP ]Nj9Q8F-[ J#逡7a@MX8-AcrKtwij41ޠl ʹC"f PЌ0/q e3/l40R/_r<@?vոQn Ii{rnˀ{g8:fXBB|40W회OZ+ak^!{4hXm%IjyK- 5uɻ#MaLSqNV%ؠ'N"%Ff ̬5- "\^j"J2e2 {P4탇PXiG+1o4XByʌcHύCy.0'1ZIDPIb!)zN)v*)([">G E̳R?Vqfbn~ \` YkS,]5l-k˶ rzX0.19Y # M`h(k@1 D5Za_c?#,v)QNf[]0(/`lcB+93KVlLgA(z00#=ѭkgvXLt(/Hx|aʯ=ūeX{o}̔Efd1箆nHani*U~:l@FO_ޑ1z ͓ cRܢ2m sfZ0`_c"`j1D.809rࡶ2jqynad!JPhhB573/-]&,>&`>>N&&4x2Y`HH`0ƠBV pUܮҸFx.*c2*x($[9讔2L"'&pЭ8uA0[,jm"\1尿ZAR K|BKԮMԐ%~.\P <]JBuwIkrtED( O9F+6̨(3EJf 18MmZ4*i D!ۤ$#0p;@IgxUh9=33s2ﰐ8{DVh,4MH ^=ˑ"榊șoL4t m0?)~,D~$H'7/rH`5IUn?G4B#]{j/l]\Bw`e-1/C;%yh3gwl [uyMaup6^).pN^ C'{X282D^#}<QAHȮ5+Phᘄ0Fk(! kG!!6ۆ(^ N4"底A:8Xʂ#KPU$R7WX̑A 6{ca@-Ax?`RrzZ:*z==Y`@ށbcr J5eZ^GB Ő ѭ2?K9]+dE[)_>!yah*LaЬ>  @9 9 0b ]1Giчa2!&eI>KHdplR& 8\GO /_n.8%Hז`V޺d-}d/Jkczn%gWVHa?\C 8EѰp؜BL.V<1MzaױԢ%VвJG^A8mL\  &vHQM`3KϘLoc-4*w&Җ}W#)#20 eFP\wfLEa[ ZafQ3%DO7/4"1 vʴ *n $e#ce 8,XNhץuU2(t+ԙyBcutӑ#vmE5/ FY R ivøT?fSuEįdM60|\I3ae.KeԬy&V+isbJd &AW b1c -WY[03`NASiRn~UfD%*QP=3!T`={ uQhNX8d/y9% !A 0K[j1kDj <==*pĕ@ 3ټ Qc+/1W* BPAT>*' sPC?!ji&tRGFMAىQ+ zanNIIx,щR:ua$pab\ӓZ0Y[ SgK ^21Cَц#4dj8%P`=! ]XXƁ : EM.8Vx[(1?Ԓ"h;;Yg7+•7`Ԥ.eQflB,!vG2yk \~T_l"lLSs~qD(ȑ9k nC!d^$%TvMpዥp̭]f5Ŀ,!0ş*(-'TfpvlG\,7[X @-vm 7(}9%p1"V1O%߅ˠX,H*%1G 1"Mto~ĢƔbs*64%\bV4DcY6aQK(P- .cBJ}cHEȝtEg9yK F}^&QCs/ EtQ39nҔbz 0G$Xv&&n\\.j&J8|$DhbK**0"O`ei1Bj0p%˳{eקے+\$%ڷXh򚊍YC:`U@qCpQ#q9ʱ(X>>Ro(#VL+D3z<5Q%q I> c2bFcTG5}D\&cx+bsshRq/큚w2 Zؖ/Ln?$l@pY!1_Jq.GFk$Q`UPTflt@])CrΠH)oQRJ!cԩUb' @ $"3r%eX,ݑ7N5H3Y,l% ԈhJs dTD5uv# O=c@w]^ZNQ'3aWX*0F vmJNP0@~\4#^"U|^LJ_^U0F-`IhquTq:,2g*&RvY"azW <,, RpJ ?C4In )2$>H|oܸ?-8X\$F\ˑ:X;Yb)P xA|41/ Kڱjpd]⬐F@ET0lJ@*VR*L6@qGO(גV^J+Q'>H2TfWA=EUF@΍BG g: ekiHm?^UGV+dڤe\L/7;"v )*T_ޥ?2BA۞T,# kOs_GXP+#G7 J+~%6&e`4*AD p̚CTHu(@ qQʇ¶~+MϓYrr˗.\<%w.\.\.\.\X˗/.\r>_J%y\ZZ[1h2˗?/!1A 0@a"Qq2#BP?.Ye_ƾ|6YeY~,iYe_/ھ͚ID~1}G #(K2؊g'%rW,D d. p1jeVC_)*R?[-Zz"4-\T_9?4KQ*?Y2Fm~95c!v]W1813b vqiEϤbomVz2:=ei.JYBHݒ(^ʌ+&F$1! dR5yc?9A~c}W;U{fe噚invd[^'G@&Wsi>R8F!w:"i/W*Qj3N'&ISrMZ% Q(憞GJHj6bk>IfQ?-3I6M?j_"V]e'6&cJFm<;LMhhdDCE'\sfƙ4zˊH'#&Q{[}=S3Qۤ&H{YHOzENv?ie䒔"zY>ͅAyBn2bv)ms D䶿zv}JM6C-.3Ou&늤g`҃Qp=5ߓV,nW37+&F]2ͶOOF6f+d };>)#jr+t6HjFij%&mZ|0x0fQ{[/迳U%tzviYq>$yU2}c1_S9IF+ڳ}.)Yq+k5TĠ&Şf,U 3 3O!/,cWřԔ '2zN/&-KzFrK$Mu3w>YeGMZjfҢ1(1SY f6M2Xb"ZXiǿÁF\Q{#S\[mdp*jh)42`9_12U!cJ=lI$wlH|VY~ %$d1O m3+Bp3cmM6R'6h[ZN)"-͘frE쿆dL׸]YdhXvlUi$Ir&$h+_{Q1ߗ/'z7#re&Y /9Cd՚i~>{I8R$+&)q["id+mv;wbfr/⮹o䩍Q[*H&>I5I46_&USV[1I.L3K32N# .K|_d9;7#ctC&+go8IrFM3O߶4IS$](cۥD*uCHcTzx1MŘq Dpv5CIkII%E.l*E%ӿET;P"`eYeLqIG (ԈN b9$!!E~*1K2,DEQ*ĭ. DH|1Z(n$. oj4U&!};"H.fd&Чĉv7ծ%f(lkۘe>xculhl;eȟE4U$$푔sXؤ3w,OqB}T2VAНkY}-qe.!1A 0@"Qa2qB`?/]t]Wˮ?BܢzuAki4cu(N<ů}&GҒV*f,0!T̺X^C2N&Dzf~E=:G,S^`'?GE_َ8!bNŋ&Bm3Iw J䢶\ظcV%\L8B+bٶ(ƙ4woTD™DIu fPkɑMJbssH?_<ۤ(\YTݛ4d[vgIQ(+Ȯ3ѶfMS"+ɨJӦ&(P^3$N.<ˍSIQM5(Y3!E$g$Þm5XۊLMB䵑7iXбKO.In5˟V0($N)Rg&فܘFpBB4&IE;f=JY\j%wG,{Yo|mne:~? ry)O~_ũS[#ZbR_NϨmTO>+{4Mdェ"5X$k7.j1'%&iwCg㒓I0cPH&3ɸ$g',춣IA\#_}dO s|1_䋔/rEɪ)tQgcYOerU3zQTn(l줇}-*chKI1N- TH7BchB4>~ 0% B^mFE;ks$Vihnk)ǃ$j_ Zt'RC*$bHKCϑE"eh͌QE&E=hؕ&}&abl\rEwS"ѵy2I#O{茈MQvq!=d[bo5፶)}¤be2FXֆ"$2iGr>$ll:̑4QB+BE 9]^l[-L䡶įc[c$| DXB}DN}r->#rY.˲'u 2|(_g1ǢD5H=+G&D^,نJ6$Nt(,/8ք4!2D$鮫ً11Hd" 1FR&},WZ"s@-4%f;bآ,Lwća \ 6KJD#d"!fI;V*]eTc"o#ɋUC6ke"Rf6)Q6쮮H/݃c1Y6FԷe)tSHse[Fr Ǖ_'֌$2y7[ԓJIcLWTN/[+z!>fOk%4ENǝv7~WE\בLW^WJQEzpkgdown/tests/testthat/assets/articles-images/DESCRIPTION0000644000176200001440000000051214633374223023013 0ustar liggesusersPackage: kittens Version: 1.0.0 Title: A test package Description: A longer statement about the package. Authors@R: c( person("Hadley", "Wickham", , "hadley@rstudio.com", role = c("aut", "cre")), person("RStudio", role = c("cph", "fnd")) ) RoxygenNote: 6.0.1 Suggests: knitr, rmarkdown VignetteBuilder: knitr pkgdown/tests/testthat/assets/templates-local/0000755000176200001440000000000014633374223021324 5ustar liggesuserspkgdown/tests/testthat/assets/templates-local/pkgdown/0000755000176200001440000000000014633374223022775 5ustar liggesuserspkgdown/tests/testthat/assets/templates-local/pkgdown/templates/0000755000176200001440000000000014633374223024773 5ustar liggesuserspkgdown/tests/testthat/assets/templates-local/pkgdown/templates/footer-article.html0000644000176200001440000000002714633374223030577 0ustar liggesusersCONTENT ARTICLE FOOTER pkgdown/tests/testthat/assets/templates-local/pkgdown/templates/content-article.html0000644000176200001440000000002514633374223030751 0ustar liggesusersCONTENT ARTICLE BODY pkgdown/tests/testthat/assets/templates-local/DESCRIPTION0000644000176200001440000000042314633374223023031 0ustar liggesusersPackage: testpackage Version: 1.0.0 Title: A test package Description: A longer statement about the package. Authors@R: c( person("Hadley", "Wickham", , "hadley@rstudio.com", role = c("aut", "cre")), person("RStudio", role = c("cph", "fnd")) ) RoxygenNote: 6.0.1 pkgdown/tests/testthat/assets/sitemaps-schema-0.9.xsd0000644000176200001440000000771014634573316022357 0ustar liggesusers XML Schema for Sitemap files. Last Modified 2008-03-26 Container for a set of up to 50,000 document elements. This is the root element of the XML file. Container for the data needed to describe a document to crawl. REQUIRED: The location URI of a document. The URI must conform to RFC 2396 (http://www.ietf.org/rfc/rfc2396.txt). OPTIONAL: The date the document was last modified. The date must conform to the W3C DATETIME format (http://www.w3.org/TR/NOTE-datetime). Example: 2005-05-10 Lastmod may also contain a timestamp. Example: 2005-05-10T17:33:30+08:00 OPTIONAL: Indicates how frequently the content at a particular URL is likely to change. The value "always" should be used to describe documents that change each time they are accessed. The value "never" should be used to describe archived URLs. Please note that web crawlers may not necessarily crawl pages marked "always" more often. Consider this element as a friendly suggestion and not a command. OPTIONAL: The priority of a particular URL relative to other pages on the same site. The value for this element is a number between 0.0 and 1.0 where 0.0 identifies the lowest priority page(s). The default priority of a page is 0.5. Priority is used to select between pages on your site. Setting a priority of 1.0 for all URLs will not help you, as the relative priority of pages on your site is what will be considered. pkgdown/tests/testthat/test-external-deps.R0000644000176200001440000000070514633374223020611 0ustar liggesuserstest_that("check integrity validates integrity", { temp <- withr::local_tempfile(lines = letters) expect_snapshot(error = TRUE, { check_integrity(temp, "sha123-abc") check_integrity(temp, "sha256-abc") }) integrity <- paste0("sha256-", compute_hash(temp, 256L)) expect_no_error(check_integrity(temp, integrity)) }) test_that("can parse integrity", { expect_equal(parse_integrity("sha256-abc"), list(size = 256L, hash = "abc")) }) pkgdown/tests/testthat/test-build-favicons.R0000644000176200001440000000077314770274305020752 0ustar liggesuserstest_that("missing logo generates message", { pkg <- local_pkgdown_site() expect_snapshot( error = TRUE, expect_output(build_favicons(pkg), "Building favicons") ) }) test_that("existing logo generates message", { pkg <- local_pkgdown_site() dir_create(path(pkg$src_path, "pkgdown", "favicon")) file_create(path(pkg$src_path, "pkgdown", "favicon", "favicon.ico")) file_create(path(pkg$src_path, "logo.png")) expect_true(has_favicons(pkg)) expect_snapshot(build_favicons(pkg)) }) pkgdown/tests/testthat/test-build-home-community.R0000644000176200001440000000114414634573316022110 0ustar liggesuserstest_that("handles CoC and SUPPORT if present", { pkg <- local_pkgdown_site() pkg <- pkg_add_file(pkg, ".github/SUPPORT.md") pkg <- pkg_add_file(pkg, ".github/CODE_OF_CONDUCT.md") expect_true(has_coc(pkg$src_path)) expect_true(has_support(pkg$src_path)) # And added to sidebar text <- data_home_sidebar_community(pkg) expect_snapshot_output(cat(text)) }) test_that("empty site doesn't have community asserts", { pkg <- local_pkgdown_site() expect_false(has_contributing(pkg$src_path)) expect_false(has_coc(pkg$src_path)) expect_equal(data_home_sidebar_community(pkg$src_path), "") }) pkgdown/tests/testthat/test-html-build.R0000644000176200001440000000234214131662734020076 0ustar liggesuserstest_that("Stripping HTML tags", { expect_identical( strip_html_tags("

    some text about data"), "some text about data" ) }) # links and references in the package description ------------------------- test_that("references in angle brackets are converted to HTML", { ## URL expect_identical( linkify("see ."), "see <https://CRAN.R-project.org/view=SpatioTemporal>." ) ## DOI expect_identical( linkify("M & H (2017) "), "M & H (2017) <doi:10.1093/biostatistics/kxw051>" ) ## arXiv expect_identical( linkify("see ."), "see <arXiv:1802.03967>." ) ## unsupported formats are left alone (just escaping special characters) unsupported <- c( "3.0.CO;2-P>", "" ) expect_identical(linkify(unsupported), escape_html(unsupported)) }) pkgdown/tests/testthat/test-tweak-tabset.R0000644000176200001440000000401214770274305020426 0ustar liggesuserstest_that("sections with class .tabset are converted to tabsets", { skip_on_os("windows") # some line ending problem pkg <- local_pkgdown_site() html <- markdown_to_html( pkg, " # Tabset {.tabset .tabset-pills} ## Tab 1 Contents 1 ## Tab 2 Contents 2 " ) tweak_tabsets(html) # strip class for older pandoc compat on GHA headings <- xml2::xml_find_all(html, ".//h1") xml2::xml_set_attr(headings, "class", NULL) expect_snapshot_output(xpath_xml(html, ".//body/div")) }) test_that("can adjust active tab", { skip_on_os("windows") # some line ending problem pkg <- local_pkgdown_site() html <- markdown_to_html( pkg, " ## Tabset {.tabset .tabset-pills} ### Tab 1 Contents 1 ### Tab 2 {.active} Contents 2 " ) tweak_tabsets(html) expect_equal( xpath_attr(html, "//div/div/div", "class"), c("tab-pane", "active tab-pane") ) }) test_that("can fade", { pkg <- local_pkgdown_site() html <- markdown_to_html( pkg, " ## Tabset {.tabset .tabset-fade} ### Tab 1 Contents 1 ### Tab 2 {.active} Contents 2 " ) tweak_tabsets(html) expect_equal( xpath_attr(html, "//div/div/div", "class"), c("fade tab-pane", "show active fade tab-pane") ) }) test_that("can accept html", { pkg <- local_pkgdown_site() html <- markdown_to_html( pkg, " ## Tabset {.tabset} ### Tab 1 `with_code` {#toc-1} Contents 1 ### Tab 2 {#toc-2} Contents 2 ### Normal Tab {#toc-normal} Contents of normal tab " ) tweak_tabsets(html) expect_match( as.character(xpath_xml(html, ".//*[@id = 'toc-1-tab']")), "Tab 1 with_code", fixed = TRUE ) expect_match( as.character(xpath_xml(html, ".//*[@id = 'toc-2-tab']")), " Tab 2", fixed = TRUE ) expect_match( as.character(xpath_xml(html, ".//*[@id = 'toc-normal-tab']")), ">Normal Tab", fixed = TRUE ) }) pkgdown/tests/testthat/test-build-redirects.R0000644000176200001440000000524114633374223021117 0ustar liggesuserstest_that("build_redirect() works", { pkg <- list( src_path = withr::local_tempdir(), dst_path = withr::local_tempdir(), meta = list(url = "https://example.com"), prefix = "", bs_version = 5 ) pkg <- structure(pkg, class = "pkgdown") expect_snapshot( build_redirect(c("old.html", "new.html#section"), 1, pkg = pkg) ) html <- xml2::read_html(path(pkg$dst_path, "old.html")) expect_equal( xpath_attr(html, "//link", "href"), "https://example.com/new.html#section" ) }) test_that("build_redirect() errors if one entry is not right.", { data_redirects_ <- function(...) { pkg <- local_pkgdown_site(meta = list(...)) data_redirects(pkg) } expect_snapshot(error = TRUE, { data_redirects_(redirects = "old.html") data_redirects_(redirects = list("old.html")) }) }) test_that("article_redirects() creates redirects for vignettes in vignettes/articles", { dir <- withr::local_tempdir() dir_create(path(dir, "vignettes", "articles")) file_create(path(dir, "vignettes", "articles", "test.Rmd")) pkg <- list( meta = list(url = "http://foo.com"), vignettes = package_vignettes(dir) ) expect_equal( article_redirects(pkg), list(c("articles/articles/test.html", "articles/test.html")) ) }) # reference_redirects ---------------------------------------------------------- test_that("generates redirects only for non-name aliases", { pkg <- list( meta = list(url = "http://foo.com"), topics = list( alias = list("foo", c("bar", "baz")), name = c("foo", "bar"), file_out = c("foo.html", "bar.html") ) ) expect_equal( reference_redirects(pkg), list(c("reference/baz.html", "reference/bar.html")) ) }) test_that("doesn't generates redirect for aliases that can't be file names", { pkg <- list( meta = list(url = "http://foo.com"), topics = list( name = "bar", alias = list(c("bar", "baz", "[<-.baz")), file_out = "bar.html" ) ) expect_equal( reference_redirects(pkg), list(c("reference/baz.html", "reference/bar.html")) ) }) test_that("never redirects away from existing topic", { pkg <- list( meta = list(url = "http://foo.com"), topics = list( alias = list("foo", c("bar", "foo")), name = c("foo", "bar"), file_out = c("foo.html", "bar.html") ) ) expect_equal( reference_redirects(pkg), list() ) }) test_that("no redirects if no aliases", { pkg <- list( meta = list(url = "http://foo.com"), topics = list( alias = list(c("foo", "bar")), name = c("foo", "bar"), file_out = c("foo.html", "bar.html") ) ) expect_equal(reference_redirects(pkg), list()) }) pkgdown/tests/testthat/helper.R0000644000176200001440000000666315074163153016347 0ustar liggesusersskip_if_no_pandoc <- function(version = "1.12.3") { skip_if_not(rmarkdown::pandoc_available(version), "pandoc not available") } skip_if_no_quarto <- function() { skip_on_os("windows") # quarto set up currently broken? skip_if(is.null(quarto::quarto_path()), "quarto not available") skip_if_not(quarto::quarto_version() >= "1.5", "quarto 1.5 not available") } # Simulate a package -------------------------------------------------------- local_pkgdown_site <- function( path = NULL, meta = list(), desc = list(), env = caller_env() ) { check_string(path, allow_null = TRUE) dst_path <- path_real( withr::local_tempdir(.local_envir = env, pattern = "pkgdown-dst") ) # Simulate init_site() so we only have to run it if we care about file_create(path(dst_path, "pkgdown.yml")) dir_create(path(dst_path, "deps")) file_create(path(dst_path, "deps", "data-deps.txt")) meta <- modify_list(meta, list(destination = dst_path)) if (is.null(path)) { path <- path_real( withr::local_tempdir(.local_envir = env, pattern = "pkgdown-src") ) description <- desc::desc("!new") description$set("Package", "testpackage") description$set("Title", "A test package") if (length(desc) > 0) { inject(description$set(!!!desc)) } description$write(file = path(path, "DESCRIPTION")) # Default to BS5 only if template not specified meta$template <- meta$template %||% list(bootstrap = 5) # Record meta in case we re-run as_pkgdown() yaml::write_yaml(meta, path(path, "_pkgdown.yml")) # Make it a bit easier to create other files dir_create(path(path, "R")) dir_create(path(path, "vignettes")) } as_pkgdown(path, meta) } pkg_add_file <- function(pkg, path, lines = NULL) { full_path <- path(pkg$src_path, path) dir_create(path_dir(full_path)) if (is.null(lines)) { file_create(full_path) } else { write_lines(lines, full_path) } if (path_has_parent(path, "vignettes")) { pkg <- as_pkgdown(pkg$src_path) } pkg } pkg_add_kitten <- function(pkg, path) { full_path <- path(pkg$src_path, path) dir_create(full_path) file_copy(test_path("assets/kitten.jpg"), full_path) pkg } pkg_vignette <- function(..., title = "title") { dots <- list2(title = title, ...) meta <- dots[have_name(dots)] contents <- unlist(dots[!have_name(dots)]) meta$vignette <- paste0("\n", " %\\VignetteIndexEntry{", title, "}") yaml <- yaml::as.yaml( meta, handlers = list(logical = yaml::verbatim_logical) ) c("---", yaml, "---", contents) } r_code_block <- function(...) c("```{r}", ..., "```") # Simulate a template package ------------------------------------------------ local_pkgdown_template_pkg <- function( path = NULL, meta = NULL, env = parent.frame() ) { if (is.null(path)) { path <- withr::local_tempdir(.local_envir = env) desc <- desc::desc("!new") desc$set("Package", "templatepackage") desc$set("Title", "A test template package") desc$write(file = path(path, "DESCRIPTION")) } if (!is.null(meta)) { path_pkgdown_yml <- path(path, "inst", "pkgdown", "_pkgdown.yml") dir_create(path_dir(path_pkgdown_yml)) yaml::write_yaml(meta, path_pkgdown_yml) } pkgload::load_all(path, quiet = TRUE) withr::defer(pkgload::unload("templatepackage"), envir = env) path } in_rcmd_check <- function() { !is.na(Sys.getenv("_R_CHECK_PACKAGE_NAME_", NA)) || tolower(Sys.getenv("_R_CHECK_LICENSE_")) == "true" } pkgdown/tests/testthat/test-build-llm.R0000644000176200001440000000362115100735002017701 0ustar liggesuserstest_that("integration test for convert_md()", { skip_if_no_pandoc() path <- withr::local_tempfile(pattern = "pkgdown-llm") convert_md(test_path("assets", "llm.html"), path) expect_snapshot(write_lines(read_lines(path), stdout())) }) test_that("simplifies page header", { html <- xml2::read_html( r"(

    )" ) simplify_page_header(xml2::xml_find_first(html, ".//main")) expect_equal(xpath_contents(html, ".//main"), "

    Package index

    ") }) test_that("replaces lifecycle badges with strong text", { html <- xml2::read_html( r"( deprecated [Experimental] )" ) simplify_lifecycle_badges(html) expect_equal( xpath_text(html, ".//strong"), c("[deprecated]", "[experimental]") ) }) test_that("converts internal urls to absolute with .md ending", { html <- xml2::read_html( r"( link link link )" ) create_absolute_links(html, "https://pkgdown.r-lib.org") expect_equal( xpath_attr(html, ".//a", "href"), c( "https://pkgdown.r-lib.org/llm.md", "#fragment", "https://example.org" ) ) }) test_that("adjusts extension even without url", { html <- xml2::read_html(r"(link)") create_absolute_links(html) expect_equal(xpath_attr(html, ".//a", "href"), "llm.md") }) test_that("strip extra classes from pre", { html <- xml2::read_html(r"(
    1+1
    )") simplify_code(html) expect_equal(xpath_attr(html, ".//pre", "class"), "r") }) pkgdown/tests/testthat/test-tweak-reference.R0000644000176200001440000001063515074502660021106 0ustar liggesuserstest_that("highlights
     wrapped in 
    with language info", { skip_if_no_pandoc("2.16") withr::local_options(downlit.topic_index = c(foo = "foo")) html <- xml2::read_html( '
    foo(x)
    ' ) tweak_reference_highlighting(html) expect_equal(xpath_attr(html, ".//code//a", "href"), "foo.html") # Or upper case R html <- xml2::read_html( '
    foo(x)
    ' ) tweak_reference_highlighting(html) expect_equal(xpath_attr(html, ".//code//a", "href"), "foo.html") html <- xml2::read_html( '
    field: value
    ' ) tweak_reference_highlighting(html) # Select all leaf to work around variations in pandoc styling expect_equal(xpath_attr(html, "//code//span[not(span)]", "class")[[1]], "fu") expect_equal(xpath_text(html, "//code//span[not(span)]")[[1]], "field") # But don't touch examples or usage html <- xml2::read_html( '
    foo(x)
    ' ) tweak_reference_highlighting(html) expect_equal(xpath_length(html, "//code//span"), 0) html <- xml2::read_html( '
    foo(x)
    ' ) tweak_reference_highlighting(html) expect_equal(xpath_length(html, "//code//span"), 0) }) test_that("highlight unwrapped
    ", {
      withr::local_options(downlit.topic_index = c(foo = "foo"))
    
      # If parseable, assume R
      html <- xml2::read_html(
        '
        
    foo(x)
    ' ) tweak_reference_highlighting(html) expect_equal(xpath_attr(html, ".//code//a", "href"), "foo.html") expect_equal(xpath_attr(html, ".//div/div", "class"), "sourceCode") # If not parseable, leave as is html <- xml2::read_html( '
    foo(
    ' ) tweak_reference_highlighting(html) expect_equal(xpath_length(html, "//code//span"), 0) expect_equal(xpath_attr(html, ".//div/div", "class"), "sourceCode") }) # highlighting ------------------------------------------------------------ test_that("can highlight R code", { html <- xml2::read_xml('
    1 + 2
    ') tweak_highlight_r(html) expect_equal( xpath_attr(html, "//code//span[@class]", "class"), c("fl", "op", "fl") ) expect_equal(xpath_text(html, "//code//span[@class]"), c("1", "+", "2")) }) test_that("fails cleanly", { html <- xml2::read_xml('
    1 + 
    ') expect_equal(tweak_highlight_r(html), FALSE) html <- xml2::read_xml('
    ') expect_equal(tweak_highlight_r(html), FALSE) html <- xml2::read_xml('
    ') expect_equal(tweak_highlight_r(html), FALSE) }) test_that("can highlight other languages", { skip_if_no_pandoc("2.16") html <- xml2::read_xml( '
    field: value
    ' ) tweak_highlight_other(html) # Select all leaf to work around variations in pandoc styling expect_equal(xpath_attr(html, "//code//span[not(span)]", "class")[[1]], "fu") expect_equal(xpath_text(html, "//code//span[not(span)]")[[1]], "field") }) test_that("can highlight 'rmd'", { skip_if_no_pandoc("2.16") html <- xml2::read_xml( '
    field: value
    ' ) tweak_highlight_other(html) expect_equal(xpath_attr(html, "//code//span[not(span)]", "class")[[1]], "an") }) test_that("fails cleanly", { html <- xml2::read_xml('
    ') tweak_highlight_other(html) expect_equal(xpath_text(html, "//code"), "") html <- xml2::read_xml('
    ') expect_equal(tweak_highlight_other(html), FALSE) }) # logo -------------------------------------------------------------------- test_that("can strip extra logo from description", { html <- xml2::read_html( '

    Hi

    Bye

    ' ) tweak_extra_logo(html) expect_equal(xpath_length(html, "//img"), 0) }) pkgdown/tests/testthat/test-build-home-md.R0000644000176200001440000000145514770274305020466 0ustar liggesuserstest_that("can find files in root and .github", { dir <- withr::local_tempdir() dir_create(path(dir, ".github")) file_create(path(dir, "a.md")) file_create(path(dir, ".github", "b.md")) mds <- withr::with_dir(dir, package_mds(".")) expect_equal(mds, c("a.md", "./.github/b.md")) }) test_that("drops files handled elsewhere", { dir <- withr::local_tempdir() dir_create(path(dir, ".github")) file_create(path(dir, c("README.md", "LICENSE.md", "NEWS.md"))) expect_equal(withr::with_dir(dir, package_mds(".")), character()) }) test_that("drops files that don't need to be rendered", { dir <- withr::local_tempdir() dir_create(path(dir, ".github")) file_create(path(dir, c("cran-comments.md", "issue_template.md"))) expect_equal(withr::with_dir(dir, package_mds(".")), character()) }) pkgdown/tests/testthat/test-render.R0000644000176200001440000000303714770274305017320 0ustar liggesuserstest_that("capture data_template()", { pkg <- local_pkgdown_site() data <- data_template(pkg) data$year <- "" data$footer$right <- gsub( packageVersion("pkgdown"), "{version}", data$footer$right, fixed = TRUE ) expect_snapshot_output(data) }) test_that("can include text in header, before body, and after body", { pkg <- local_pkgdown_site( meta = list( template = list( includes = list( in_header = "in header", before_body = "before body", after_body = "after body" ) ) ) ) expect_named( data_template(pkg)$includes, c("in_header", "before_body", "after_body") ) pkg$bs_version <- 3 html <- render_page_html(pkg, "title-body") expect_equal( xpath_text(html, ".//test"), c("in header", "before body", "after body") ) pkg$bs_version <- 5 suppressMessages(init_site(pkg)) html <- render_page_html(pkg, "title-body") expect_equal( xpath_text(html, ".//test"), c("in header", "before body", "after body") ) }) test_that("check_opengraph validates inputs", { data_open_graph_ <- function(x) { pkg <- local_pkgdown_site(meta = list(template = list(opengraph = x))) data_open_graph(pkg) invisible() } expect_snapshot(error = TRUE, { data_open_graph_(list(foo = list())) data_open_graph_(list(foo = list(), bar = list())) data_open_graph_(list(twitter = 1)) data_open_graph_(list(twitter = list())) data_open_graph_(list(image = 1)) }) }) pkgdown/tests/testthat/test-package.R0000644000176200001440000001076615074163153017437 0ustar liggesuserstest_that("is_pkgdown checks its inputs", { expect_snapshot(error = TRUE, { as_pkgdown(1) as_pkgdown(override = 1) }) }) test_that("package_vignettes() doesn't trip over directories", { dir <- withr::local_tempdir() dir_create(path(dir, "vignettes", "test.Rmd")) file_create(path(dir, "vignettes", "test2.Rmd")) expect_equal( as.character(package_vignettes(dir)$file_in), "vignettes/test2.Rmd" ) }) test_that("check_bootstrap_version() allows 3, 4 (with warning), and 5", { pkg <- local_pkgdown_site() expect_equal(check_bootstrap_version(3, pkg), 3) expect_snapshot(expect_equal(check_bootstrap_version(4, pkg), 5)) expect_equal(check_bootstrap_version(5, pkg), 5) }) test_that("check_bootstrap_version() gives informative error otherwise", { pkg <- local_pkgdown_site() expect_snapshot(check_bootstrap_version(1, pkg), error = TRUE) }) test_that("package_vignettes() moves vignettes/articles up one level", { dir <- withr::local_tempdir() dir_create(path(dir, "vignettes", "articles")) file_create(path(dir, "vignettes", "articles", "test.Rmd")) pkg_vig <- package_vignettes(dir) expect_equal(as.character(pkg_vig$file_out), "articles/test.html") expect_equal(pkg_vig$depth, 1L) }) test_that("package_vignettes() detects conflicts in final article paths", { dir <- withr::local_tempdir() dir_create(path(dir, "vignettes", "articles")) file_create(path(dir, "vignettes", "test.Rmd")) file_create(path(dir, "vignettes", "articles", "test.Rmd")) expect_snapshot(package_vignettes(dir), error = TRUE) }) test_that("package_vignettes() sorts articles alphabetically by file name", { pkg <- local_pkgdown_site() pkg <- pkg_add_file(pkg, "vignettes/a.Rmd") pkg <- pkg_add_file(pkg, "vignettes/b.Rmd") pkg <- pkg_add_file(pkg, "vignettes/c.Rmd") expect_equal( path_file(pkg$vignettes$file_out), c("a.html", "b.html", "c.html") ) }) test_that("override works correctly for as_pkgdown", { pkg1 <- local_pkgdown_site(meta = list(figures = list(dev = "jpeg"))) pkg2 <- as_pkgdown(pkg1, override = list(figures = list(dev = "png"))) expect_equal(pkg2$meta$figures$dev, "png") }) # titles ------------------------------------------------------------------ test_that("multiline titles are collapsed", { rd <- rd_text( "\\title{ x }", fragment = FALSE ) expect_equal(extract_title(rd), "x") }) test_that("titles can contain other markup", { rd <- rd_text("\\title{\\strong{x}}", fragment = FALSE) expect_equal(extract_title(rd), "x") }) test_that("titles don't get autolinked code", { rd <- rd_text("\\title{\\code{foo()}}", fragment = FALSE) expect_equal(extract_title(rd), "foo()") }) test_that("read_meta() errors gracefully if _pkgdown.yml failed to parse", { pkg <- local_pkgdown_site() pkg <- pkg_add_file( pkg, "_pkgdown.yml", c( "url: https://pkgdown.r-lib.org", " title: Build websites for R packages" ) ) expect_snapshot( as_pkgdown(pkg$src_path), error = TRUE, transform = function(x) gsub(pkg$src_path, "", x, fixed = TRUE) ) }) # lifecycle --------------------------------------------------------------- test_that("can extract lifecycle badges from description", { rd_desc <- rd_text( paste0("\\description{", lifecycle::badge("deprecated"), "}"), fragment = FALSE ) rd_param <- rd_text( paste0("\\arguments{\\item{pkg}{", lifecycle::badge("deprecated"), "}}"), fragment = FALSE ) expect_equal(extract_lifecycle(rd_desc), "deprecated") expect_equal(extract_lifecycle(rd_param), NULL) }) test_that("malformed figures fail gracefully", { rd_lifecycle <- function(x) extract_lifecycle(rd_text(x)) expect_null(rd_lifecycle("{\\figure{deprecated.svg}}")) expect_null(rd_lifecycle("{\\figure{}}")) }) # language --------------------------------------------------------------------- test_that("as_pkgdown sets language", { # Default pkg <- as_pkgdown(test_path("assets/reference")) expect_equal( pkg$lang, "en" ) # Single language specified in DESCRIPTION pkg <- as_pkgdown(test_path("assets/reference-language/one")) expect_equal( pkg$lang, "fr" ) # Two languages specified in DESCRIPTION pkg <- as_pkgdown(test_path("assets/reference-language/two")) expect_equal( pkg$lang, "en-US" ) # Language specified in _pkgdown.yml or override. pkg <- as_pkgdown( test_path("assets/reference-language/two"), override = list(lang = "en-GB") ) expect_equal( pkg$lang, "en-GB" ) }) pkgdown/tests/testthat/test-rd-data.R0000644000176200001440000000452414770274305017357 0ustar liggesusers# Value blocks ------------------------------------------------------------ test_that("leading text parsed as paragraph", { # fmt: skip expected <- c( "

    text

    ", "
    ", "
    x
    ", "

    y

    ", "
    " ) expect_equal(value2html("\ntext\n\\item{x}{y}"), expected) expect_equal(value2html("text\\item{x}{y}"), expected) }) test_that("leading text is optional", { expect_equal( value2html("\\item{x}{y}"), c("
    ", "
    x
    ", "

    y

    ", "
    ") ) }) test_that("can process empty string", { expect_equal(value2html(""), character()) }) test_that("leading text is optional", { expect_equal(value2html("text"), "

    text

    ") }) test_that("items are optional", { value <- rd_text("\\value{text}", fragment = FALSE) expect_equal(as_data(value[[1]])$contents, "

    text

    ") }) test_that("whitespace between items doesn't affect grouping", { expect_equal( value2html("\\item{a}{b}\n\n\\item{c}{d}\n\n\\item{e}{f}"), # fmt: skip c( "
    ", "
    a
    ", "

    b

    ", "", "", "
    c
    ", "

    d

    ", "", "", "
    e
    ", "

    f

    ", "
    " ) ) }) test_that("leading whitespace doesn't break items", { expect_equal( value2html("\n\\item{a}{b}\n\n\\item{c}{d}\n\n\\item{e}{f}"), # fmt: skip c( "
    ", "
    a
    ", "

    b

    ", "", "", "
    c
    ", "

    d

    ", "", "", "
    e
    ", "

    f

    ", "
    " ) ) }) test_that("whitespace between text is not preserved", { expect_equal( value2html("a\n\nb\n\nc"), c("

    a

    ", "

    b

    ", "

    c

    ") ) }) test_that("can have multiple interleaved blocks", { expect_equal( value2html("text1\\item{a}{b}\\item{c}{d}text2\\item{e}{f}"), # fmt: skip c( "

    text1

    ", "
    ", "
    a
    ", "

    b

    ", "
    c
    ", "

    d

    ", "
    ", "

    text2

    ", "
    ", "
    e
    ", "

    f

    ", "
    " ) ) }) test_that("other tags don't affect breaking (#2371)", { expect_equal( value2html("1\\code{xxx}\n2\n3"), c("

    1xxx", "2", "3

    ") ) # additionally teading whitespace expect_equal( value2html("1\\code{xxx}\n 2\n 3"), c("

    1xxx", "2", "3

    ") ) }) pkgdown/tests/testthat/test-build-home-index.R0000644000176200001440000001302114770274305021165 0ustar liggesuserstest_that("messages about reading and writing", { pkg <- local_pkgdown_site() expect_snapshot({ build_home_index(pkg) build_home_index(pkg) }) }) test_that("title and description come from DESCRIPTION by default", { pkg <- local_pkgdown_site( desc = list( Title = "A test title", Description = "A test description." ) ) expect_equal(data_home(pkg)$pagetitle, "A test title") expect_equal(data_home(pkg)$opengraph$description, "A test description.") # but overridden by home pkg$meta <- list(home = list(title = "X", description = "Y")) expect_equal(data_home(pkg)$pagetitle, "X") expect_equal(data_home(pkg)$opengraph$description, "Y") }) test_that("math is handled", { pkg <- local_pkgdown_site() pkg <- pkg_add_file(pkg, "README.md", "$1 + 1$") suppressMessages(build_home_index(pkg)) html <- xml2::read_html(path(pkg$dst_path, "index.html")) expect_equal(xpath_length(html, ".//math"), 1) }) test_that("data_home() validates yaml metadata", { data_home_ <- function(...) { pkg <- local_pkgdown_site(meta = list(...)) data_home(pkg) } expect_snapshot(error = TRUE, { data_home_(home = 1) data_home_(home = list(title = 1)) data_home_(home = list(description = 1)) data_home_(template = list(trailing_slash_redirect = 1)) }) }) test_that("version formatting in preserved", { pkg <- local_pkgdown_site(desc = list(Version = "1.0.0-9000")) expect_equal(pkg$version, "1.0.0-9000") suppressMessages(build_home_index(pkg)) index <- read_lines(path(pkg$dst_path, "index.html")) expect_match(index, "1.0.0-9000", fixed = TRUE, all = FALSE) }) test_that("data_home_sidebar() works by default", { pkg <- local_pkgdown_site() expect_snapshot(cat(data_home_sidebar(pkg))) # comments are not included pkg <- local_pkgdown_site( desc = list( `Authors@R` = 'c( person("Hadley", "Wickham", , "hadley@rstudio.com", role = c("aut", "cre")), person("RStudio", role = c("cph", "fnd"), comment = c("Thank you!")) )' ) ) html <- xml2::read_html(data_home_sidebar(pkg)) expect_snapshot_output(xpath_xml(html, ".//div[@class='developers']")) }) test_that("data_home_sidebar() can be removed", { pkg <- local_pkgdown_site(meta = list(home = list(sidebar = FALSE))) # not built by data_home_sidebar() expect_false(data_home_sidebar(pkg)) # nor later -- so probably not to be tested here?! suppressMessages(build_home_index(pkg)) html <- xml2::read_html(path(pkg$dst_path, "index.html")) expect_equal(xpath_length(html, ".//aside/*"), 0) }) test_that("data_home_sidebar() can be defined by a HTML file", { pkg <- local_pkgdown_site( meta = list(home = list(sidebar = list(html = "sidebar.html"))) ) expect_snapshot(data_home_sidebar(pkg), error = TRUE) pkg <- pkg_add_file(pkg, "sidebar.html", "Hello, world!") expect_equal(data_home_sidebar(pkg), "Hello, world!\n") }) test_that("data_home_sidebar() can get a custom markdown formatted component", { pkg <- local_pkgdown_site( meta = list( home = list( sidebar = list( structure = "fancy", components = list( fancy = list( title = "Fancy section", text = "How *cool* is pkgdown?!" ) ) ) ) ) ) html <- xml2::read_html(data_home_sidebar(pkg)) expect_snapshot_output(xpath_xml(html, ".//div[@class='fancy-section']")) }) test_that("data_home_sidebar() can add a TOC", { pkg <- local_pkgdown_site( meta = list( home = list(sidebar = list(structure = "toc")) ) ) html <- xml2::read_html(data_home_sidebar(pkg)) expect_snapshot_output(xpath_xml(html, ".//div[@class='table-of-contents']")) }) test_that("data_home_sidebar() outputs informative error messages", { data_home_sidebar_ <- function(...) { pkg <- local_pkgdown_site(meta = list(home = list(sidebar = list(...)))) data_home_sidebar(pkg) } expect_snapshot(error = TRUE, { data_home_sidebar_(html = 1) data_home_sidebar_(structure = 1) data_home_sidebar_(structure = "fancy") data_home_sidebar_(structure = c("fancy", "cool")) data_home_sidebar_( structure = "fancy", components = list(fancy = list(text = "bla")) ) data_home_sidebar_(structure = "fancy", components = list(fancy = list())) }) }) test_that("package repo verification", { skip_on_cran() # requires internet connection expect_null(cran_link("notarealpkg")) expect_equal( cran_link("dplyr"), list(repo = "CRAN", url = "https://cloud.r-project.org/package=dplyr") ) expect_equal( cran_link("Biobase"), list( repo = "Bioconductor", url = "https://www.bioconductor.org/packages/Biobase" ) ) }) test_that("cran_unquote works", { expect_equal( cran_unquote("'Quoting' is CRAN's thing."), "Quoting is CRAN's thing." ) }) test_that("allow email in BugReports", { # currently desc throws a warning if BugReports is an email pkg <- suppressWarnings(local_pkgdown_site( desc = list(BugReports = "me@tidyverse.com") )) html <- xml2::read_html(data_home_sidebar(pkg)) expect_snapshot(xpath_xml(html, ".//li/a")) }) test_that("ANSI are handled", { withr::local_options(cli.num_colors = 256) pkg <- local_pkgdown_site() pkg <- pkg_add_file(pkg, "index.md", sprintf("prefer %s", cli::col_blue("a"))) suppressMessages(build_home_index(pkg)) html <- xml2::read_html(path(pkg$dst_path, "index.html")) readme_p <- xml2::xml_find_first(html, ".//main[@id='main']/p") expect_equal(xml2::xml_text(readme_p), "prefer \u2029[34ma\u2029[39m") }) pkgdown/tests/testthat/test-figure.R0000644000176200001440000000125414770274305017321 0ustar liggesuserstest_that("can override defaults in _pkgdown.yml", { skip_if_no_pandoc() skip_if_no_quarto() withr::local_temp_libpaths() pkg <- local_pkgdown_site(test_path("assets/figure")) suppressMessages(init_site(pkg)) callr::rcmd("INSTALL", pkg$src_path, show = FALSE, fail_on_status = TRUE) suppressMessages(build_reference(pkg, devel = FALSE)) img <- path_file(dir_ls(path(pkg$dst_path, "reference"), glob = "*.jpg")) expect_setequal(img, c("figure-1.jpg", "figure-2.jpg")) suppressMessages(build_articles(pkg)) img <- path_file(dir_ls( path(pkg$dst_path, "articles"), glob = "*.jpg", recurse = TRUE )) expect_equal(img, "unnamed-chunk-1-1.jpg") }) pkgdown/tests/testthat/test-build-home-authors.R0000644000176200001440000001774115074163153021554 0ustar liggesuserstest_that("authors page includes inst/AUTHORS", { pkg <- local_pkgdown_site() pkg <- pkg_add_file(pkg, "inst/AUTHORS", "Hello") suppressMessages(build_citation_authors(pkg)) lines <- read_lines(path(pkg$dst_path, "authors.html")) expect_match(lines, "
    Hello
    ", all = FALSE) }) test_that("authors page includes multiline inst/AUTHORS", { pkg <- local_pkgdown_site() pkg <- pkg_add_file(pkg, "inst/AUTHORS", c("Hello", "------", "bla bla")) suppressMessages(build_citation_authors(pkg)) lines <- read_lines(path(pkg$dst_path, "authors.html")) content <- paste(lines, collapse = " ") expect_match(content, "
    Hello ------ bla bla
    ") }) test_that("data_authors validates yaml inputs", { data_authors_ <- function(...) { pkg <- local_pkgdown_site(meta = list(...)) data_authors(pkg) } expect_snapshot(error = TRUE, { data_authors_(authors = 1) data_authors_(authors = list(before = 1)) data_authors_(authors = list(after = 1)) }) }) test_that("data_home_sidebar_authors validates yaml inputs", { data_home_sidebar_authors_ <- function(...) { pkg <- local_pkgdown_site(meta = list(...)) data_home_sidebar_authors(pkg) } expect_snapshot(error = TRUE, { data_home_sidebar_authors_(authors = list(sidebar = list(roles = 1))) data_home_sidebar_authors_(authors = list(sidebar = list(before = 1))) data_home_sidebar_authors_( authors = list(sidebar = list(before = "x\n\ny")) ) }) }) # authors -------------------------------------------------------------------- test_that("ORCID can be identified & removed from all comment styles", { desc <- desc::desc( text = c( 'Authors@R: c(', ' person("no comment"),', ' person("bare comment", comment = "comment"),', ' person("orcid only", comment = c(ORCID = "0000-0000-0000-0001")),', ' person("both", comment = c("comment", ORCID = "0000-0003-4757-117X"))', ' )' ) ) authors <- purrr::map(desc$get_authors(), author_list, list()) expect_equal( purrr::map(authors, "orcid"), list( NULL, NULL, orcid_link("0000-0000-0000-0001"), orcid_link("0000-0003-4757-117X") ) ) expect_equal( purrr::map(authors, "comment"), list(character(), "comment", character(), "comment") ) }) test_that("ROR can be identified & removed from all comment styles", { desc <- desc::desc( text = c( 'Authors@R: c(', ' person("no comment"),', ' person("bare comment", comment = "comment"),', ' person("ror only", comment = c(ROR = "123456789")),', ' person("both", comment = c("comment", ROR = "987653421"))', ' )' ) ) authors <- purrr::map(desc$get_authors(), author_list, list()) expect_equal( purrr::map(authors, "ror"), list(NULL, NULL, ror_link("123456789"), ror_link("987653421")) ) expect_equal( purrr::map(authors, "comment"), list(character(), "comment", character(), "comment") ) }) test_that("author comments linkified with escaped angle brackets (#2127)", { p <- list(name = "Jane Doe", roles = "rev", comment = "") expect_match( author_desc(p), "<https://x.org/>", fixed = TRUE ) }) test_that("authors data can be filtered with different roles", { pkg <- local_pkgdown_site( desc = list( `Authors@R` = ' c( person("Hadley", "Wickham", , "hadley@rstudio.com", role = c("aut", "cre")), person("RStudio", role = c("cph", "fnd")) )' ) ) expect_length(data_authors(pkg)$main, 2) expect_length(data_authors(pkg, roles = "cre")$main, 1) }) test_that("authors data includes inst/AUTHORS", { pkg <- local_pkgdown_site() pkg <- pkg_add_file(pkg, "inst/AUTHORS", "Hello") expect_equal(data_authors(pkg)$inst, "Hello") }) test_that("sidebar can accept additional before and after text", { pkg <- local_pkgdown_site() pkg$meta$authors$sidebar$before <- "BEFORE" pkg$meta$authors$sidebar$after <- "AFTER" expect_snapshot(cat(data_home_sidebar_authors(pkg))) }) test_that("role has multiple fallbacks", { expect_equal(role_lookup("cre"), "maintainer") expect_equal(role_lookup("res"), "researcher") expect_snapshot(role_lookup("unknown")) }) # citations ------------------------------------------------------------------- test_that("can handle UTF-8 encoding (#416, #493)", { # Work around bug in utils::citation() local_options(warnPartialMatchDollar = FALSE) pkg <- local_pkgdown_site( desc = list( Title = "A søphîstiçated påckagé", Date = "2018-02-02" ) ) meta <- create_citation_meta(pkg$src_path) expect_type(meta, "list") expect_equal(meta$Title, "A søphîstiçated påckagé") pkg <- pkg_add_file( pkg, "inst/CITATION", c( 'citEntry(', ' entry = "Article",', ' title="Title: é",', ' author="Author: é",', ' journal="Journal é",', ' year="2017",', ' textVersion = "é"', ')' ) ) cit <- read_citation(pkg$src_path) expect_s3_class(cit, "citation") pkg <- pkg_add_file(pkg, "inst/CITATION", "citation(auto = meta)") cit <- read_citation(pkg$src_path) expect_s3_class(cit, "citation") }) test_that("can handle latin1 encoding (#689)", { pkg <- local_pkgdown_site( desc = list( Title = "A søphîstiçated påckagé", Date = "2018-02-02", Encoding = "latin1" ) ) meta <- create_citation_meta(pkg$src_path) expect_equal(meta$Title, "A søphîstiçated påckagé") expect_equal(Encoding(meta$Title), "UTF-8") pkg <- pkg_add_file( pkg, "inst/CITATION", c( 'citEntry(', ' entry = "Article",', ' title="Title: é",', ' author="Author: é",', ' journal="Journal é",', ' year="2017",', ' textVersion = "é"', ')' ) ) cit_path <- path(pkg$src_path, "inst/CITATION") citation <- readLines(cit_path) # nolint con <- file(cit_path, open = "w+", encoding = "native.enc") withr::defer(close(con)) base::writeLines(iconv(citation, to = "latin1"), con, useBytes = TRUE) # nolint cit <- read_citation(pkg$src_path) expect_s3_class(cit, "citation") pkg <- pkg_add_file(pkg, "inst/CITATION", "citation(auto = meta)") cit <- read_citation(pkg$src_path) expect_s3_class(cit, "citation") }) test_that("source link is added to citation page", { # Work around bug in utils::citation() local_options(warnPartialMatchDollar = FALSE) pkg <- local_pkgdown_site( meta = list( repo = list(url = list(source = "http://github.com/test/test")) ) ) pkg <- pkg_add_file( pkg, "inst/CITATION", c( 'citEntry(', ' entry = "Article",', ' title="Title",', ' author="Author",', ' journal="Journal",', ' year="2020",', ' textVersion = ""', ')' ) ) suppressMessages(build_citation_authors(pkg)) lines <- read_lines(path(pkg$dst_path, "authors.html")) expect_match( lines, "inst/CITATION", all = FALSE, fixed = TRUE ) }) test_that("multiple citations all have HTML and BibTeX formats", { pkg <- local_pkgdown_site() pkg <- pkg_add_file( pkg, "inst/CITATION", c( 'bibentry("misc", title="Proof of b < a > c", author=c("A", "B"), year="2021", textVersion="A & B (2021): Proof of b < a > c.")', 'bibentry("misc", title="Title Two", author="Author Two", year="2022")' ) ) citations <- data_citations(pkg$src_path) expect_snapshot_output(citations) }) test_that("bibtex is escaped", { pkg <- local_pkgdown_site() pkg <- pkg_add_file( pkg, "inst/CITATION", c( 'citEntry(', ' entry = "Article",', ' title="test special HTML characters: <&>",', ' author="x",', ' journal="x",', ' year="2017",', ' textVersion = ""', ')' ) ) suppressMessages(build_citation_authors(pkg)) html <- xml2::read_html(path(pkg$dst_path, "authors.html")) expect_match(xpath_text(html, "//pre"), "<&>", fixed = TRUE) }) pkgdown/tests/testthat/test-tweak-navbar.R0000644000176200001440000000423614770274305020425 0ustar liggesuserstest_that("navbar_links_haystack()", { html <- xml2::read_html( ' ' ) best_match <- function(path) { navbar_links_haystack(html, pkg = list(), path)[1, c("links", "similar")] } # Link to exact path if present expect_equal( best_match("articles/pkgdown.html"), tibble::tibble(links = "articles/pkgdown.html", similar = 2) ) # even if in sub-menu expect_equal( best_match("articles/linking.html"), tibble::tibble(links = "articles/linking.html", similar = 2) ) # ignores index.html expect_equal( best_match("articles/index.html"), tibble::tibble(links = "articles", similar = 1) ) # If not present, guess at top-level home expect_equal( best_match("articles/bla.html"), tibble::tibble(links = "articles", similar = 1) ) }) test_that("activation sets class of best match", { html <- xml2::read_html( ' ' ) activate_navbar(html, "articles/linking.html") expect_equal( xpath_attr(html, "//li", "class"), c("nav-item", "nav-item", "active nav-item dropdown") ) }) pkgdown/tests/testthat/test-navbar.R0000644000176200001440000001273614770274305017320 0ustar liggesuserstest_that("adds github/gitlab/codeberg link when available", { pkg <- pkg_navbar() expect_snapshot_output(navbar_components(pkg)) pkg <- pkg_navbar(github_url = "https://github.com/r-lib/pkgdown") expect_snapshot_output(navbar_components(pkg)) pkg <- pkg_navbar(github_url = "https://gitlab.com/r-lib/pkgdown") expect_snapshot_output(navbar_components(pkg)) }) test_that("vignette with package name turns into getting started", { vig <- pkg_navbar_vignettes("test") pkg <- pkg_navbar(vignettes = vig) expect_snapshot_output(navbar_components(pkg)) }) test_that("can control articles navbar through articles meta", { pkg <- function(...) { vig <- pkg_navbar_vignettes(c("a", "b")) pkg_navbar(vignettes = vig, meta = list(...)) } "Default: show all alphabetically" expect_snapshot(navbar_articles(pkg())) "No navbar sections: link to index" expect_snapshot( navbar_articles( pkg( articles = list(list(name = "all", contents = c("a", "b"))) ) ) ) "navbar without text" expect_snapshot( navbar_articles( pkg( articles = list(list( name = "all", contents = c("a", "b"), navbar = NULL )) ) ) ) "navbar with label" expect_snapshot( navbar_articles( pkg( articles = list(list( name = "all", contents = c("a", "b"), navbar = "Label" )) ) ) ) "navbar with only some articles" expect_snapshot( navbar_articles( pkg( articles = list( list(name = "a", contents = "a", navbar = NULL), list(name = "b", contents = "b") ) ) ) ) }) test_that("can control articles navbar through navbar meta", { pkg <- local_pkgdown_site( meta = list( navbar = list( components = list( articles = menu_submenu("Hi!", list(menu_heading("Hi"))) ) ) ) ) pkg <- pkg_add_file(pkg, "vignettes/a.Rmd", pkg_vignette()) pkg <- pkg_add_file(pkg, "vignettes/b.Rmd", pkg_vignette()) navbar <- navbar_link_components(pkg) expect_equal(navbar$left$articles$text, "Hi!") }) test_that("data_navbar() works by default", { pkg <- local_pkgdown_site( meta = list( repo = list(url = list(home = "https://github.com/r-lib/pkgdown/")) ) ) file_touch(path(pkg$src_path, "NEWS.md")) expect_snapshot(data_navbar(pkg)) }) test_that("data_navbar() can re-order default elements", { pkg <- local_pkgdown_site( meta = list( repo = list(url = list(home = "https://github.com/r-lib/pkgdown/")), navbar = list( structure = list( left = c("github", "search"), right = "news" ) ) ) ) file_create(path(pkg$src_path, "NEWS.md")) expect_snapshot(data_navbar(pkg)[c("left", "right")]) }) test_that("data_navbar() can remove elements", { pkg <- local_pkgdown_site( meta = list( navbar = list( structure = list( left = c("github", "search"), right = list() ) ) ) ) expect_equal(data_navbar(pkg)$right, "") }) test_that("data_navbar() works with empty side", { pkg <- local_pkgdown_site( meta = list(navbar = list(structure = list(left = list(), right = list()))) ) expect_snapshot(data_navbar(pkg)) }) test_that("data_navbar_() errors with bad yaml specifications", { data_navbar_ <- function(...) { pkg <- local_pkgdown_site(meta = list(...)) data_navbar(pkg) } expect_snapshot(error = TRUE, { data_navbar_(navbar = list(structure = list(left = 1))) data_navbar_(navbar = list(right = "github")) }) }) test_that("for bs4, default bg and type come from bootswatch", { style <- navbar_style(bs_version = 5) expect_equal(style, list(bg = "light", type = "light")) style <- navbar_style(theme = "cyborg", bs_version = 5) expect_equal(style, list(bg = "dark", type = "dark")) # but can override style <- navbar_style(list(bg = "primary"), bs_version = 5) expect_equal(style, list(bg = "primary", type = "dark")) style <- navbar_style(list(bg = "primary", type = "light"), bs_version = 5) expect_equal(style, list(bg = "primary", type = "light")) }) test_that("render_navbar_links BS3 & BS4 default", { x <- list( intro = menu_link("Get started", "articles/pkgdown.html"), reference = menu_link("Reference", "reference/index.html"), articles = menu_submenu( "Articles", list( menu_link("Auto-linking", "articles/linking.html"), menu_link("Search", "articles/search.html"), menu_link("Metadata", "articles/metadata.html"), menu_link( "Customize your pkgdown website", "articles/customization.html" ), menu_separator(), menu_link("More...", "articles/index.html") ) ), news = menu_link("News", "news/index.html") ) expect_snapshot(cat(render_navbar_links(x, pkg = list(bs_version = 3)))) expect_snapshot(cat(render_navbar_links(x, pkg = list(bs_version = 4)))) }) test_that("dropdowns on right are right-aligned", { x <- list( articles = menu_submenu( "Articles", list(menu_heading("A"), menu_heading("B")) ) ) pkg <- list(bs_version = 5) right <- xml2::read_html(render_navbar_links(x, pkg = pkg, side = "right")) left <- xml2::read_html(render_navbar_links(x, pkg = pkg, side = "left")) expect_equal( xpath_attr(right, ".//ul", "class"), "dropdown-menu dropdown-menu-end" ) expect_equal(xpath_attr(left, ".//ul", "class"), "dropdown-menu") }) pkgdown/tests/testthat/test-build-github.R0000644000176200001440000000112114634573316020413 0ustar liggesuserstest_that("a CNAME record is built if a url exists in metadata", { pkg <- local_pkgdown_site(meta = list(url = "https://testpackage.r-lib.org")) dir_create(path(pkg$dst_path, "docs")) expect_snapshot(build_github_pages(pkg)) expect_equal(read_lines(path(pkg$dst_path, "CNAME")), "testpackage.r-lib.org") }) test_that("CNAME URLs are valid", { expect_equal(cname_url("http://google.com/"), "google.com") expect_equal(cname_url("https://google.com/"), "google.com") # this is not a valid URL because it has a trailing path expect_null(cname_url("http://google.com/path/")) }) pkgdown/tests/testthat/test-deploy-site.R0000644000176200001440000000101013634412136020256 0ustar liggesusers# ci_commit_sha() ------------------------------------------------------------ test_that("commit sha can be retrieved from travis or GitHub action env vars", { sha <- "XYZ" withr::with_envvar( c("TRAVIS_COMMIT" = sha, "GITHUB_SHA" = ""), expect_equal(ci_commit_sha(), sha) ) withr::with_envvar( c("TRAVIS_COMMIT" = "", "GITHUB_SHA" = sha), expect_equal(ci_commit_sha(), sha) ) withr::with_envvar( c("TRAVIS_COMMIT" = "", "GITHUB_SHA" = ""), expect_equal(ci_commit_sha(), "") ) }) pkgdown/tests/testthat/test-build-home.R0000644000176200001440000000204714770274305020066 0ustar liggesusers# index ------------------------------------------------------------------- test_that("can build site even if no Authors@R present", { skip_if_no_pandoc() pkg <- local_pkgdown_site( desc = list( Author = "Hadley Wickham", Maintainer = "Hadley Wickham ", `Authors@R` = NA ) ) expect_no_error(suppressMessages(build_home_index(pkg))) }) test_that("can build package without any index/readme", { pkg <- local_pkgdown_site() expect_no_error(suppressMessages(build_home_index(pkg))) }) # .github files ----------------------------------------------------------- test_that(".github files are copied and linked", { skip_if_no_pandoc() pkg <- local_pkgdown_site() pkg <- pkg_add_file(pkg, ".github/404.md") pkg <- pkg_add_file(pkg, ".github/CODE_OF_CONDUCT.md") suppressMessages(build_home(pkg)) lines <- read_lines(path(pkg$dst_path, "index.html")) expect_match(lines, 'href="CODE_OF_CONDUCT.html"', fixed = TRUE, all = FALSE) expect_true(file_exists(path(pkg$dst_path, "404.html"))) }) pkgdown/tests/testthat/test-build-reference-index.R0000644000176200001440000001025214770274305022176 0ustar liggesuserstest_that("can generate three types of row", { ref <- list( list(title = "A"), list(subtitle = "B"), list(contents = c("a", "b", "c", "e", "?")) ) meta <- list(reference = ref) pkg <- as_pkgdown(test_path("assets/reference"), override = meta) expect_snapshot(data_reference_index(pkg)) }) test_that("can use markdown in title and subtitle", { ref <- list( list(title = "*A*"), list(subtitle = "*B*"), list(contents = c("a", "b", "c", "e", "?")) ) meta <- list(reference = ref) pkg <- as_pkgdown(test_path("assets/reference"), override = meta) data <- data_reference_index(pkg) expect_equal(data$rows[[1]]$title, "A") expect_equal(data$rows[[2]]$subtitle, "B") }) test_that("rows with title internal are dropped", { ref <- list( list(title = "internal", contents = c("a", "b")), list(contents = c("c", "e", "?")), list(title = "internal") ) meta <- list(reference = ref) pkg <- as_pkgdown(test_path("assets/reference"), override = meta) expect_warning(index <- data_reference_index(pkg), NA) expect_equal(length(index$rows), 1) }) test_that("duplicate entries within a group is dropped", { ref <- list( list(contents = c("a", "b", "a", "a")), list(contents = c("b", "c", "?", "e")) ) meta <- list(reference = ref) pkg <- as_pkgdown(test_path("assets/reference"), override = meta) index <- data_reference_index(pkg) expect_equal(length(index$rows[[1]]$topics), 2) expect_equal(length(index$rows[[2]]$topics), 4) }) test_that("warns if missing topics", { ref <- list( list(contents = c("a", "b")) ) meta <- list(reference = ref) pkg <- as_pkgdown(test_path("assets/reference"), override = meta) expect_snapshot(data_reference_index(pkg), error = TRUE) }) test_that("default reference includes all functions, only escaping non-syntactic", { ref <- default_reference_index(test_path("assets/reference")) expect_equal(ref[[1]]$contents, c("a", "b", "c", "e", "`?`")) }) test_that("gives informative errors", { data_reference_index_ <- function(x) { pkg <- local_pkgdown_site(meta = list(reference = x)) data_reference_index(pkg) } expect_snapshot(error = TRUE, { data_reference_index_(1) data_reference_index_(list(1)) data_reference_index_(list(list(title = 1))) data_reference_index_(list(list(title = "a\n\nb"))) data_reference_index_(list(list(subtitle = 1))) data_reference_index_(list(list(subtitle = "a\n\nb"))) data_reference_index_(list(list(title = "bla", contents = 1))) data_reference_index_(list(list(title = "bla", contents = NULL))) data_reference_index_(list(list(title = "bla", contents = list("a", NULL)))) data_reference_index_(list(list(title = "bla", contents = list()))) data_reference_index_(list(list( title = "bla", contents = "notapackage::lala" ))) data_reference_index_(list(list(title = "bla", contents = "rlang::lala"))) }) }) test_that("can exclude topics", { pkg <- local_pkgdown_site( test_path("assets/reference"), list( reference = list( list(title = "Exclude", contents = c("a", "b", "-a")), list( title = "Exclude multiple", contents = c("a", "b", "c", "-matches('a|b')") ), list(title = "Everything else", contents = c("a", "c", "e", "?")) ) ) ) ref <- data_reference_index(pkg) # row 1 is the title row expect_equal(length(ref$rows[[2]]$topics), 1) expect_equal(ref$rows[[2]]$topics[[1]]$aliases, "b()") expect_equal(length(ref$rows[[4]]$topics), 1) expect_equal(ref$rows[[4]]$topics[[1]]$aliases, "c()") }) test_that("can use a topic from another package", { pkg <- local_pkgdown_site( meta = list( reference = list( list( title = "bla", contents = c("rlang::is_installed()", "bslib::bs_add_rules") ) ) ) ) expect_snapshot(data_reference_index(pkg)) }) test_that("can use a selector name as a topic name", { pkg <- local_pkgdown_site( test_path("assets/reference-selector"), list( reference = list( list(title = "bla", contents = c("matches", "matches('A')")) ) ) ) expect_snapshot(data_reference_index(pkg)) }) pkgdown/tests/testthat/test-init.R0000644000176200001440000000420114770274305016776 0ustar liggesuserstest_that("informative print method", { pkg <- local_pkgdown_site() expect_snapshot(init_site(pkg)) }) test_that("extra.css and extra.js copied and linked", { pkg <- local_pkgdown_site() dir_create(path(pkg$src_path, "pkgdown")) file_create(path(pkg$src_path, "pkgdown", "extra.css")) file_create(path(pkg$src_path, "pkgdown", "extra.js")) suppressMessages(init_site(pkg)) expect_true(file_exists(path(pkg$dst_path, "extra.css"))) expect_true(file_exists(path(pkg$dst_path, "extra.js"))) skip_if_no_pandoc() # Now check they actually get used . suppressMessages(build_home(pkg)) html <- xml2::read_html(path(pkg$dst_path, "index.html")) paths <- xpath_attr(html, ".//link", "href") expect_true("extra.css" %in% paths) }) test_that("single extra.css correctly copied", { pkg <- local_pkgdown_site() dir_create(path(pkg$src_path, "pkgdown")) file_create(path(pkg$src_path, "pkgdown", "extra.css")) suppressMessages(init_site(pkg)) expect_true(file_exists(path(pkg$dst_path, "extra.css"))) }) test_that("asset subdirectories are copied", { pkg <- local_pkgdown_site() pkg <- pkg_add_file(pkg, "pkgdown/assets/subdir1/file1.txt") pkg <- pkg_add_file(pkg, "pkgdown/assets/subdir1/subdir2/file2.txt") suppressMessages(init_site(pkg)) expect_true(file_exists(path(pkg$dst_path, "subdir1", "file1.txt"))) expect_true(file_exists(path( pkg$dst_path, "subdir1", "subdir2", "file2.txt" ))) }) test_that("site meta doesn't break unexpectedly", { pkg <- local_pkgdown_site() pkg <- pkg_add_file(pkg, "vignettes/a.Rmd") pkg <- pkg_add_file(pkg, "vignettes/b.Rmd") # null out components that will vary yaml <- site_meta(pkg) yaml$pkgdown <- "{version}" yaml$pkgdown_sha <- "{sha}" yaml$pandoc <- "{version}" yaml$last_built <- timestamp(as.POSIXct("2020-01-01", tz = "UTC")) expect_snapshot(yaml) }) test_that("site meta includes vignette subdirectories", { pkg <- local_pkgdown_site() pkg <- pkg_add_file(pkg, "vignettes/a/a.Rmd") pkg <- pkg_add_file(pkg, "vignettes/a/b.Rmd") meta <- site_meta(pkg) expect_equal(meta$articles, list("a/a" = "a/a.html", "a/b" = "a/b.html")) }) pkgdown/tests/testthat/_snaps/0000755000176200001440000000000015100735002016201 5ustar liggesuserspkgdown/tests/testthat/_snaps/usage.md0000644000176200001440000000100515100735320017626 0ustar liggesusers# usage generates user facing code for S3/S4 infix/replacement methods Code cat(usage2text("\\S3method{$}{indexed_frame}(x, name)")) Output # S3 method for class 'indexed_frame' x$name Code cat(usage2text("\\method{[[}{indexed_frame}(x, i) <- value")) Output # S3 method for class 'indexed_frame' x[[i]] <- value Code cat(usage2text("\\S4method{>=}{MyType,numeric}(e1, e2)")) Output # S4 method for class 'MyType,numeric' e1 >= e2 pkgdown/tests/testthat/_snaps/build-llm-dl.md0000644000176200001440000000053615100735311021010 0ustar liggesusers# dd with block elements simplifies correctly Code xpath_xml(html, ".//li") Output
  • a:

    b

    c

  • # warns if not applied Code . <- simplify_dls(html) Condition Warning: Skipping this
    : not a simple term-definition list pkgdown/tests/testthat/_snaps/theme.md0000644000176200001440000000141715100735317017641 0ustar liggesusers# check_bslib_theme() works Code check_bslib_theme("paper", pkg, bs_version = 4) Condition Error: x In _pkgdown.yml, template.bootswatch contains unknown Bootswatch/bslib theme "paper". i Using Bootstrap version 4 (template.bootstrap). # validations yaml specification Code build_bslib_(theme = 1) Condition Error in `bs_theme_rules()`: ! In _pkgdown.yml, template.theme must be a string, not the number 1. Code build_bslib_(theme = "fruit") Condition Error in `build_bslib_()`: ! In _pkgdown.yml, template.theme uses theme "fruit" Code build_bslib_(`theme-dark` = "fruit") Condition Error in `build_bslib_()`: ! In _pkgdown.yml, template.theme-dark uses theme "fruit" pkgdown/tests/testthat/_snaps/navbar-menu.md0000644000176200001440000000675215100735315020757 0ustar liggesusers# can construct menu with children Code cat(navbar_html(menu)) Output # bad inputs give clear error Code navbar_html(1) Condition Error in `menu_type()`: ! Navbar components must be named lists, not the number 1. Code navbar_html(list(foo = 1)) Condition Error in `menu_type()`: ! Unknown navbar component with names foo. Code navbar_html(submenu) Condition Error in `menu_type()`: ! Nested menus are not supported. # can construct bullets Code cat(navbar_html(menu_icon("fa-question", "https://example.com", "label"))) Output Code cat(navbar_html(menu_heading("Hi"))) Output Code cat(navbar_html(menu_link("Hi", "https://example.com"))) Output # icons warn if no aria-label Code . <- navbar_html(menu_icon("fa-question", "https://example.com", NULL)) Message x Icon "fa-question" lacks an `aria-label`. i Specify `aria-label` to make the icon accessible to screen readers. i Learn more in `vignette(pkgdown::accessibility)`. This message is displayed once every 8 hours. # can construct theme menu Code cat(navbar_html(lightswitch)) Output # simple components don't change without warning Code cat(navbar_html(menu_heading("a"))) Output Code cat(navbar_html(menu_link("a", "b"))) Output Code cat(navbar_html(menu_separator())) Output Code cat(navbar_html(menu_search())) Output pkgdown/tests/testthat/_snaps/build-redirects.md0000644000176200001440000000116515100735313021614 0ustar liggesusers# build_redirect() works Code build_redirect(c("old.html", "new.html#section"), 1, pkg = pkg) Message Adding redirect from old.html to new.html#section. # build_redirect() errors if one entry is not right. Code data_redirects_(redirects = "old.html") Condition Error in `data_redirects_()`: ! In _pkgdown.yml, redirects must be a list, not the string "old.html". Code data_redirects_(redirects = list("old.html")) Condition Error in `data_redirects_()`: ! In _pkgdown.yml, redirects[1] must be a character vector of length 2, not the string "old.html". pkgdown/tests/testthat/_snaps/not-in-rcmcheck/0000755000176200001440000000000015001744016021167 5ustar liggesuserspkgdown/tests/testthat/_snaps/not-in-rcmcheck/build-article.md0000644000176200001440000000137315001744016024235 0ustar liggesusers# build_article yields useful error if R fails Code build_article("test", pkg) Message Reading vignettes/test.Rmd Condition Error in `build_article()`: ! Failed to render 'vignettes/test.Rmd'. x Quitting from test.Rmd:4-10 [unnamed-chunk-1] Caused by error: ! Error! --- Code summary(expect_error(build_article("test", pkg))) Message Reading vignettes/test.Rmd Output Error in `build_article()`: ! Failed to render 'vignettes/test.Rmd'. x Quitting from test.Rmd:4-10 [unnamed-chunk-1] Caused by error: ! Error! --- Backtrace: x 1. \-global f() 2. \-global g() 3. \-global h() pkgdown/tests/testthat/_snaps/init.md0000644000176200001440000000413015100735317017475 0ustar liggesusers# informative print method Code init_site(pkg) Message -- Initialising site ----------------------------------------------------------- Copying /BS5/assets/katex-auto.js to katex-auto.js Copying /BS5/assets/lightswitch.js to lightswitch.js Copying /BS5/assets/link.svg to link.svg Copying /BS5/assets/pkgdown.js to pkgdown.js Updating deps/bootstrap-5.3.1/bootstrap.bundle.min.js Updating deps/bootstrap-5.3.1/bootstrap.bundle.min.js.map Updating deps/bootstrap-5.3.1/bootstrap.min.css Updating deps/bootstrap-toc-1.0.1/bootstrap-toc.min.js Updating deps/clipboard.js-2.0.11/clipboard.min.js Updating deps/font-awesome-6.5.2/css/all.css Updating deps/font-awesome-6.5.2/css/all.min.css Updating deps/font-awesome-6.5.2/css/v4-shims.css Updating deps/font-awesome-6.5.2/css/v4-shims.min.css Updating deps/font-awesome-6.5.2/webfonts/fa-brands-400.ttf Updating deps/font-awesome-6.5.2/webfonts/fa-brands-400.woff2 Updating deps/font-awesome-6.5.2/webfonts/fa-regular-400.ttf Updating deps/font-awesome-6.5.2/webfonts/fa-regular-400.woff2 Updating deps/font-awesome-6.5.2/webfonts/fa-solid-900.ttf Updating deps/font-awesome-6.5.2/webfonts/fa-solid-900.woff2 Updating deps/font-awesome-6.5.2/webfonts/fa-v4compatibility.ttf Updating deps/font-awesome-6.5.2/webfonts/fa-v4compatibility.woff2 Updating deps/headroom-0.11.0/headroom.min.js Updating deps/headroom-0.11.0/jQuery.headroom.min.js Updating deps/jquery-3.6.0/jquery-3.6.0.js Updating deps/jquery-3.6.0/jquery-3.6.0.min.js Updating deps/jquery-3.6.0/jquery-3.6.0.min.map Updating deps/search-1.0.0/autocomplete.jquery.min.js Updating deps/search-1.0.0/fuse.min.js Updating deps/search-1.0.0/mark.min.js # site meta doesn't break unexpectedly Code yaml Output pandoc: '{version}' pkgdown: '{version}' pkgdown_sha: '{sha}' articles: a: a.html b: b.html last_built: 2020-01-01T00:00Z pkgdown/tests/testthat/_snaps/repo.md0000644000176200001440000000103115100735317017474 0ustar liggesusers# repo_source() truncates automatically Code cat(repo_source(pkg, character())) cat(repo_source(pkg, "a")) Output Source: a Code cat(repo_source(pkg, letters[1:10])) Output Source: a, b, c, and 7 more pkgdown/tests/testthat/_snaps/preview.md0000644000176200001440000000071215100735316020214 0ustar liggesusers# checks its inputs Code preview_site(pkg, path = 1) Condition Error in `preview_site()`: ! `path` must be a single string, not the number 1. Code preview_site(pkg, path = "foo") Condition Error in `preview_site()`: ! Can't find file 'foo'. Code preview_site(pkg, preview = 1) Condition Error in `preview_site()`: ! `preview` must be `TRUE`, `FALSE`, or `NA`, not the number 1. pkgdown/tests/testthat/_snaps/build-article.md0000644000176200001440000000274715100762421021262 0ustar liggesusers# bad width gives nice error Code rmarkdown_setup_pkgdown(pkg) Condition Error in `rmarkdown_setup_pkgdown()`: ! In _pkgdown.yml, code.width must be a whole number, not the string "abc". # output is reproducible by default, i.e. 'seed' is respected Code cat(output) Output ## [1] 0.080750138 0.834333037 0.600760886 0.157208442 0.007399441 # reports on bad open graph meta-data Code build_article("test", pkg) Message Reading vignettes/test.Rmd Condition Error in `build_article()`: ! In vignettes/test.Rmd, opengraph.twitter must be a list, not the number 1. # build_article styles ANSI escapes ## X # build_article copies image files in subdirectories Code build_article("test", pkg) Message Reading vignettes/test.Rmd Writing `articles/test.html` # warns about missing images Code build_article("kitten", pkg) Message Reading vignettes/kitten.Rmd Writing `articles/kitten.html` Missing images in 'vignettes/kitten.Rmd': 'kitten.jpg' i pkgdown can only use images in 'man/figures' and 'vignettes' # warns about missing alt-text Code build_article("kitten", pkg) Message Reading vignettes/kitten.Rmd Writing `articles/kitten.html` x Missing alt-text in 'vignettes/kitten.Rmd' * kitten.jpg i Learn more in `vignette(pkgdown::accessibility)`. pkgdown/tests/testthat/_snaps/tweak-tags.md0000644000176200001440000000045715100735320020603 0ustar liggesusers# anchor html added to headings

    abc

    # can process footnote with code Code xpath_attr(html, ".//a", "data-bs-content") Output [1] "

    Including code:

    \n
    1 +\n2 +
    \n

    And more text

    " pkgdown/tests/testthat/_snaps/build-home-authors.md0000644000176200001440000000444415100735311022244 0ustar liggesusers# data_authors validates yaml inputs Code data_authors_(authors = 1) Condition Error in `data_authors_()`: ! In _pkgdown.yml, authors must be a list, not the number 1. Code data_authors_(authors = list(before = 1)) Condition Error in `data_authors_()`: ! In _pkgdown.yml, authors.before must be a string, not the number 1. Code data_authors_(authors = list(after = 1)) Condition Error in `data_authors_()`: ! In _pkgdown.yml, authors.after must be a string, not the number 1. # data_home_sidebar_authors validates yaml inputs Code data_home_sidebar_authors_(authors = list(sidebar = list(roles = 1))) Condition Error in `data_home_sidebar_authors_()`: ! In _pkgdown.yml, authors.sidebar.roles must be a character vector, not the number 1. Code data_home_sidebar_authors_(authors = list(sidebar = list(before = 1))) Condition Error in `data_home_sidebar_authors_()`: ! In _pkgdown.yml, authors.sidebar.before must be a string, not the number 1. Code data_home_sidebar_authors_(authors = list(sidebar = list(before = "x\n\ny"))) Condition Error in `data_home_sidebar_authors_()`: ! In _pkgdown.yml, authors.sidebar.before must be inline markdown. # sidebar can accept additional before and after text Code cat(data_home_sidebar_authors(pkg)) Output

    Developers

    • BEFORE
    • Jo Doe
      Author, maintainer
    • AFTER
    # role has multiple fallbacks Code role_lookup("unknown") Condition Warning: Unknown MARC role abbreviation: unknown Output [1] "unknown" # multiple citations all have HTML and BibTeX formats [[1]] [[1]]$html [1] "

    A & B (2021): Proof of b < a > c.

    " [[1]]$bibtex [1] "@Misc{,\n title = {Proof of b < a > c},\n author = {{A} and {B}},\n year = {2021},\n}" [[2]] [[2]]$html [1] "

    Two A (2022).\n“Title Two.” \n

    " [[2]]$bibtex [1] "@Misc{,\n title = {Title Two},\n author = {Author Two},\n year = {2022},\n}" pkgdown/tests/testthat/_snaps/package.md0000644000176200001440000000263215100735316020131 0ustar liggesusers# is_pkgdown checks its inputs Code as_pkgdown(1) Condition Error in `as_pkgdown()`: ! `pkg` must be a single string, not the number 1. Code as_pkgdown(override = 1) Condition Error in `as_pkgdown()`: ! `override` must be a list, not the number 1. # check_bootstrap_version() allows 3, 4 (with warning), and 5 Code expect_equal(check_bootstrap_version(4, pkg), 5) Condition Warning: In _pkgdown.yml, `template.bootstrap: 4` no longer supported i Using `template.bootstrap: 5` instead # check_bootstrap_version() gives informative error otherwise Code check_bootstrap_version(1, pkg) Condition Error in `check_bootstrap_version()`: ! In _pkgdown.yml, template.bootstrap must be 3 or 5, not 1. # package_vignettes() detects conflicts in final article paths Code package_vignettes(dir) Condition Error in `package_vignettes()`: ! Rendered articles must have unique names. Rename or relocate: x vignettes/articles/test.Rmd and vignettes/test.Rmd # read_meta() errors gracefully if _pkgdown.yml failed to parse Code as_pkgdown(pkg$src_path) Condition Error in `as_pkgdown()`: ! Could not parse config file at '/_pkgdown.yml'. Caused by error in `yaml.load()`: ! Scanner error: mapping values are not allowed in this context at line 2, column 8 pkgdown/tests/testthat/_snaps/build-llm.md0000644000176200001440000000025215100735311020406 0ustar liggesusers# integration test for convert_md() Code write_lines(read_lines(path), stdout()) Output # Page title ## Heading Some text pkgdown/tests/testthat/_snaps/build-footer.md0000644000176200001440000000216615100735311021126 0ustar liggesusers# works by default $left [1] "

    Developed by First Last.

    " $right [1] "

    Site built with pkgdown {version}.

    " # validates meta components Code data_footer_(footer = 1) Condition Error in `data_footer_()`: ! In _pkgdown.yml, footer must be a list, not the number 1. Code data_footer_(footer = list(structure = 1)) Condition Error in `data_footer_()`: ! In _pkgdown.yml, footer.structure must be a list, not the number 1. Code data_footer_(footer = list(components = 1)) Condition Error in `data_footer_()`: ! In _pkgdown.yml, footer.components must be a list, not the number 1. Code data_footer_(authors = list(footer = list(roles = 1))) Condition Error in `data_footer_()`: ! In _pkgdown.yml, authors.footer.roles must be a character vector, not the number 1. Code data_footer_(authors = list(footer = list(text = 1))) Condition Error in `data_footer_()`: ! In _pkgdown.yml, authors.footer.text must be a string, not the number 1. pkgdown/tests/testthat/_snaps/utils-fs.md0000644000176200001440000000056515100735320020302 0ustar liggesusers# missing template package yields custom error Code path_package_pkgdown("x", "missing", 3) Condition Error: ! Template package "missing" is not installed. i Please install before continuing. # out_of_date works as expected Code out_of_date("doesntexist", temp1) Condition Error: ! 'doesntexist' does not exist pkgdown/tests/testthat/_snaps/config.md0000644000176200001440000000150415100735315017777 0ustar liggesusers# config_pluck_character generates informative error Code config_pluck_character(pkg, "x") Condition Error: ! In _pkgdown.yml, x must be a character vector, not the number 1. # config_pluck_string generates informative error Code config_pluck_string(pkg, "x") Condition Error: ! In _pkgdown.yml, x must be a string, not the number 1. # config_check_list gives informative errors Code config_check_list_(1, has_names = "x") Condition Error in `config_check_list_()`: ! In _pkgdown.yml, path must be a list, not the number 1. Code config_check_list_(list(x = 1, y = 1), has_names = c("y", "z")) Condition Error in `config_check_list_()`: ! In _pkgdown.yml, path must have components "y" and "z". 1 missing component: "z". pkgdown/tests/testthat/_snaps/highlight.md0000644000176200001440000000110015100735315020471 0ustar liggesusers# highlight_examples runs and hides DONTSHOW calls() Code cat(strip_html_tags(out)) Output x #> [1] 1 # pre() can produce needed range of outputs Code cat(pre("x")) Output
    x
    Code cat(pre("x", r_code = TRUE)) Output
    x
    # tweak_highlight_other() renders nested code blocks for roxygen2 >= 7.2.0 Code cat(xpath_text(div, "pre/code")) Output blablabla ```{r results='asis'} lalala ``` pkgdown/tests/testthat/_snaps/check-built.md0000644000176200001440000000044315100735315020725 0ustar liggesusers# check images in readme Code check_built_site(pkg) Message -- Checking for problems ------------------------------------------------------- Missing images in 'README.md': 'articles/kitten.jpg' i pkgdown can only use images in 'man/figures' and 'vignettes' pkgdown/tests/testthat/_snaps/external-deps.md0000644000176200001440000000142215100735315021304 0ustar liggesusers# check integrity validates integrity Code check_integrity(temp, "sha123-abc") Condition Error in `check_integrity()`: ! integrity must use SHA-256, SHA-384, or SHA-512 i This is an internal error that was detected in the pkgdown package. Please report it at with a reprex () and the full backtrace. Code check_integrity(temp, "sha256-abc") Condition Error in `check_integrity()`: ! Downloaded asset does not match known integrity i This is an internal error that was detected in the pkgdown package. Please report it at with a reprex () and the full backtrace. pkgdown/tests/testthat/_snaps/topics.md0000644000176200001440000000541115100735320020030 0ustar liggesusers# bad inputs give informative warnings Code select_topics_("x + ", topics) Condition Error in `select_topics_()`: ! In _pkgdown.yml, reference[1].contents[1] (x + ) must be valid R code. Code select_topics_("y", topics) Condition Error in `select_topics_()`: ! In _pkgdown.yml, reference[1].contents[1] (y) must be a known topic name or alias. Code select_topics_("paste(1)", topics) Condition Error in `select_topics_()`: ! In _pkgdown.yml, reference[1].contents[1] (paste(1)) failed to evaluate. Caused by error in `paste()`: ! could not find function "paste" Code select_topics_("starts_with", topics) Condition Error in `select_topics_()`: ! In _pkgdown.yml, reference[1].contents[1] (starts_with) must be a known topic name or alias. Code select_topics_("1", topics) Condition Error in `select_topics_()`: ! In _pkgdown.yml, reference[1].contents[1] (1) must be a string or function call. Code select_topics_("starts_with('y')", topics) Condition Error in `select_topics_()`: ! In _pkgdown.yml, reference[1].contents failed to match any topics. # selector functions validate their inputs Code select_topics_("starts_with('x', 'y')", topics) Condition Error in `select_topics_()`: ! In _pkgdown.yml, reference[1].contents[1] (starts_with('x', 'y')) failed to evaluate. Caused by error in `starts_with()`: ! `internal` must be `TRUE` or `FALSE`, not the string "y". Code select_topics_("starts_with(c('x', 'y'))", topics) Condition Error in `select_topics_()`: ! In _pkgdown.yml, reference[1].contents[1] (starts_with(c('x', 'y'))) failed to evaluate. Caused by error in `starts_with()`: ! `x` must be a single string, not a character vector. # can select by name or alias Code select_topics_("a4", topics) Condition Error in `select_topics_()`: ! In _pkgdown.yml, reference[1].contents[1] (a4) must be a known topic name or alias. Code select_topics_("c::a", topics) Condition Error in `select_topics_()`: ! In _pkgdown.yml, reference[1].contents[1] (c::a) must be a known topic name or alias. # can combine positive and negative selections Code select_topics_("c(a, -x)", topics) Condition Error in `select_topics_()`: ! In _pkgdown.yml, reference[1].contents[1] (c(a, -x)) must be all negative or all positive. # an unmatched selection generates a warning Code select_topics_(c("a", "starts_with('unmatched')"), topics) Condition Error in `select_topics_()`: ! In _pkgdown.yml, reference[1].contents (starts_with('unmatched')) must match a function or concept. pkgdown/tests/testthat/_snaps/render.md0000644000176200001440000000463115100735317020017 0ustar liggesusers# capture data_template() package: name: testpackage version: 1.0.0 site: root: '' title: testpackage year: lang: en translate: skip: Skip to contents toggle_nav: Toggle navigation on_this_page: On this page source: Source abstract: Abstract authors: Authors version: Version examples: Examples citation: Citation author_details: Additional details toc: Table of contents site_nav: Site navigation has_favicons: no opengraph: [] extra: css: ~ js: ~ yaml: .present: yes headdeps: '' development: destination: dev mode: default version_label: muted in_dev: no prefix: '' version_tooltip: '' navbar: bg: light type: light left: right: "
  • \n \n
  • " footer: left:

    Developed by Jo Doe.

    right:

    Site built with pkgdown {version}.

    lightswitch: no uses_katex: no uses_mathjax: no # check_opengraph validates inputs Code data_open_graph_(list(foo = list())) Condition Warning in `data_open_graph_()`: In _pkgdown.yml, template.opengraph contains unsupported fields "foo". Code data_open_graph_(list(foo = list(), bar = list())) Condition Warning in `data_open_graph_()`: In _pkgdown.yml, template.opengraph contains unsupported fields "foo" and "bar". Code data_open_graph_(list(twitter = 1)) Condition Error in `data_open_graph_()`: ! In _pkgdown.yml, template.opengraph.twitter must be a list, not the number 1. Code data_open_graph_(list(twitter = list())) Condition Error in `data_open_graph_()`: ! In _pkgdown.yml, opengraph.twitter must include either creator or site. Code data_open_graph_(list(image = 1)) Condition Error in `data_open_graph_()`: ! In _pkgdown.yml, template.opengraph.image must be a list, not the number 1. pkgdown/tests/testthat/_snaps/build-github.md0000644000176200001440000000036215100735310021105 0ustar liggesusers# a CNAME record is built if a url exists in metadata Code build_github_pages(pkg) Message -- Extra files for GitHub pages ------------------------------------------------ Writing `.nojekyll` Writing `CNAME` pkgdown/tests/testthat/_snaps/topics-external.md0000644000176200001440000000160215100735317021654 0ustar liggesusers# can get info about external function Code str(ext_topics("base::mean")) Output tibble [1 x 12] (S3: tbl_df/tbl/data.frame) $ name : chr "base::mean" $ file_in : chr NA $ file_out : chr "https://rdrr.io/r/base/mean.html" $ alias :List of 1 ..$ : chr(0) $ funs :List of 1 ..$ : chr "mean()" $ title : chr "Arithmetic Mean (from base)" $ rd :List of 1 ..$ : chr(0) $ source : chr NA $ keywords :List of 1 ..$ : chr(0) $ concepts :List of 1 ..$ : chr(0) $ internal : logi FALSE $ lifecycle:List of 1 ..$ : NULL # fails if documentation not available Code ext_topics("base::doesntexist") Condition Error in `build_reference_index()`: ! Could not find documentation for `base::doesntexist()`. pkgdown/tests/testthat/_snaps/navbar.md0000644000176200001440000001533115100735316020007 0ustar liggesusers# adds github/gitlab/codeberg link when available reference: text: Reference href: reference/index.html search: search: [] --- reference: text: Reference href: reference/index.html search: search: [] github: icon: fab fa-github fa-lg href: https://github.com/r-lib/pkgdown aria-label: GitHub --- reference: text: Reference href: reference/index.html search: search: [] github: icon: fab fa-gitlab fa-lg href: https://gitlab.com/r-lib/pkgdown aria-label: GitLab # vignette with package name turns into getting started reference: text: Reference href: reference/index.html search: search: [] intro: text: Get started href: test.html # can control articles navbar through articles meta Code navbar_articles(pkg()) Output articles: text: Articles menu: - text: Title a href: a.html - text: Title b href: b.html --- Code navbar_articles(pkg(articles = list(list(name = "all", contents = c("a", "b"))))) Output articles: text: Articles href: articles/index.html --- Code navbar_articles(pkg(articles = list(list(name = "all", contents = c("a", "b"), navbar = NULL)))) Output articles: text: Articles menu: - text: Title a href: a.html - text: Title b href: b.html --- Code navbar_articles(pkg(articles = list(list(name = "all", contents = c("a", "b"), navbar = "Label")))) Output articles: text: Articles menu: - text: '---------' - text: Label - text: Title a href: a.html - text: Title b href: b.html --- Code navbar_articles(pkg(articles = list(list(name = "a", contents = "a", navbar = NULL), list(name = "b", contents = "b")))) Output articles: text: Articles menu: - text: Title a href: a.html - text: '---------' - text: More articles... href: articles/index.html # data_navbar() works by default Code data_navbar(pkg) Output $bg [1] "light" $type [1] "light" $left [1] "
  • Reference
  • \n
  • Changelog
  • " $right [1] "
  • \n \n
  • \n
  • " # data_navbar() can re-order default elements Code data_navbar(pkg)[c("left", "right")] Output $left [1] "
  • \n
  • \n \n
  • " $right [1] "
  • Changelog
  • " # data_navbar() works with empty side Code data_navbar(pkg) Output $bg [1] "light" $type [1] "light" $left [1] "" $right [1] "" # data_navbar_() errors with bad yaml specifications Code data_navbar_(navbar = list(structure = list(left = 1))) Condition Error in `data_navbar_()`: ! In _pkgdown.yml, navbar.structure.left must be a character vector, not the number 1. Code data_navbar_(navbar = list(right = "github")) Condition Error in `data_template()`: ! In _pkgdown.yml, navbar is incorrectly specified. i See details in `vignette(pkgdown::customise)`. # render_navbar_links BS3 & BS4 default Code cat(render_navbar_links(x, pkg = list(bs_version = 3))) Output
  • Get started
  • Reference
  • News
  • --- Code cat(render_navbar_links(x, pkg = list(bs_version = 4))) Output pkgdown/tests/testthat/_snaps/tweak-tabset.md0000644000176200001440000000200215100735320021113 0ustar liggesusers# sections with class .tabset are converted to tabsets

    Tabset

    Contents 1

    Contents 2

    pkgdown/tests/testthat/_snaps/build-reference.md0000644000176200001440000000112615100735314021564 0ustar liggesusers# parse failures include file name Code build_reference(pkg) Message -- Building function reference ------------------------------------------------- Writing `reference/index.html` Reading man/f.Rd Condition Error in `build_reference()`: ! Failed to parse Rd in 'f.Rd' Caused by error: ! Failed to parse tag "\\url{}". i Check for empty \url{} tags. # examples are reproducible by default, i.e. 'seed' is respected Code cat(examples) Output #> [1] 0.600760886 0.157208442 0.007399441 0.466393497 0.497777389 pkgdown/tests/testthat/_snaps/build-home-index.md0000644000176200001440000001114115100735313021660 0ustar liggesusers# messages about reading and writing Code build_home_index(pkg) Message Reading 'DESCRIPTION' Writing `index.html` Code build_home_index(pkg) Message Reading 'DESCRIPTION' # data_home() validates yaml metadata Code data_home_(home = 1) Condition Error in `data_home_()`: ! In _pkgdown.yml, home must be a list, not the number 1. Code data_home_(home = list(title = 1)) Condition Error in `data_home_()`: ! In _pkgdown.yml, home.title must be a string, not the number 1. Code data_home_(home = list(description = 1)) Condition Error in `data_home_()`: ! In _pkgdown.yml, home.description must be a string, not the number 1. Code data_home_(template = list(trailing_slash_redirect = 1)) Condition Error in `data_home_()`: ! In _pkgdown.yml, template.trailing_slash_redirect must be true or false, not the number 1. # data_home_sidebar() works by default Code cat(data_home_sidebar(pkg)) Output

    License

    • {{ License }}

    Developers

    • Jo Doe
      Author, maintainer

    Dev Status

    • placeholder
    ---

    Developers

    # data_home_sidebar() can be defined by a HTML file Code data_home_sidebar(pkg) Condition Error: ! In _pkgdown.yml, home.sidebar.html specifies a file that doesn't exist ('sidebar.html'). # data_home_sidebar() can get a custom markdown formatted component

    Fancy section

    • How cool is pkgdown?!

    # data_home_sidebar() can add a TOC

    Table of contents

    # data_home_sidebar() outputs informative error messages Code data_home_sidebar_(html = 1) Condition Error in `data_home_sidebar_()`: ! In _pkgdown.yml, home.sidebar.html must be a string, not the number 1. Code data_home_sidebar_(structure = 1) Condition Error in `data_home_sidebar_()`: ! In _pkgdown.yml, home.sidebar.structure must be a character vector, not the number 1. Code data_home_sidebar_(structure = "fancy") Condition Error in `data_home_sidebar_()`: ! In _pkgdown.yml, home.sidebar.components must have component "fancy". 1 missing component: "fancy". Code data_home_sidebar_(structure = c("fancy", "cool")) Condition Error in `data_home_sidebar_()`: ! In _pkgdown.yml, home.sidebar.components must have components "fancy" and "cool". 2 missing components: "fancy" and "cool". Code data_home_sidebar_(structure = "fancy", components = list(fancy = list(text = "bla"))) Condition Error in `data_home_sidebar_()`: ! In _pkgdown.yml, home.sidebar.components.fancy must have components "title" and "text". 1 missing component: "title". Code data_home_sidebar_(structure = "fancy", components = list(fancy = list())) Condition Error in `data_home_sidebar_()`: ! In _pkgdown.yml, home.sidebar.components.fancy must have components "title" and "text". 2 missing components: "title" and "text". # allow email in BugReports Code xpath_xml(html, ".//li/a") Output Report a bug Citing testpackage pkgdown/tests/testthat/_snaps/templates.md0000644000176200001440000000210715100735317020532 0ustar liggesusers# Invalid bootstrap version spec in template package Code local_pkgdown_site(meta = list(template = list(package = "templatepackage"))) Condition Error in `as_pkgdown()`: ! In _pkgdown.yml, must set only one of template.bootstrap and template.bslib.version. i Specified locally and in template package templatepackage. # Invalid bootstrap version spec in _pkgdown.yml Code local_pkgdown_site(meta = list(template = list(bootstrap = 4, bslib = list( version = 5)))) Condition Error in `as_pkgdown()`: ! In _pkgdown.yml, must set only one of template.bootstrap and template.bslib.version. # Warns when Bootstrap theme is specified in multiple locations Code get_bslib_theme(pkg) Condition Warning: Multiple Bootstrap preset themes were set. Using "flatly" from template.bslib.preset. x Found template.bslib.preset, template.bslib.bootswatch, template.bootswatch, and template.params.bootswatch. i Remove extraneous theme declarations to avoid this warning. Output [1] "flatly" pkgdown/tests/testthat/_snaps/development.md0000644000176200001440000000174715100735315021065 0ustar liggesusers# validates yaml Code data_development_(development = 1) Condition Error in `as_pkgdown()`: ! In _pkgdown.yml, development must be a list, not the number 1. Code data_development_(development = list(mode = 1)) Condition Error in `as_pkgdown()`: ! In _pkgdown.yml, development.mode must be a string, not the number 1. Code data_development_(development = list(mode = "foo")) Condition Error in `as_pkgdown()`: ! In _pkgdown.yml, development.mode must be one of auto, default, release, devel, or unreleased, not foo. Code data_development_(development = list(destination = 1)) Condition Error in `as_pkgdown()`: ! In _pkgdown.yml, development.destination must be a string, not the number 1. Code data_development_(development = list(version_label = 1)) Condition Error in `as_pkgdown()`: ! In _pkgdown.yml, development.version_label must be a string, not the number 1. pkgdown/tests/testthat/_snaps/build-favicons.md0000644000176200001440000000116515100735310021435 0ustar liggesusers# missing logo generates message Code expect_output(build_favicons(pkg), "Building favicons") Message -- Building favicons ----------------------------------------------------------- Condition Error in `build_favicons()`: ! Can't find package logo PNG or SVG to build favicons. i See `usethis::use_logo()` for more information. # existing logo generates message Code build_favicons(pkg) Message -- Building favicons ----------------------------------------------------------- Favicons already exist in 'pkgdown' i Set `overwrite = TRUE` to re-create. pkgdown/tests/testthat/_snaps/rcmdcheck/0000755000176200001440000000000015001744016020131 5ustar liggesuserspkgdown/tests/testthat/_snaps/rcmdcheck/build-article.md0000644000176200001440000000276315001744016023203 0ustar liggesusers# build_article yields useful error if R fails Code build_article("test", pkg) Message Reading vignettes/test.Rmd Condition Error in `build_article()`: ! Failed to render 'vignettes/test.Rmd'. x Quitting from test.Rmd:4-10 [unnamed-chunk-1] x ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ x x Error in `h()`: x ! Error! x --- x Backtrace: x ▆ x 1. └─global f() x 2. └─global g() x 3. └─global h() x ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Caused by error: ! Error! --- Code summary(expect_error(build_article("test", pkg))) Message Reading vignettes/test.Rmd Output Error in `build_article()`: ! Failed to render 'vignettes/test.Rmd'. x Quitting from test.Rmd:4-10 [unnamed-chunk-1] x ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ x x Error in `h()`: x ! Error! x --- x Backtrace: x ▆ x 1. └─global f() x 2. └─global g() x 3. └─global h() x ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Caused by error: ! Error! --- Backtrace: x 1. \-global f() 2. \-global g() 3. \-global h() pkgdown/tests/testthat/_snaps/rd-example.md0000644000176200001440000000170415100735316020573 0ustar liggesusers# @examplesIf Code expect_equal(strtrim(rd2ex(rd3), 40), strtrim(exp3, 40)) Condition Warning: @examplesIf condition "TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && TRUE && FALSE" is "FALSE" pkgdown/tests/testthat/_snaps/tweak-homepage.md0000644000176200001440000000137115100735317021434 0ustar liggesusers# can remove logo Code xpath_xml(html, ".//div") Output --- Code xpath_xml(html, ".//div") Output # can move badges to sidebar Code xpath_xml(html, ".//div") Output

    Dev status

    # remove badges even if no dev-status div Code html Output {html_document} [1] \n

    Title

    \n pkgdown/tests/testthat/_snaps/build-quarto-articles.md0000644000176200001440000000123515102501667022752 0ustar liggesusers# we find out if quarto styles change Code cat(data$includes$style) Output code{white-space: pre-wrap;} span.smallcaps{font-variant: small-caps;} div.columns{display: flex; gap: min(4vw, 1.5em);} div.column{flex: auto; overflow-x: auto;} div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;} ul.task-list{list-style: none;} ul.task-list li input[type="checkbox"] { width: 0.8em; margin: 0 0.8em 0.2em -1em; /* quarto-specific, see https://github.com/quarto-dev/quarto-cli/issues/4556 */ vertical-align: middle; } pkgdown/tests/testthat/_snaps/build-search-docs.md0000644000176200001440000000153415100735315022025 0ustar liggesusers# build_search_index() has expected structure Code str(build_search_index(pkg)) Output List of 1 $ :List of 8 ..$ path : chr "https://example.com/index.html" ..$ id : chr "my-package" ..$ dir : chr "" ..$ previous_headings: chr "" ..$ what : chr "A test package" ..$ title : chr "A test package" ..$ text : chr "pakage " ..$ code : chr "" # build sitemap only messages when it updates Code build_sitemap(pkg) Message -- Building sitemap ------------------------------------------------------------ Writing `sitemap.xml` Code build_sitemap(pkg) Message -- Building sitemap ------------------------------------------------------------ pkgdown/tests/testthat/_snaps/build-news.md0000644000176200001440000000435315100735313020606 0ustar liggesusers# data_news works as expected for h1 & h2 # A tibble: 2 x 3 version page anchor 1 1.0.0.9000 dev testpackage-1009000 2 1.0.0 1.0 testpackage-100 --- # A tibble: 2 x 3 version page anchor 1 1.0.0.9000 dev testpackage-1009000 2 1.0.0 1.0 testpackage-100 # multi-page news are rendered Code data_news(pkg)[c("version", "page", "anchor")] Output # A tibble: 4 x 3 version page anchor 1 2.0 2.0 testpackage-20 2 1.1 1.1 testpackage-11 3 1.0.1 1.0 testpackage-101 4 1.0.0 1.0 testpackage-100 --- Code build_news(pkg) Message -- Building news --------------------------------------------------------------- Writing `news/news-2.0.html` Writing `news/news-1.1.html` Writing `news/news-1.0.html` Writing `news/index.html` # news headings get class and release date
    ---

    CRAN release: 2020-01-01

    # clear error for bad hierarchy - bad nesting Code data_news(pkg) Condition Error: ! In NEWS.md, inconsistent use of section headings. i Top-level headings must be either all

    or all

    . i See `?pkgdown::build_news()` for more details. # clear error for bad hierarchy - h3 Code data_news(pkg) Condition Error: ! In NEWS.md, inconsistent use of section headings. i Top-level headings must be either all

    or all

    . i See `?pkgdown::build_news()` for more details. # news can contain footnotes Code x <- data_news(pkg) Condition Warning: Footnotes in NEWS.md are not currently supported # data_news warns if no headings found Code . <- data_news(pkg) Condition Warning: In NEWS.md, no version headings found i See `?pkgdown::build_news()` for expected structure. pkgdown/tests/testthat/_snaps/build-home-community.md0000644000176200001440000000042115100735311022572 0ustar liggesusers# handles CoC and SUPPORT if present pkgdown/tests/testthat/_snaps/rd-html.md0000644000176200001440000000426715100735317020114 0ustar liggesusers# converts Rd unicode shortcuts Code rd2html("``a -- b --- c''") Output [1] "“a – b — c”" # subsection generates h3 Code cli::cat_line(rd2html("\\subsection{A}{B}")) Output

    A

    B

    --- Code cli::cat_line(rd2html("\\subsection{A}{\n p1\n\n p2\n }")) Output

    A

    p1

    p2

    # nested subsection generates h4 Code cli::cat_line(rd2html("\\subsection{H3}{\\subsection{H4}{}}")) Output

    H3

    H4

    # Sexprs in file share environment Code rd2html("\\Sexpr{x}") Condition Error: ! object 'x' not found # bad specs throw errors Code rd2html("\\url{}") Condition Error: ! Failed to parse tag "\\url{}". i Check for empty \url{} tags. Code rd2html("\\url{a\nb}") Condition Error: ! Failed to parse tag "\\url{}". i This may be caused by a \url tag that spans a line break. Code rd2html("\\email{}") Condition Error: ! Failed to parse tag "\\email{}". i empty Code rd2html("\\linkS4class{}") Condition Error: ! Failed to parse tag "\\linkS4class{}". # \describe items can contain multiple paragraphs
    Label 1

    Contents 1

    Label 2

    Contents 2

    ---
    Label

    Paragraph 1

    Paragraph 2

    # can add ids to descriptions
    abc

    Contents 1

    xyz

    Contents 2

    # nested item with whitespace parsed correctly
    Label

    This text is indented in a way pkgdown doesn't like.

    pkgdown/tests/testthat/_snaps/markdown.md0000644000176200001440000000154715100735316020364 0ustar liggesusers# markdown_text_inline() works with inline markdown Code markdown_text_inline(pkg, "x\n\ny", error_path = "title") Condition Error: ! In _pkgdown.yml, title must be inline markdown. # validates math yaml Code config_math_rendering_(`math-rendering` = 1) Condition Error in `config_math_rendering_()`: ! In _pkgdown.yml, template.math-rendering must be a string, not the number 1. Code config_math_rendering_(`math-rendering` = "math") Condition Error in `config_math_rendering_()`: ! In _pkgdown.yml, template.math-rendering must be one of mathml, mathjax, and katex, not math. # preserves ANSI characters Code markdown_text(pkg, sprintf("prefer %s", cli::col_blue("a"))) Output {html_document} [1]

    prefer \u2029[34ma\u2029[39m

    pkgdown/tests/testthat/_snaps/build-articles.md0000644000176200001440000000636415100735311021442 0ustar liggesusers# validates articles yaml Code data_articles_index_(1) Condition Error in `data_articles_index_()`: ! In _pkgdown.yml, articles must be a list, not the number 1. Code data_articles_index_(list(1)) Condition Error in `data_articles_index_()`: ! In _pkgdown.yml, articles[1] must be a list, not the number 1. Code data_articles_index_(list(list())) Condition Error in `data_articles_index_()`: ! In _pkgdown.yml, articles[1] must have components "title" and "contents". 2 missing components: "title" and "contents". Code data_articles_index_(list(list(title = 1, contents = 1))) Condition Error in `data_articles_index_()`: ! In _pkgdown.yml, articles[1].title must be a string, not the number 1. Code data_articles_index_(list(list(title = "a\n\nb", contents = 1))) Condition Error in `data_articles_index_()`: ! In _pkgdown.yml, articles[1].title must be inline markdown. Code data_articles_index_(list(list(title = "a", contents = 1))) Condition Error in `data_articles_index_()`: ! In _pkgdown.yml, articles[1].contents[1] must be a string. i You might need to add '' around special YAML values like 'N' or 'off' # validates external-articles Code data_articles_(1) Condition Error in `data_articles_()`: ! In _pkgdown.yml, external-articles must be a list, not the number 1. Code data_articles_(list(1)) Condition Error in `data_articles_()`: ! In _pkgdown.yml, external-articles[1] must be a list, not the number 1. Code data_articles_(list(list(name = "x"))) Condition Error in `data_articles_()`: ! In _pkgdown.yml, external-articles[1] must have components "name", "title", "href", and "description". 3 missing components: "title", "href", and "description". Code data_articles_(list(list(name = 1, title = "x", href = "x", description = "x"))) Condition Error in `data_articles_()`: ! In _pkgdown.yml, external-articles[1].name must be a string, not the number 1. Code data_articles_(list(list(name = "x", title = 1, href = "x", description = "x"))) Condition Error in `data_articles_()`: ! In _pkgdown.yml, external-articles[1].title must be a string, not the number 1. Code data_articles_(list(list(name = "x", title = "x", href = 1, description = "x"))) Condition Error in `data_articles_()`: ! In _pkgdown.yml, external-articles[1].href must be a string, not the number 1. Code data_articles_(list(list(name = "x", title = "x", href = "x", description = 1))) Condition Error in `data_articles_()`: ! In _pkgdown.yml, external-articles[1].description must be a string, not the number 1. # articles in vignettes/articles/ are unnested into articles/ Code build_redirects(pkg) Message -- Building redirects ---------------------------------------------------------- Adding redirect from articles/articles/nested.html to articles/nested.html. # warns about articles missing from index Code . <- data_articles_index(pkg) Condition Error: ! In _pkgdown.yml, 1 vignette missing from index: "c". pkgdown/tests/testthat/_snaps/build-reference-index.md0000644000176200001440000001225615100735315022700 0ustar liggesusers# can generate three types of row Code data_reference_index(pkg) Output pagetitle: Package index rows: - title: A slug: a desc: ~ is_internal: no - subtitle: B slug: b desc: ~ is_internal: no - topics: - path: a.html title: A lifecycle: ~ aliases: a() icon: ~ - path: b.html title: B lifecycle: ~ aliases: b() icon: ~ - path: c.html title: C lifecycle: ~ aliases: c() icon: ~ - path: e.html title: E lifecycle: ~ aliases: e icon: ~ - path: help.html title: D lifecycle: ~ aliases: '`?`()' icon: ~ names: - a - b - c - e - '?' row_has_icons: no is_internal: no has_icons: no # warns if missing topics Code data_reference_index(pkg) Condition Error: ! In _pkgdown.yml, 3 topics missing from index: "c", "e", and "?". i Either add to the reference index, or use `@keywords internal` to drop from the index. # gives informative errors Code data_reference_index_(1) Condition Error in `config_pluck_reference()`: ! In _pkgdown.yml, reference must be a list, not the number 1. Code data_reference_index_(list(1)) Condition Error in `data_reference_index_()`: ! In _pkgdown.yml, reference[1] must be a list, not the number 1. Code data_reference_index_(list(list(title = 1))) Condition Error in `data_reference_index_()`: ! In _pkgdown.yml, reference[1].title must be a string, not the number 1. Code data_reference_index_(list(list(title = "a\n\nb"))) Condition Error in `data_reference_index_()`: ! In _pkgdown.yml, reference[1].title must be inline markdown. Code data_reference_index_(list(list(subtitle = 1))) Condition Error in `data_reference_index_()`: ! In _pkgdown.yml, reference[1].subtitle must be a string, not the number 1. Code data_reference_index_(list(list(subtitle = "a\n\nb"))) Condition Error in `data_reference_index_()`: ! In _pkgdown.yml, reference[1].subtitle must be inline markdown. Code data_reference_index_(list(list(title = "bla", contents = 1))) Condition Error in `data_reference_index_()`: ! In _pkgdown.yml, reference[1].contents[1] must be a string. i You might need to add '' around special YAML values like 'N' or 'off' Code data_reference_index_(list(list(title = "bla", contents = NULL))) Condition Error in `data_reference_index_()`: ! In _pkgdown.yml, reference[1].contents is empty. Code data_reference_index_(list(list(title = "bla", contents = list("a", NULL)))) Condition Error in `data_reference_index_()`: ! In _pkgdown.yml, reference[1].contents[2] is empty. Code data_reference_index_(list(list(title = "bla", contents = list()))) Condition Error in `data_reference_index_()`: ! In _pkgdown.yml, reference[1].contents is empty. Code data_reference_index_(list(list(title = "bla", contents = "notapackage::lala"))) Condition Error in `build_reference_index()`: ! The package "notapackage" is required as it's used in the reference index. Code data_reference_index_(list(list(title = "bla", contents = "rlang::lala"))) Condition Error in `build_reference_index()`: ! Could not find documentation for `rlang::lala()`. # can use a topic from another package Code data_reference_index(pkg) Output pagetitle: Package index rows: - title: bla slug: bla desc: ~ is_internal: no - topics: - path: https://rlang.r-lib.org/reference/is_installed.html title: Are packages installed in any of the libraries? (from rlang) lifecycle: ~ aliases: - is_installed() - check_installed() icon: ~ - path: https://rstudio.github.io/bslib/reference/bs_bundle.html title: Add low-level theming customizations (from bslib) lifecycle: ~ aliases: - bs_add_variables() - bs_add_rules() - bs_add_functions() - bs_add_mixins() - bs_bundle() icon: ~ names: - rlang::is_installed() - bslib::bs_add_rules row_has_icons: no is_internal: no has_icons: no # can use a selector name as a topic name Code data_reference_index(pkg) Output pagetitle: Package index rows: - title: bla slug: bla desc: ~ is_internal: no - topics: - path: matches.html title: matches lifecycle: ~ aliases: matches() icon: ~ - path: A.html title: A lifecycle: ~ aliases: A() icon: ~ names: - matches - A row_has_icons: no is_internal: no has_icons: no pkgdown/tests/testthat/_snaps/check.md0000644000176200001440000000457715100735315017624 0ustar liggesusers# sitrep complains about BS3 Code pkgdown_sitrep(pkg) Message -- Sitrep ---------------------------------------------------------------------- x Bootstrap 3 is deprecated; please switch to Bootstrap 5. i Learn more at . v URLs ok. v Favicons ok. v Open graph metadata ok. v Articles metadata ok. v Reference metadata ok. # sitrep reports all problems Code pkgdown_sitrep(pkg) Message -- Sitrep ---------------------------------------------------------------------- x URLs not ok. In DESCRIPTION, URL is missing package url (http://test.org). See details in `vignette(pkgdown::metadata)`. v Favicons ok. v Open graph metadata ok. v Articles metadata ok. x Reference metadata not ok. In _pkgdown.yml, 1 topic missing from index: "?". Either add to the reference index, or use `@keywords internal` to drop from the index. # checks fails on first problem Code check_pkgdown(pkg) Condition Error in `check_pkgdown()`: ! In DESCRIPTION, URL is missing package url (http://test.org). i See details in `vignette(pkgdown::metadata)`. # both inform if everything is ok Code pkgdown_sitrep(pkg) Message -- Sitrep ---------------------------------------------------------------------- v URLs ok. v Favicons ok. v Open graph metadata ok. v Articles metadata ok. v Reference metadata ok. Code check_pkgdown(pkg) Message v No problems found. # check_urls reports problems Code check_urls(pkg) Condition Error: ! In _pkgdown.yml, url is missing. i See details in `vignette(pkgdown::metadata)`. --- Code check_urls(pkg) Condition Error: ! In DESCRIPTION, URL is missing package url (https://testpackage.r-lib.org). i See details in `vignette(pkgdown::metadata)`. # check_favicons reports problems Code check_favicons(pkg) Condition Error in `check_favicons()`: ! Found package logo but not favicons. i Do you need to run `build_favicons()`? --- Code check_favicons(pkg) Condition Error in `check_favicons()`: ! Package logo is newer than favicons. i Do you need to rerun `build_favicons()`? pkgdown/tests/testthat/test-templates.R0000644000176200001440000001364114770274305020041 0ustar liggesuserstest_that("template_candidates look for specific first", { expect_equal( path_file(template_candidates("content", "article")), c("content-article.html", "content.html") ) }) test_that("template_candidates look in template dir then pkgdown", { pkg_dir <- withr::local_tempdir() template_dir <- withr::local_tempdir() pkg <- list( src_path = pkg_dir, meta = list(template = list(path = template_dir)), bs_version = 3 ) # ensure that templates_dir(pkg) returns the specific template path expect_equal(templates_dir(pkg), path(template_dir)) paths <- template_candidates("content", "article", pkg = pkg) dirs <- unique(path_dir(paths)) expect_equal( dirs, c( # search for candidates... path(pkg_dir, "pkgdown", "templates"), # first in local templates path(template_dir), # second in global template path path_pkgdown("BS3", "templates") # finally in pkgdown templates ) ) }) test_that("look for templates_dir in right places", { dir <- withr::local_tempdir() pkg <- list(src_path = dir, meta = list(template = list())) # Look in site templates expect_equal(templates_dir(pkg), path(dir, "pkgdown", "templates")) # Look in specified directory pkg$meta$template$path <- path(withr::local_tempdir()) expect_equal(templates_dir(pkg), pkg$meta$template$path) }) test_that("find templates in local pkgdown first", { pkg <- test_path("assets", "templates-local") # local template used over default pkgdown template expect_equal( find_template("content", "article", pkg = pkg), path_abs(path(pkg, "pkgdown", "templates", "content-article.html")) ) expect_equal( find_template("footer", "article", pkg = pkg), path_abs(path(pkg, "pkgdown", "templates", "footer-article.html")) ) # pkgdown template used (no local template) expect_equal( find_template("content", "tutorial", pkg = pkg), path_pkgdown("BS3", "templates", "content-tutorial.html") ) expect_equal( find_template("footer", "ignored", pkg = pkg), path_pkgdown("BS3", "templates", "footer.html") ) }) # Expected contents ------------------------------------------------------- test_that("BS5 templates have main + aside", { names <- dir_ls(path_pkgdown("BS5", "templates"), regexp = "content-") names <- path_ext_remove(path_file(names)) names <- gsub("content-", "", names) templates <- lapply( names, read_template_html, type = "content", pkg = list(bs_version = 5) ) for (i in seq_along(templates)) { template <- templates[[i]] name <- names[[i]] expect_equal(xpath_length(template, ".//div/main"), 1, info = name) expect_equal(xpath_attr(template, ".//div/main", "id"), "main", info = name) expect_equal(xpath_length(template, ".//div/aside"), 1, info = name) expect_equal( xpath_attr(template, ".//div/aside", "class"), "col-md-3", info = name ) } }) # Bootstrap version resolution -------------------------------------------- test_that("Bootstrap version in template package under `template.bootstrap`", { path_template_package <- local_pkgdown_template_pkg( meta = list(template = list(bootstrap = 5)) ) pkg <- local_pkgdown_site( meta = list(template = list(package = "templatepackage")) ) expect_equal(pkg$bs_version, 5) }) test_that("Bootstrap version in template package under `template.bslib.version`", { path_template_package <- local_pkgdown_template_pkg( meta = list(template = list(bslib = list(version = 5))) ) pkg <- local_pkgdown_site( meta = list(template = list(package = "templatepackage")) ) expect_equal(pkg$bs_version, 5) }) test_that("Invalid bootstrap version spec in template package", { path_template_package <- local_pkgdown_template_pkg( meta = list(template = list(bootstrap = 4, bslib = list(version = 5))) ) expect_snapshot( error = TRUE, local_pkgdown_site( meta = list(template = list(package = "templatepackage")) ) ) }) test_that("Invalid bootstrap version spec in _pkgdown.yml", { expect_snapshot( error = TRUE, local_pkgdown_site( meta = list( template = list( bootstrap = 4, bslib = list(version = 5) ) ) ) ) }) test_that("Valid local Bootstrap version masks invalid template package", { path_template_package <- local_pkgdown_template_pkg( meta = list(template = list(bootstrap = 4, bslib = list(version = 5))) ) expect_no_error( local_pkgdown_site( meta = list( template = list( package = "templatepackage", bootstrap = 5 ) ) ) ) }) # Bootstrap theme resolution ---------------------------------------------- test_that("Finds Bootstrap theme in all the places", { pkg_sketchy <- local_pkgdown_site( meta = list(template = list(bslib = list(preset = "sketchy", version = 5))) ) pkg_cosmo <- local_pkgdown_site( meta = list(template = list(bootstrap = 5, bootswatch = "cosmo")) ) pkg_yeti <- local_pkgdown_site( meta = list( template = list(bootstrap = 5, params = list(bootswatch = "yeti")) ) ) expect_equal(get_bslib_theme(pkg_sketchy), "sketchy") expect_equal(get_bslib_theme(pkg_cosmo), "cosmo") expect_equal(get_bslib_theme(pkg_yeti), "yeti") }) test_that("Warns when Bootstrap theme is specified in multiple locations", { pkg <- local_pkgdown_site( meta = list( template = list( bootstrap = 5, bootswatch = "cerulean", bslib = list(preset = "flatly", bootswatch = "lux"), params = list(bootswatch = "darkly") ) ) ) expect_snapshot(get_bslib_theme(pkg)) }) test_that("Doesn't warn when the same Bootstrap theme is specified in multiple locations", { pkg <- local_pkgdown_site( meta = list( template = list( bootstrap = 5, bootswatch = "cerulean", bslib = list(preset = "cerulean") ) ) ) expect_equal(expect_silent(get_bslib_theme(pkg)), "cerulean") }) pkgdown/tests/testthat/test-repo.R0000644000176200001440000001541314770274305017007 0ustar liggesusers# repo_auto_link --------------------------------------------------------- test_that("authors are automatically linked", { pkg <- list(repo = repo_meta(user = "TEST/")) # email addresses shouldn't get linked expect_equal(repo_auto_link(pkg, "x@y.com"), "x@y.com") # must have leading whitespace or open parens expect_equal(repo_auto_link(pkg, "@y"), "@y") expect_equal(repo_auto_link(pkg, " @y"), " @y") expect_equal(repo_auto_link(pkg, "(@y)"), "(@y)") expect_equal( repo_auto_link(pkg, "

    @y some other text.

    "), "

    @y some other text.

    " ) }) test_that("issues are automatically linked", { pkg <- list(repo = repo_meta(issue = "TEST/")) expect_equal(repo_auto_link(pkg, "(#123"), "(#123") expect_equal(repo_auto_link(pkg, "in #123"), "in #123") expect_equal( repo_auto_link(pkg, "

    #123 some other text.

    "), "

    #123 some other text.

    " ) expect_equal( repo_auto_link(pkg, "

    #123

    "), "

    #123

    " ) }) test_that("already linked issues aren't re-linked", { pkg <- list(repo = repo_meta(issue = "TEST/")) expect_equal( repo_auto_link(pkg, "

    #123

    "), "

    #123

    " ) }) test_that("URLs with hash (#) are preserved", { pkg <- list(repo = repo_meta(issue = "TEST/")) expect_equal( repo_auto_link(pkg, "[example 5.4](https:/my.site#5-4-ad)"), "[example 5.4](https:/my.site#5-4-ad)" ) }) test_that("Jira issues are automatically linked", { pkg <- list(repo = repo_meta(issue = "TEST/")) pkg$repo$jira_projects <- c("JIRA", "OTHER") expect_equal( repo_auto_link(pkg, "JIRA-123"), "JIRA-123" ) expect_equal( repo_auto_link(pkg, "OTHER-4321"), "OTHER-4321" ) # but only the jira projects specified are caught expect_equal(repo_auto_link(pkg, "NOPE-123"), "NOPE-123") }) # repo_source ------------------------------------------------------------- test_that("repo_source() truncates automatically", { withr::local_envvar(GITHUB_HEAD_REF = "HEAD") pkg <- list(repo = repo_meta_gh_like("https://github.com/r-lib/pkgdown")) expect_snapshot({ cat(repo_source(pkg, character())) cat(repo_source(pkg, "a")) cat(repo_source(pkg, letters[1:10])) }) }) test_that("repo_source() is robust to trailing slash", { pkg <- list(repo = repo_meta_gh_like("https://github.com/r-lib/pkgdown")) meta <- function(x) { list(repo = list(url = list(source = x))) } source <- "Source: a" expect_equal(repo_source(meta("http://example.com"), "a"), source) expect_equal(repo_source(meta("http://example.com/"), "a"), source) }) test_that("repo_source() uses the branch setting in meta", { pkg <- local_pkgdown_site( meta = list(repo = list(branch = "main")), desc = list(URL = "https://github.com/r-lib/pkgdown") ) expect_match( repo_source(pkg, "a"), "https://github.com/r-lib/pkgdown/blob/main/a" ) }) # package_repo ------------------------------------------------------------ test_that("can find github from BugReports or URL", { withr::local_envvar(GITHUB_HEAD_REF = "HEAD") expected <- repo_meta_gh_like("https://github.com/r-lib/pkgdown") pkg <- local_pkgdown_site( desc = list( URL = "https://github.com/r-lib/pkgdown" ) ) expect_equal(package_repo(pkg), expected) # BugReports beats URL pkg <- local_pkgdown_site( desc = list( URL = "https://github.com/r-lib/BLAHBLAH", BugReports = "https://github.com/r-lib/pkgdown/issues" ) ) expect_equal(package_repo(pkg), expected) # URL can be in any position pkg <- local_pkgdown_site( desc = list( URL = "https://pkgdown.r-lib.org, https://github.com/r-lib/pkgdown" ) ) expect_equal(package_repo(pkg), expected) }) test_that("can find gitlab url", { withr::local_envvar(GITHUB_HEAD_REF = "HEAD") url <- "https://gitlab.com/msberends/AMR" pkg <- local_pkgdown_site(desc = list(URL = url)) expect_equal(package_repo(pkg), repo_meta_gh_like(url)) }) test_that("can find codeberg url", { withr::local_envvar(GITHUB_HEAD_REF = "HEAD") url <- "https://codeberg.org/msberends/AMR" pkg <- local_pkgdown_site(desc = list(URL = url)) expect_equal(package_repo(pkg), repo_meta_gh_like(url)) }) test_that("uses GITHUB env vars if set", { withr::local_envvar(GITHUB_HEAD_REF = NA, GITHUB_REF_NAME = "abc") expect_equal( repo_meta_gh_like("https://github.com/r-lib/pkgdown")$url$source, "https://github.com/r-lib/pkgdown/blob/abc/" ) withr::local_envvar(GITHUB_HEAD_REF = "xyz") expect_equal( repo_meta_gh_like("https://github.com/r-lib/pkgdown")$url$source, "https://github.com/r-lib/pkgdown/blob/xyz/" ) }) test_that("GitLab subgroups are properly parsed", { issue_url <- function(...) { pkg <- local_pkgdown_site(desc = list(...)) pkg$repo$url$issue } base <- "https://gitlab.com/salim_b/r/pkgs/pal" expected <- paste0(base, "/-/issues/") expect_identical(issue_url(URL = base), expected) expect_identical(issue_url(URL = paste0(base, "/")), expected) expect_identical(issue_url(BugReports = paste0(base, "/issues")), expected) expect_identical(issue_url(BugReports = paste0(base, "/issues/")), expected) expect_identical(issue_url(BugReports = paste0(base, "/-/issues")), expected) expect_identical(issue_url(BugReports = paste0(base, "/-/issues/")), expected) }) test_that("can find github enterprise url", { withr::local_envvar(GITHUB_HEAD_REF = "HEAD") url <- "https://github.acme.com/roadrunner/speed" pkg <- local_pkgdown_site(desc = list(BugReports = url)) expect_equal(package_repo(pkg), repo_meta_gh_like(url)) }) test_that("meta overrides autodetection", { pkg <- local_pkgdown_site( meta = list(repo = list(url = list(home = "http://one.com"))), desc = list(URL = "http://two.com") ) expect_equal(package_repo(pkg)$url$home, "http://one.com") }) test_that("returns NULL if no urls found", { pkg <- local_pkgdown_site(desc = list(URL = "https://pkgdown.r-lib.org")) expect_null(package_repo(pkg)) }) test_that("repo_type detects repo type", { repo_type2 <- function(url) { repo_type(list(repo = list(url = list(home = url)))) } expect_equal(repo_type2("https://github.com/r-lib/pkgdown"), "github") expect_equal(repo_type2("https://github.r-lib.com/pkgdown"), "github") expect_equal(repo_type2("https://gitlab.com/r-lib/pkgdown"), "gitlab") expect_equal(repo_type2("https://gitlab.r-lib.com/pkgdown"), "gitlab") expect_equal(repo_type2("https://codeberg.org/r-lib/pkgdown"), "codeberg") expect_equal(repo_type2(NULL), "other") }) pkgdown/tests/testthat/test-build-reference.R0000644000176200001440000001111714770274305021072 0ustar liggesuserstest_that("parse failures include file name", { pkg <- local_pkgdown_site(test_path("assets/reference-fail")) expect_snapshot(build_reference(pkg), error = TRUE) }) test_that("examples_env runs pre and post code", { dst_path <- withr::local_tempdir() dir_create(path(dst_path, "reference")) pkg <- list( package = "test", src_path = test_path("assets/reference-pre-post"), dst_path = dst_path ) env <- local(examples_env(pkg)) expect_equal(env$a, 2) }) test_that("examples_env sets width", { pkg <- local_pkgdown_site( test_path("assets/reference"), list(code = list(width = 50)) ) dir_create(path(pkg$dst_path, "reference")) examples_env(pkg) expect_equal(getOption("width"), 50) }) test_that("test usage ok on rendered page", { pkg <- local_pkgdown_site( test_path("assets/reference"), list(template = list(bootstrap = 3)) ) suppressMessages(init_site(pkg)) suppressMessages(build_reference(pkg, topics = "c")) html <- xml2::read_html(path(pkg$dst_path, "reference", "c.html")) expect_equal(xpath_text(html, "//div[@id='ref-usage']", trim = TRUE), "c()") clean_site(pkg, quiet = TRUE) pkg <- local_pkgdown_site(test_path("assets/reference")) suppressMessages(init_site(pkg)) suppressMessages(build_reference(pkg, topics = "c")) html <- xml2::read_html(path(pkg$dst_path, "reference", "c.html")) # tweak_anchors() moves id into

    expect_equal( xpath_text(html, "//div[h2[@id='ref-usage']]/div", trim = TRUE), "c()" ) }) test_that(".Rd without usage doesn't get Usage section", { pkg <- local_pkgdown_site( test_path("assets/reference"), list(template = list(bootstrap = 3)) ) suppressMessages(init_site(pkg)) suppressMessages(build_reference(pkg, topics = "e")) html <- xml2::read_html(path(pkg$dst_path, "reference", "e.html")) expect_equal(xpath_length(html, "//div[@id='ref-usage']"), 0) clean_site(pkg, quiet = TRUE) pkg <- local_pkgdown_site(test_path("assets/reference")) suppressMessages(init_site(pkg)) suppressMessages(build_reference(pkg, topics = "e")) html <- xml2::read_html(path(pkg$dst_path, "reference", "e.html")) # tweak_anchors() moves id into

    expect_equal(xpath_length(html, "//div[h2[@id='ref-usage']]"), 0) }) test_that("pkgdown html dependencies are suppressed from examples in references", { pkg <- local_pkgdown_site(test_path("assets/reference-html-dep")) suppressMessages(init_site(pkg)) suppressMessages(build_reference(pkg, topics = "a")) html <- xml2::read_html(path(pkg$dst_path, "reference", "a.html")) # jquery is only loaded once, even though it's included by an example expect_equal( xpath_length(html, ".//script[(@src and contains(@src, '/jquery'))]"), 1 ) # same for bootstrap js and css str_subset_bootstrap <- function(x) { bs_rgx <- "bootstrap-[\\d.]+" # ex: bootstrap-5.1.0 not bootstrap-toc, grep(bs_rgx, x, value = TRUE, perl = TRUE) } bs_js_src <- str_subset_bootstrap( xpath_attr( html, ".//script[(@src and contains(@src, '/bootstrap'))]", "src" ) ) expect_length(bs_js_src, 1) bs_css_href <- str_subset_bootstrap( xpath_attr( html, ".//link[(@href and contains(@href, '/bootstrap'))]", "href" ) ) expect_length(bs_css_href, 1) }) test_that("examples are reproducible by default, i.e. 'seed' is respected", { pkg <- local_pkgdown_site(test_path("assets/reference")) suppressMessages(init_site(pkg)) suppressMessages(build_reference(pkg, topics = "f")) html <- xml2::read_html(path(pkg$dst_path, "reference", "f.html")) examples <- xpath_text(html, ".//code//*[contains(@class, 'r-out')]") expect_snapshot(cat(examples)) }) test_that("arguments get individual ids", { pkg <- local_pkgdown_site(test_path("assets/reference")) suppressMessages(init_site(pkg)) suppressMessages(build_reference(pkg, topics = "a")) html <- xml2::read_html(path(pkg$dst_path, "reference", "a.html")) expect_equal(xpath_attr(html, "//dt", "id"), c("arg-a", "arg-b", "arg-c")) }) test_that("title and page title escapes html", { pkg <- local_pkgdown_site(test_path("assets/reference")) suppressMessages(init_site(pkg)) suppressMessages(build_reference(pkg, topics = "g")) html <- xml2::read_html(path(pkg$dst_path, "reference", "g.html")) expect_equal( xpath_text(html, "//title", trim = TRUE), "g <-> h — g • testpackage" ) expect_equal(xpath_text(html, "//h1", trim = TRUE), "g <-> h") }) test_that("get_rdname handles edge cases", { expect_equal(get_rdname(list(file_in = "foo..Rd")), "foo.") expect_equal(get_rdname(list(file_in = "foo.rd")), "foo") }) pkgdown/tests/testthat/test-check-built.R0000644000176200001440000000104014634573316020226 0ustar liggesuserstest_that("check images in readme", { pkg <- local_pkgdown_site() pkg <- pkg_add_file(pkg, "README.md", "![foo](vignettes/kitten.jpg)") suppressMessages(build_home_index(pkg)) # no image, so should warn expect_snapshot(check_built_site(pkg)) # create and build vignette that uses image, so no warning pkg <- pkg_add_file(pkg, "vignettes/kitten.Rmd", "![foo](kitten.jpg)") pkg <- pkg_add_kitten(pkg, "vignettes") suppressMessages(build_article("kitten", pkg)) suppressMessages(expect_no_warning(check_built_site(pkg))) }) pkgdown/tests/testthat/test-build-footer.R0000644000176200001440000000410114770274305020425 0ustar liggesuserstest_that("works by default", { pkg <- structure( list( desc = desc::desc( text = "Authors@R: person('First', 'Last', role = 'cre')" ), src_path = tempdir() ), class = "pkgdown" ) footer <- data_footer(pkg) footer$right <- gsub( packageVersion("pkgdown"), "{version}", footer$right, fixed = TRUE ) expect_snapshot_output(footer) }) test_that("includes package component", { pkg <- structure( list( package = "noodlr", desc = desc::desc( text = "Authors@R: person('First', 'Last', role = 'cre')" ), src_path = tempdir(), meta = list( footer = list( structure = list(left = "package") ) ) ), class = "pkgdown" ) expect_equal(data_footer(pkg)$left, "

    noodlr

    ") }) test_that("can use custom components", { pkg <- structure( list( desc = desc::desc(text = "Authors@R: person('a', 'b', roles = 'cre')"), src_path = tempdir(), meta = list( footer = list( structure = list(left = "test"), components = list(test = "_test_") ) ) ), class = "pkgdown" ) expect_equal(data_footer(pkg)$left, "

    test

    ") }) test_that("multiple components are pasted together", { pkg <- structure( list( desc = desc::desc(text = "Authors@R: person('a', 'b', roles = 'cre')"), src_path = tempdir(), meta = list( footer = list( structure = list(left = c("a", "b")), components = list(a = "a", b = "b") ) ) ), class = "pkgdown" ) expect_equal(data_footer(pkg)$left, "

    a b

    ") }) test_that("validates meta components", { data_footer_ <- function(...) { pkg <- local_pkgdown_site(meta = list(...)) data_footer(pkg) } expect_snapshot(error = TRUE, { data_footer_(footer = 1) data_footer_(footer = list(structure = 1)) data_footer_(footer = list(components = 1)) data_footer_(authors = list(footer = list(roles = 1))) data_footer_(authors = list(footer = list(text = 1))) }) }) pkgdown/tests/testthat/test-config.R0000644000176200001440000000261114770274305017303 0ustar liggesuserstest_that("config_pluck_character coerces empty values to character", { pkg <- local_pkgdown_site(meta = list(x = NULL, y = list())) expect_equal(config_pluck_character(pkg, "x"), character()) expect_equal(config_pluck_character(pkg, "y"), character()) expect_equal(config_pluck_character(pkg, "z"), character()) }) test_that("config_pluck_character generates informative error", { pkg <- local_pkgdown_site(meta = list(x = 1)) expect_snapshot(config_pluck_character(pkg, "x"), error = TRUE) }) test_that("config_pluck_string generates informative error", { pkg <- local_pkgdown_site(meta = list(x = 1)) expect_snapshot(config_pluck_string(pkg, "x"), error = TRUE) }) # checkers -------------------------------------------------------------------- test_that("config_check_list() returns list if ok", { x <- list(x = 1, y = 2) expect_equal(config_check_list(x), x) expect_equal(config_check_list(x, has_names = "x"), x) expect_equal(config_check_list(x, has_names = c("x", "y")), x) }) test_that("config_check_list gives informative errors", { # Avoid showing unneeded call details in snapshot pkg <- local_pkgdown_site() config_check_list_ <- function(...) { config_check_list(..., error_pkg = pkg, error_path = "path") } expect_snapshot(error = TRUE, { config_check_list_(1, has_names = "x") config_check_list_(list(x = 1, y = 1), has_names = c("y", "z")) }) }) pkgdown/tests/testthat/test-build-home-license.R0000644000176200001440000000106614770274305021506 0ustar liggesuserstest_that("link_license matchs exactly", { # Shouldn't match first GPL-2 expect_equal( autolink_license("LGPL-2"), "LGPL-2" ) expect_equal( autolink_license("MPL-2.0"), "MPL-2.0" ) }) test_that("link_license matches LICENSE", { expect_equal( autolink_license("LICENSE"), "LICENSE" ) expect_equal( autolink_license("LICENCE"), "LICENCE" ) }) pkgdown/tests/testthat/test-build-articles.R0000644000176200001440000001003014770274305020733 0ustar liggesuserstest_that("can recognise intro variants", { expect_true(article_is_intro("package", "package")) expect_true(article_is_intro("articles/package", "package")) expect_true(article_is_intro("pack-age", "pack.age")) expect_true(article_is_intro("articles/pack-age", "pack.age")) }) test_that("validates articles yaml", { data_articles_index_ <- function(x) { pkg <- local_pkgdown_site(meta = list(articles = x)) data_articles_index(pkg) } expect_snapshot(error = TRUE, { data_articles_index_(1) data_articles_index_(list(1)) data_articles_index_(list(list())) data_articles_index_(list(list(title = 1, contents = 1))) data_articles_index_(list(list(title = "a\n\nb", contents = 1))) data_articles_index_(list(list(title = "a", contents = 1))) }) }) test_that("validates external-articles", { data_articles_ <- function(x) { pkg <- local_pkgdown_site(meta = list(`external-articles` = x)) data_articles(pkg) } expect_snapshot(error = TRUE, { data_articles_(1) data_articles_(list(1)) data_articles_(list(list(name = "x"))) data_articles_(list(list( name = 1, title = "x", href = "x", description = "x" ))) data_articles_(list(list( name = "x", title = 1, href = "x", description = "x" ))) data_articles_(list(list( name = "x", title = "x", href = 1, description = "x" ))) data_articles_(list(list( name = "x", title = "x", href = "x", description = 1 ))) }) }) test_that("data_articles includes external articles", { pkg <- local_pkgdown_site( meta = list( `external-articles` = list( list(name = "c", title = "c", href = "c", description = "*c*") ) ) ) pkg <- pkg_add_file(pkg, "vignettes/a.Rmd") pkg <- pkg_add_file(pkg, "vignettes/b.Rmd") articles <- data_articles(pkg) expect_equal(articles$name, c("a", "b", "c")) expect_equal(articles$internal, rep(FALSE, 3)) expect_equal(articles$description, list(NULL, NULL, "

    c

    ")) }) test_that("articles in vignettes/articles/ are unnested into articles/", { # weird path differences that I don't have the energy to dig into skip_on_cran() pkg <- local_pkgdown_site(meta = list(url = "https://example.com")) pkg <- pkg_add_file(pkg, "vignettes/articles/nested.Rmd") nested <- pkg$vignettes[pkg$vignettes$name == "articles/nested", ] expect_equal(nested$file_out, "articles/nested.html") # Check automatic redirect from articles/articles/foo.html -> articles/foo.html expect_snapshot(build_redirects(pkg)) }) test_that("warns about articles missing from index", { pkg <- local_pkgdown_site( meta = list( articles = list( list(title = "External", contents = c("a", "b")) ) ) ) pkg <- pkg_add_file(pkg, "vignettes/a.Rmd") pkg <- pkg_add_file(pkg, "vignettes/b.Rmd") pkg <- pkg_add_file(pkg, "vignettes/c.Rmd") expect_snapshot(. <- data_articles_index(pkg), error = TRUE) }) test_that("internal articles aren't included and don't trigger warning", { pkg <- local_pkgdown_site( meta = list( articles = list( list(title = "External", contents = c("a", "b")), list(title = "internal", contents = "c") ) ) ) pkg <- pkg_add_file(pkg, "vignettes/a.Rmd") pkg <- pkg_add_file(pkg, "vignettes/b.Rmd") pkg <- pkg_add_file(pkg, "vignettes/c.Rmd") expect_no_error(index <- data_articles_index(pkg)) expect_length(index$sections, 1) expect_length(index$sections[[1]]$contents, 2) }) test_that("default template includes all articles", { pkg <- local_pkgdown_site() pkg <- pkg_add_file(pkg, "vignettes/a.Rmd") expect_equal(default_articles_index(pkg)[[1]]$contents, "a") }) test_that("check doesn't include getting started vignette", { pkg <- local_pkgdown_site( meta = list( articles = list(list(title = "Vignettes", contents = "a")) ) ) pkg <- pkg_add_file(pkg, "vignettes/a.Rmd") pkg <- pkg_add_file(pkg, "vignettes/testpackage.Rmd") expect_no_error(data_articles_index(pkg)) }) pkgdown/tests/testthat/test-development.R0000644000176200001440000000353714770274305020370 0ustar liggesuserstest_that("empty yaml gets correct defaults", { pkg <- local_pkgdown_site() expect_equal(pkg$development$mode, "default") expect_equal(pkg$development$in_dev, FALSE) expect_equal(pkg$development$version_label, "muted") }) test_that("mode = auto uses version", { pkg <- local_pkgdown_site( desc = list(Version = "0.0.9000"), meta = list(development = list(mode = "auto")) ) expect_equal(pkg$development$mode, "devel") expect_equal(pkg$development$in_dev, TRUE) expect_equal(pkg$development$version_label, "danger") }) test_that("mode overrides version", { pkg <- local_pkgdown_site( desc = list(Version = "0.0.9000"), meta = list(development = list(mode = "release")) ) expect_equal(pkg$development$mode, "release") }) test_that("env var overrides mode", { withr::local_envvar("PKGDOWN_DEV_MODE" = "devel") pkg <- local_pkgdown_site( meta = list(development = list(mode = "release")) ) expect_equal(pkg$development$mode, "devel") }) test_that("dev_mode recognises basic version structure", { expect_equal(dev_mode_auto("0.0.0.9000"), "unreleased") expect_equal(dev_mode_auto("0.0.1"), "release") expect_equal(dev_mode_auto("0.1"), "release") expect_equal(dev_mode_auto("0.1.0"), "release") expect_equal(dev_mode_auto("0.1.9000"), "devel") expect_equal(dev_mode_auto("1.0"), "release") expect_equal(dev_mode_auto("1.0.0"), "release") expect_equal(dev_mode_auto("1.0.0.9000"), "devel") }) test_that("validates yaml", { data_development_ <- function(...) { local_pkgdown_site(meta = list(...)) } expect_snapshot(error = TRUE, { data_development_(development = 1) data_development_(development = list(mode = 1)) data_development_(development = list(mode = "foo")) data_development_(development = list(destination = 1)) data_development_(development = list(version_label = 1)) }) }) pkgdown/tests/testthat/test-build-news.R0000644000176200001440000001630014770274305020107 0ustar liggesuserstest_that("data_news works as expected for h1 & h2", { skip_if_no_pandoc() # fmt: skip lines_h1 <- c( "# testpackage 1.0.0.9000", "", "* bullet (#222 @someone)", "", "# testpackage 1.0.0", "", "## sub-heading", "", "* first thing (#111 @githubuser)", "", "* second thing", "" ) lines_h2 <- gsub("^#", "##", lines_h1) pkg <- local_pkgdown_site() pkg <- pkg_add_file(pkg, "NEWS.md", lines_h1) expect_snapshot_output(data_news(pkg)[c("version", "page", "anchor")]) pkg <- pkg_add_file(pkg, "NEWS.md", lines_h2) expect_snapshot_output(data_news(pkg)[c("version", "page", "anchor")]) }) test_that("news is syntax highlighted once", { pkg <- local_pkgdown_site() pkg <- pkg_add_file( pkg, "NEWS.md", c( "# testpackage 1.0.0.9000", "```r", "x <- 1", "```" ) ) suppressMessages(build_news(pkg, preview = FALSE)) html <- xml2::read_html(path(pkg$dst_path, "news", "index.html")) expect_equal(xpath_text(html, "//code"), "x <- 1") }) test_that("multi-page news are rendered", { skip_if_no_pandoc() pkg <- local_pkgdown_site(meta = list(news = list(one_page = FALSE))) # fmt: skip pkg <- pkg_add_file(pkg, "NEWS.md", c( "# testpackage 2.0", "", "* bullet (#222 @someone)", "", "# testpackage 1.1", "", "* bullet (#222 @someone)", "", "# testpackage 1.0.1", "", "* bullet (#222 @someone)", "", "# testpackage 1.0.0", "", "## sub-heading", "", "* first thing (#111 @githubuser)", "", "* second thing" )) expect_snapshot(data_news(pkg)[c("version", "page", "anchor")]) expect_snapshot(build_news(pkg)) # test that index links are correct lines <- xml2::read_html(path(pkg$dst_path, "news", "index.html")) expect_equal( xpath_attr(lines, "//main//a", "href"), c("news-2.0.html", "news-1.1.html", "news-1.0.html") ) expect_equal( xpath_text(lines, "//main//a"), c("Version 2.0", "Version 1.1", "Version 1.0") ) # test single page structure lines <- xml2::read_html(path(pkg$dst_path, "news", "news-1.0.html")) expect_equal(xpath_text(lines, ".//h1"), "Version 1.0") expect_equal( xpath_text(lines, ".//main//h2"), c("testpackage 1.0.0", "testpackage 1.0.1") ) }) test_that("github links are added to news items", { skip_if_no_pandoc() pkg <- local_pkgdown_site( meta = list( repo = list( url = list( home = "https://github.com/r-lib/pkgdown", user = "https://github.com/", issue = "https://github.com/r-lib/pkgdown/issues/" ) ) ) ) # fmt: skip pkg <- pkg_add_file(pkg, "NEWS.md", c( "# testpackage 0.1.0", "", "## Major changes", "", "- Bug fixes (@hadley, #100)", "", "- Merges (@josue-rodriguez)" )) news_tbl <- data_news(pkg) html <- xml2::read_xml(news_tbl$html) expect_equal( xpath_attr(html, ".//a", "href"), c( "https://github.com/hadley", "https://github.com/r-lib/pkgdown/issues/100", "https://github.com/josue-rodriguez" ) ) }) test_that("pkg_timeline fails cleanly for unknown package", { skip_on_cran() expect_null(pkg_timeline("__XYZ__")) }) test_that("pkg_timeline works for package that have been archived", { skip_on_cran() expect_no_error(pkg_timeline("PF")) }) test_that("correct timeline for first ggplot2 releases", { skip_on_cran() timeline <- pkg_timeline("ggplot2")[1:3, ] expected <- data.frame( version = c("0.5", "0.5.1", "0.5.2"), date = as.Date(c("2007-06-01", "2007-06-09", "2007-06-18")) ) expect_equal(timeline, expected) }) # news_title and version_page ----------------------------------------------- test_that("can recognise common forms of title", { # Variants in beginning version <- news_version( c( "foo 1.3.0", "foo v1.3.0", "foo 1.3.0", "VERSION 1.3.0", "changes in 1.3.0", "changes in foo version 1.3.0" ), "foo" ) expect_equal(version, rep("1.3.0", length(version))) # Variants in version spec expect_equal( news_version(c("foo 1-2", "foo 1-2-3", "foo 1-2-3-4"), "foo"), c("1-2", "1-2-3", "1-2-3-4") ) expect_equal( news_version("foo (development version)", "foo"), "development version" ) }) test_that("correctly collapses version to page for common cases", { versions <- c("1.0.0", "1.0.0.0", "1.0.0.9000", "development version") pages <- purrr::map_chr(versions, version_page) expect_equal(pages, c("1.0", "1.0", "dev", "dev")) }) # Tweaks ------------------------------------------------------------------ test_that("sections tweaked down a level", { html <- xml2::read_xml( "

    " ) tweak_section_levels(html) expect_equal(xml2::xml_name(xpath_xml(html, "//div/*")), paste0("h", 2:6)) expect_equal(xpath_attr(html, "//div", "class"), paste0("section level", 2:6)) }) test_that("anchors de-duplicated with version", { html <- xml2::read_xml( "
    Heading
    " ) tweak_news_anchor(html, "1.0") expect_equal(xpath_attr(html, ".//div", "id"), "x-1-0") }) test_that("news headings get class and release date", { timeline <- tibble::tibble(version = "1.0", date = "2020-01-01") html <- xml2::read_xml("

    ") tweak_news_heading(html, version = "1.0", timeline = timeline, bs_version = 3) expect_snapshot_output(xpath_xml(html, "//div")) html <- xml2::read_xml("

    ") tweak_news_heading(html, version = "1.0", timeline = timeline, bs_version = 4) expect_snapshot_output(xpath_xml(html, "//div")) }) # Header checks ---------------------------------------------------------- test_that("clear error for bad hierarchy - bad nesting", { pkg <- local_pkgdown_site() # fmt: skip pkg <- pkg_add_file(pkg, "NEWS.md", c( "### testpackage 1.0.0.9000", "", "* bullet (#222 @someone)", "", "# testpackage 1.0.0", "", "## sub-heading", "", "* first thing (#111 @githubuser)", "", "* second thing", "" )) expect_snapshot(data_news(pkg), error = TRUE) }) test_that("clear error for bad hierarchy - h3", { pkg <- local_pkgdown_site() # fmt: skip pkg <- pkg_add_file(pkg, "NEWS.md", c( "### testpackage 1.0.0.9000", "", "* bullet (#222 @someone)", "", "### testpackage 1.0.0", "", "#### sub-heading", "", "* first thing (#111 @githubuser)", "", "* second thing", "" )) expect_snapshot(data_news(pkg), error = TRUE) }) test_that("news can contain footnotes", { pkg <- local_pkgdown_site() # fmt: skip pkg <- pkg_add_file(pkg, "NEWS.md", c( "## testpackage 1.0.0.9000", "", "* bullet", "", "* inline footnote^[used to fail] ", "" )) expect_snapshot(x <- data_news(pkg)) }) test_that("data_news warns if no headings found", { skip_if_no_pandoc() pkg <- local_pkgdown_site() # fmt: skip pkg <- pkg_add_file( pkg, "NEWS.md", c( "# mypackage", "", "## mypackage foo", "", "## mypackage bar", "" ) ) expect_snapshot(. <- data_news(pkg)) }) pkgdown/tests/testthat/test-tweak-page.R0000644000176200001440000001156614770274305020074 0ustar liggesuserstest_that("links to vignettes & figures tweaked", { html <- xml2::read_html( ' ' ) tweak_page( html, "article", list(bs_version = 3, desc = desc::desc(text = "")) ) expect_equal( xpath_attr(html, ".//img", "src"), c( "articles/x.png", "../articles/x.png", "reference/figures/x.png", "../reference/figures/x.png" ) ) }) test_that("reference index table is not altered", { html <- xml2::read_html( "
    " ) pkg <- list(bs_version = 3, desc = desc::desc(text = "")) tweak_page(html, "reference-index", pkg) expect_equal(xpath_attr(html, ".//table", "class"), NA_character_) }) test_that("articles get rescue highlighting for non-collapsed output", { html <- xml2::read_xml( "
    1
    1
    1
    " ) pkg <- list(bs_version = 3, desc = desc::desc(text = "")) tweak_page(html, "article", pkg) pre <- xml2::xml_find_all(html, ".//pre") expect_equal(xml2::xml_find_num(pre, "count(.//span[@class])"), c(1, 0, 0)) }) test_that("toc removed if one or fewer headings", { html <- xml2::read_html( "

    " ) tweak_useless_toc(html) expect_equal(xpath_length(html, ".//nav"), 1) html <- xml2::read_html( "

    " ) tweak_useless_toc(html) expect_equal(xpath_length(html, ".//nav"), 0) html <- xml2::read_html( "
    " ) tweak_useless_toc(html) expect_equal(xpath_length(html, ".//nav"), 0) }) test_that("toc removed if one or fewer headings", { html <- xml2::read_html( "

    " ) tweak_useless_toc(html) expect_equal(xpath_length(html, ".//nav"), 1) html <- xml2::read_html( "

    " ) tweak_useless_toc(html) expect_equal(xpath_length(html, ".//nav"), 0) html <- xml2::read_html( "
    " ) tweak_useless_toc(html) expect_equal(xpath_length(html, ".//nav"), 0) }) test_that("sidebar removed if empty", { html <- xml2::read_html( "
    " ) tweak_useless_toc(html) expect_equal(xpath_length(html, ".//div"), 0) }) test_that("sidebar removed if empty", { html <- xml2::read_html( "
    " ) tweak_useless_toc(html) expect_equal(xpath_length(html, ".//aside"), 0) }) # rmarkdown --------------------------------------------------------------- test_that("h1 section headings adjusted to h2 (and so on)", { html <- xml2::read_html( "

    1

    1.1

    2

    " ) tweak_rmarkdown_html(html) expect_equal(xpath_text(html, ".//h1"), "Title") expect_equal(xpath_text(html, ".//h2"), c("1", "2")) expect_equal(xpath_text(html, ".//h3"), "1.1") expect_equal(xpath_text(html, ".//h4"), "Author") expect_equal( xpath_attr(html, ".//div", "class"), c("page-header", "section level2", "section level3", "section level2") ) }) test_that("slashes not URL encoded during relative path conversion", { # Since the URL conversion process in tweak_markdown_html() makes calls to # fs::path_real() (which requires paths to exist), we create a # temporary pkgdown site directory and populate it with an image file, which # we can then reference in our test HTML file. # Create a site pkg <- local_pkgdown_site() # Add the referenced image in a subdirectory of vignettes. pkg <- pkg_add_kitten(pkg, "vignettes/img/") # Get the full path to the image. sim_path <- path_real(path(pkg$src_path, "vignettes/img/kitten.jpg")) # Simulate an output HTML file referencing the absolute path. html <- xml2::read_html( sprintf( ' ', sim_path ) ) # Function should update the absolute path to a relative path. tweak_rmarkdown_html(html, path(pkg$src_path, "vignettes")) # Check that the relative path has a non-encoded slash. expect_equal(xpath_attr(html, ".//img", "src"), "img/kitten.jpg") }) pkgdown/tests/testthat/test-build-logo.R0000644000176200001440000000075514770274305020102 0ustar liggesuserstest_that("can handle logo in subdir", { src <- withr::local_tempdir() dst <- withr::local_tempdir() dir_create(path(src, "man", "figures")) file_create(path(src, "man", "figures", "logo.svg")) pkg <- structure(list(src_path = src, dst_path = dst), class = "pkgdown") expect_true(has_logo(pkg)) suppressMessages(copy_logo(pkg)) expect_true(file_exists(path(dst, "logo.svg"))) expect_equal(logo_path(pkg, 0), "logo.svg") expect_equal(logo_path(pkg, 1), "../logo.svg") }) pkgdown/tests/testthat/test-build-llm-dl.R0000644000176200001440000000253715100735002020303 0ustar liggesuserstest_that("single dt/dd pair converts to simple li", { html <- xml2::read_html("
    ") simplify_dls(html) expect_equal(xpath_length(html, ".//dl"), 0) expect_equal(xpath_length(html, ".//ul"), 1) }) test_that("single dt/dd pair converts to simple li", { html <- xml2::read_html( "
    a
    b
    " ) simplify_dls(html) expect_equal(xpath_length(html, ".//dl"), 0) expect_equal(xpath_text(html, ".//li"), "a: b") }) test_that("dd with block elements simplifies correctly", { html <- xml2::read_html( "
    a

    b

    c

    " ) simplify_dls(html) expect_equal(xpath_length(html, ".//dl"), 0) expect_equal(xpath_length(html, ".//ul"), 1) expect_snapshot(xpath_xml(html, ".//li")) }) test_that("warns if not applied", { html <- xml2::read_html( "
    a
    " ) expect_snapshot(. <- simplify_dls(html)) }) test_that("correctly detects simple dls", { expect_false(is_simple_dl("dt")) expect_false(is_simple_dl(c("dd", "dt"))) expect_false(is_simple_dl(c("dt", "dd", "dt"))) expect_false(is_simple_dl(c("dd", "dt", "dd", "dt"))) expect_true(is_simple_dl(c())) expect_true(is_simple_dl(c("dt", "dd"))) expect_true(is_simple_dl(c("dt", "dd", "dt", "dd"))) }) pkgdown/tests/testthat/test-build-quarto-articles.R0000644000176200001440000000734715101160151022243 0ustar liggesuserstest_that("can build all quarto article", { skip_if_no_quarto() pkg <- local_pkgdown_site() pkg <- pkg_add_file(pkg, "vignettes/vig1.qmd") pkg <- pkg_add_file(pkg, "vignettes/vig2.qmd") suppressMessages(build_articles(pkg)) expect_true(file_exists(path(pkg$dst_path, "articles/vig1.html"))) expect_true(file_exists(path(pkg$dst_path, "articles/vig2.html"))) }) test_that("can build a single quarto article", { skip_if_no_quarto() pkg <- local_pkgdown_site() pkg <- pkg_add_file(pkg, "vignettes/vig1.qmd") pkg <- pkg_add_file(pkg, "vignettes/vig2.qmd") suppressMessages(build_article("vig1", pkg)) expect_true(file_exists(path(pkg$dst_path, "articles/vig1.html"))) expect_false(file_exists(path(pkg$dst_path, "articles/vig2.html"))) }) test_that("doesn't do anything if no quarto articles", { pkg <- local_pkgdown_site() expect_no_error(suppressMessages(build_quarto_articles(pkg))) }) test_that("can render a pdf qmd", { skip_if_no_quarto() pkg <- local_pkgdown_site() pkg <- pkg_add_file( pkg, "vignettes/vig1.qmd", pkg_vignette( format = list(pdf = list(toc = TRUE)) ) ) expect_equal(pkg$vignettes$type, "qmd") expect_equal(pkg$vignettes$file_out, "articles/vig1.pdf") suppressMessages(build_article("vig1", pkg)) expect_true(file_exists(path(pkg$dst_path, "articles/vig1.pdf"))) }) test_that("auto-adjusts heading levels", { skip_if_no_quarto() pkg <- local_pkgdown_site() pkg <- pkg_add_file( pkg, "vignettes/vig1.qmd", pkg_vignette( "# Heading 1", "# Heading 2" ) ) suppressMessages(build_article("vig1", pkg)) html <- xml2::read_html(path(pkg$dst_path, "articles/vig1.html")) expect_equal(xpath_text(html, "//h1"), "title") expect_equal(xpath_text(html, "//h2"), c("Heading 1\n", "Heading 2\n")) }) test_that("we find out if quarto styles change", { skip_if_no_quarto() pkg <- local_pkgdown_site() pkg <- pkg_add_file(pkg, "vignettes/vig1.qmd") output_dir <- quarto_render(pkg, path(pkg$src_path, "vignettes", "vig1.qmd")) data <- data_quarto_article(pkg, path(output_dir, "vig1.html"), "vig1.qmd") expect_snapshot(cat(data$includes$style)) }) test_that("quarto articles are included in the index", { skip_if_no_quarto() pkg <- local_pkgdown_site() pkg <- pkg_add_file( pkg, "vignettes/vig1.qmd", pkg_vignette( "## Heading 1", "Some text" ) ) suppressMessages(build_article("vig1", pkg)) index <- build_search_index(pkg) expect_equal(index[[1]]$path, "/articles/vig1.html") expect_equal(index[[1]]$what, "Heading 1") expect_equal(index[[1]]$text, "text") # some is a stop word }) test_that("quarto headings get anchors", { skip_if_no_quarto() pkg <- local_pkgdown_site() pkg <- pkg_add_file( pkg, "vignettes/vig1.qmd", pkg_vignette( "## Heading 1", "### Heading 2" ) ) suppressMessages(build_article("vig1", pkg)) html <- xml2::read_html(path(pkg$dst_path, "articles/vig1.html")) headings <- xpath_xml(html, "//h2|//h3") expect_equal( xpath_attr(headings, "./a", "href"), c("#heading-1", "#heading-2") ) }) test_that("can build quarto articles in articles folder", { skip_if_no_quarto() pkg <- local_pkgdown_site() pkg <- pkg_add_file(pkg, "vignettes/articles/vig1.qmd") pkg <- pkg_add_file(pkg, "vignettes/vig2.qmd") pkg <- pkg_add_file(pkg, "vignettes/articles/vig3.rmd") pkg <- pkg_add_file(pkg, "vignettes/vig4.rmd") suppressMessages(build_articles(pkg)) expect_true(file_exists(path(pkg$dst_path, "articles/vig1.html"))) expect_true(file_exists(path(pkg$dst_path, "articles/vig2.html"))) expect_true(file_exists(path(pkg$dst_path, "articles/vig3.html"))) expect_true(file_exists(path(pkg$dst_path, "articles/vig4.html"))) }) pkgdown/tests/testthat/test-build-search-docs.R0000644000176200001440000000414414770274305021331 0ustar liggesuserstest_that("docsearch.json and sitemap.xml are valid for BS 3 site", { pkg <- local_pkgdown_site( meta = list( url = "https://example.com", template = list( bootstrap = 3, params = list( docsearch = list( api_key = "test-api-key", index_name = "test-index-name" ) ) ) ) ) suppressMessages(build_docsearch_json(pkg)) json <- path(pkg$dst_path, "docsearch.json") expect_true(jsonlite::validate(read_lines(json))) suppressMessages(build_sitemap(pkg)) xml <- path(pkg$dst_path, "sitemap.xml") schema <- xml2::read_xml(test_path("assets/sitemaps-schema-0.9.xsd")) expect_true(xml2::xml_validate(xml2::read_xml(xml), schema)) }) test_that("build_search_index() has expected structure", { pkg <- local_pkgdown_site( desc = list(Version = "1.0.0"), meta = list(url = "https://example.com") ) pkg <- pkg_add_file( pkg, "README.md", c( "# My Package", "What the pakage does" ) ) suppressMessages(init_site(pkg)) suppressMessages(build_home_index(pkg)) expect_snapshot(str(build_search_index(pkg))) }) test_that("build sitemap only messages when it updates", { pkg <- local_pkgdown_site(meta = list(url = "https://example.com")) suppressMessages(init_site(pkg)) suppressMessages(build_home(pkg)) expect_snapshot({ build_sitemap(pkg) build_sitemap(pkg) }) }) test_that("build_search() builds the expected search.json with no URL", { pkg <- local_pkgdown_site(desc = list(Version = "1.0.0")) pkg <- pkg_add_file( pkg, "README.md", c( "# My Package", "What the pakage does" ) ) suppressMessages(build_home(pkg)) index <- build_search_index(pkg) paths <- purrr::map_chr(index, "path") expect_equal(paths, c("/authors.html", "/authors.html", "/index.html")) }) test_that("sitemap excludes redirects", { pkg <- local_pkgdown_site( meta = list( url = "https://example.com", redirects = list(c("a.html", "b.html")) ) ) suppressMessages(build_redirects(pkg)) expect_equal(get_site_paths(pkg), character()) }) pkgdown/tests/testthat/test-build-article.R0000644000176200001440000002771515001744016020557 0ustar liggesuserstest_that("can build article that uses html_vignette", { pkg <- local_pkgdown_site() pkg <- pkg_add_file( pkg, "vignettes/test.Rmd", pkg_vignette( output = "rmarkdown::html_vignette", pkgdown = list(as_is = TRUE) ) ) # theme is not set since html_vignette doesn't support it suppressMessages(expect_no_error(build_article("test", pkg))) }) test_that("can override html_document() options", { pkg <- local_pkgdown_site() pkg <- pkg_add_file( pkg, "vignettes/test.Rmd", pkg_vignette( output = list(html_document = list(number_sections = TRUE)), pkgdown = list(as_is = TRUE), "# Heading 1", "# Heading 2" ) ) suppressMessages(path <- build_article("test", pkg)) # Check that number_sections is respected html <- xml2::read_html(path) expect_equal(xpath_text(html, ".//h2//span"), c("1", "2")) # But title isn't affected expect_equal(xpath_text(html, ".//h1"), "title") # And no links or scripts are inlined expect_equal(xpath_length(html, ".//body//link"), 0) expect_equal(xpath_length(html, ".//body//script"), 0) }) test_that("can set width", { pkg <- local_pkgdown_site(meta = list(code = list(width = 50))) pkg <- pkg_add_file( pkg, "vignettes/test.Rmd", pkg_vignette( r_code_block("getOption('width')") ) ) suppressMessages(path <- build_article("test", pkg)) html <- xml2::read_html(path) expect_equal(xpath_text(html, ".//pre")[[2]], "## [1] 50") }) test_that("bad width gives nice error", { pkg <- local_pkgdown_site(meta = list(code = list(width = "abc"))) expect_snapshot(rmarkdown_setup_pkgdown(pkg), error = TRUE) }) test_that("BS5 article laid out correctly with and without TOC", { pkg <- local_pkgdown_site() pkg <- pkg_add_file( pkg, "vignettes/toc-true.Rmd", pkg_vignette( "## Heading 1", "## Heading 2" ) ) pkg <- pkg_add_file( pkg, "vignettes/toc-false.Rmd", pkg_vignette( toc = FALSE, "## Heading 1", "## Heading 2" ) ) suppressMessages(toc_true_path <- build_article("toc-true", pkg)) suppressMessages(toc_false_path <- build_article("toc-false", pkg)) toc_true <- xml2::read_html(toc_true_path) toc_false <- xml2::read_html(toc_false_path) # Always has class col-md-9 expect_equal(xpath_attr(toc_true, ".//main", "class"), "col-md-9") expect_equal(xpath_attr(toc_false, ".//main", "class"), "col-md-9") # The no sidebar without toc expect_equal(xpath_length(toc_true, ".//aside"), 1) expect_equal(xpath_length(toc_false, ".//aside"), 0) }) test_that("BS5 article gets correctly activated navbar", { pkg <- local_pkgdown_site() pkg <- pkg_add_file(pkg, "vignettes/article.Rmd", pkg_vignette()) suppressMessages(article_path <- build_article("article", pkg)) html <- xml2::read_html(article_path) navbar <- xml2::xml_find_first(html, ".//div[contains(@class, 'navbar')]") expect_equal( xpath_text(navbar, ".//li[contains(@class, 'active')]//button"), "Articles" ) }) test_that("titles are escaped when needed", { pkg <- local_pkgdown_site() pkg <- pkg_add_file( pkg, "vignettes/test.Rmd", pkg_vignette(title = "a <-> b") ) suppressMessages(path <- build_article("test", pkg)) html <- xml2::read_html(path) expect_equal( xpath_text(html, "//title", trim = TRUE), "a <-> b • testpackage" ) expect_equal(xpath_text(html, "//h1", trim = TRUE), "a <-> b") }) test_that("output is reproducible by default, i.e. 'seed' is respected", { pkg <- local_pkgdown_site() pkg <- pkg_add_file( pkg, "vignettes/test.Rmd", pkg_vignette( r_code_block("runif(5L)") ) ) suppressMessages(path <- build_article("test", pkg)) html <- xml2::read_html(path) output <- xpath_text(html, "//main//pre")[[2]] expect_snapshot(cat(output)) }) test_that("reports on bad open graph meta-data", { pkg <- local_pkgdown_site() pkg <- pkg_add_file( pkg, "vignettes/test.Rmd", pkg_vignette( opengraph = list(twitter = 1) ) ) expect_snapshot(build_article("test", pkg), error = TRUE) }) test_that("can control math mode", { pkg <- local_pkgdown_site() pkg <- pkg_add_file(pkg, "vignettes/math.Rmd", "$1 + 1$") pkg$meta$template$`math-rendering` <- "mathml" suppressMessages(init_site(pkg)) suppressMessages(path <- build_article("math", pkg)) html <- xml2::read_html(path) expect_equal(xpath_length(html, ".//math"), 1) pkg$meta$template$`math-rendering` <- "mathjax" suppressMessages(init_site(pkg)) suppressMessages(path <- build_article("math", pkg)) html <- xml2::read_html(path) expect_equal(xpath_length(html, ".//span[contains(@class, 'math')]"), 1) pkg$meta$template$`math-rendering` <- "katex" suppressMessages(init_site(pkg)) suppressMessages(path <- build_article("math", pkg)) html <- xml2::read_html(path) expect_equal(xpath_length(html, ".//span[contains(@class, 'math')]"), 1) expect_contains( path_file(xpath_attr(html, ".//script", "src")), c("katex-auto.js", "auto-render.min.js", "katex.min.js") ) }) test_that("rmarkdown_template cleans up after itself", { pkg <- local_pkgdown_site() path <- NULL local({ path <<- rmarkdown_template(pkg) expect_true(file_exists(path)) }) expect_false(file_exists(path)) }) test_that("build_article styles ANSI escapes", { skip_if_no_pandoc() pkg <- local_pkgdown_site() pkg <- pkg_add_file( pkg, "vignettes/test.Rmd", pkg_vignette( r_code_block("cat(cli::col_red('X'), '\n')") ) ) suppressMessages(path <- build_article("test", pkg)) html <- xml2::read_html(path) expect_snapshot_output(xpath_xml(html, ".//code//span[@class='co']")) }) # Errors ----------------------------------------------------------------------- test_that("build_article yields useful error if pandoc fails", { skip_on_cran() # fragile due to pandoc dependency skip_if_no_pandoc("2.18") pkg <- local_pkgdown_site() pkg <- pkg_add_file( pkg, "vignettes/test.Rmd", c( "Some text.", "", "[^1]: Unreferenced footnote.", "" ) ) expect_error( build_article("test", pkg, pandoc_args = "--fail-if-warnings"), "Note with key .+ defined at .+ but not used" ) }) test_that("build_article yields useful error if R fails", { skip_if_no_pandoc() # R 4.1.3 does not have UTF-8 support on Windows which breaks snapshot skip_if( R.version$minor < 4.2 && identical(tolower(Sys.info()[['sysname']]), "windows"), "R on Windows before 4.2 does not have UTF-8 support." ) # workaround an as-yet unreleassed knitr version # https://github.com/yihui/knitr/issues/2399#issuecomment-2803554647 skip_if(packageVersion('knitr') < '1.50.3') pkg <- local_pkgdown_site() pkg <- pkg_add_file( pkg, "vignettes/test.Rmd", c( "---", "title: title", "---", "```{r}", "options(cli.num_colors = 1L)", "f <- function() g()", "g <- function() h()", "h <- function() rlang::abort('Error!')", "f()", "```" ) ) # For following snapshot we opted-out color setting option in the Rmd file # check that error looks good expect_snapshot( build_article("test", pkg), error = TRUE, variant = if (in_rcmd_check()) "rcmdcheck" else "not-in-rcmcheck" ) # check that traceback looks good - need extra work because rlang # avoids tracebacks in snapshots expect_snapshot( summary(expect_error(build_article("test", pkg))), variant = if (in_rcmd_check()) "rcmdcheck" else "not-in-rcmcheck" ) }) # Images ----------------------------------------------------------------------- test_that("build_article copies image files in subdirectories", { skip_if_no_pandoc() pkg <- local_pkgdown_site() pkg <- pkg_add_file( pkg, "vignettes/test.Rmd", c( "```{r}", "#| fig-alt: alt-text", "knitr::include_graphics('test/kitten.jpg')", "```" ) ) pkg <- pkg_add_kitten(pkg, "vignettes/test") expect_snapshot(build_article("test", pkg)) expect_equal( path_file(dir_ls(path(pkg$dst_path, "articles", "test"))), "kitten.jpg" ) }) test_that("finds external resources referenced by R code", { # weird path differences that I don't have the energy to dig into skip_on_cran() pkg <- local_pkgdown_site() pkg <- pkg_add_file( pkg, "vignettes/test.Rmd", c( "![external dependency](`r 'kitten.jpg'`)" ) ) pkg <- pkg_add_kitten(pkg, "vignettes") suppressMessages(path <- build_article("test", pkg)) # ensure that we the HTML references `` directly html <- xml2::read_html(path) expect_equal(xpath_attr(html, ".//img", "src"), "kitten.jpg") # expect that `external.png` was copied to the rendered article directory expect_true(file_exists(path(path_dir(path), "kitten.jpg"))) }) test_that("image links relative to output", { pkg <- local_pkgdown_site(test_path("assets/articles-images")) suppressMessages(init_site(pkg)) suppressMessages(copy_figures(pkg)) suppressMessages(build_article("kitten", pkg)) html <- xml2::read_html(path(pkg$dst_path, "articles", "kitten.html")) src <- xpath_attr(html, "//main//img", "src") expect_equal( src, c( # knitr::include_graphics() "../reference/figures/kitten.jpg", "another-kitten.jpg", # rmarkdown image "../reference/figures/kitten.jpg", "another-kitten.jpg", # magick::image_read() "kitten_files/figure-html/magick-1.png", # figure "kitten_files/figure-html/plot-1.jpg" ) ) # And files aren't copied expect_false(dir_exists(path(pkg$dst_path, "man"))) }) test_that("warns about missing images", { pkg <- local_pkgdown_site() pkg <- pkg_add_file(pkg, "vignettes/kitten.Rmd", "![foo](kitten.jpg)") expect_snapshot(build_article("kitten", pkg)) }) test_that("spaces in sorce paths do work", { # create simulated package pkg0 <- local_pkgdown_site() pkg0 <- pkg_add_file(pkg0, "vignettes/kitten.Rmd", "![Kitten](kitten.jpg)") pkg0 <- pkg_add_kitten(pkg0, "vignettes") # copy simulated pkg to path that contains spaces pkg1 <- fs::dir_copy( pkg0$src_path, fs::file_temp(pattern = "beware of spaces-") ) # check that pkgdown site builds anyways expect_no_error(suppressMessages( build_article("kitten", as_pkgdown(pkg1)) )) }) test_that("warns about missing alt-text", { pkg <- local_pkgdown_site() pkg <- pkg_add_file(pkg, "vignettes/kitten.Rmd", "![](kitten.jpg)") pkg <- pkg_add_kitten(pkg, "vignettes") expect_snapshot(build_article("kitten", pkg)) }) # External dependencies -------------------------------------------------------- test_that("pkgdown deps are included only once in articles", { pkg <- local_pkgdown_site() pkg <- pkg_add_file( pkg, "vignettes/test.Rmd", pkg_vignette( # Some code that adds jquery/bootstrap r_code_block( 'htmltools::tagList( htmltools::p("hello"), rmarkdown::html_dependency_jquery(), rmarkdown::html_dependency_bootstrap("flatly") )' ) ) ) # Rely on default init_site() from local_pkgdown_site() setting all # the default includes to empty suppressMessages(path <- build_article("test", pkg)) html <- xml2::read_html(path) expect_equal(path_file(xpath_attr(html, ".//script", "src")), "pkgdown.js") expect_equal(path_file(xpath_attr(html, ".//link", "href")), character()) }) test_that("html widgets get needed css/js", { pkg <- local_pkgdown_site() pkg <- pkg_add_file( pkg, "vignettes/test.Rmd", pkg_vignette( r_code_block( ' path1 <- tempfile() writeLines(letters, path1) path2 <- tempfile() writeLines(letters[-(10:11)], path2) diffviewer::visual_diff(path1, path2) ' ) ) ) suppressMessages(path <- build_article("test", pkg)) html <- xml2::read_html(path) css <- xpath_attr(html, ".//body//link", "href") js <- xpath_attr(html, ".//body//script", "src") expect_true("diffviewer.css" %in% path_file(css)) expect_true("diffviewer.js" %in% path_file(js)) }) pkgdown/tests/testthat/test-markdown.R0000644000176200001440000000436414770274305017667 0ustar liggesuserstest_that("handles empty inputs (returns NULL)", { pkg <- local_pkgdown_site() expect_null(markdown_text_inline(pkg, "")) expect_null(markdown_text_inline(pkg, NULL)) expect_null(markdown_text_block(pkg, NULL)) expect_null(markdown_text_block(pkg, "")) path <- withr::local_tempfile() file_create(path) expect_null(markdown_body(pkg, path)) }) test_that("header attributes are parsed", { pkg <- local_pkgdown_site() text <- markdown_text_block(pkg, "# Header {.class #id}") expect_match(text, "id=\"id\"") expect_match(text, "class=\".*? class\"") }) test_that("markdown_text_inline() works with inline markdown", { pkg <- local_pkgdown_site() expect_equal(markdown_text_inline(pkg, "**lala**"), "lala") expect_snapshot(error = TRUE, { markdown_text_inline(pkg, "x\n\ny", error_path = "title") }) }) test_that("markdown_text_block() works with inline and block markdown", { skip_if_no_pandoc("2.17.1") pkg <- local_pkgdown_site() expect_equal(markdown_text_block(pkg, "**x**"), "

    x

    ") expect_equal(markdown_text_block(pkg, "x\n\ny"), "

    x

    y

    ") }) test_that("markdown_body() captures title", { pkg <- local_pkgdown_site() temp <- withr::local_tempfile(lines = "# Title\n\nSome text") html <- markdown_body(pkg, temp) expect_equal(attr(html, "title"), "Title") # And can optionally strip it html <- markdown_body(pkg, temp, strip_header = TRUE) expect_equal(attr(html, "title"), "Title") expect_no_match(html, "Title") }) test_that("markdown_text_*() handles UTF-8 correctly", { pkg <- local_pkgdown_site() expect_equal(markdown_text_block(pkg, "\u00f8"), "

    \u00f8

    ") expect_equal(markdown_text_inline(pkg, "\u00f8"), "\u00f8") }) test_that("validates math yaml", { config_math_rendering_ <- function(...) { pkg <- local_pkgdown_site(meta = list(template = list(...))) config_math_rendering(pkg) } expect_snapshot(error = TRUE, { config_math_rendering_(`math-rendering` = 1) config_math_rendering_(`math-rendering` = "math") }) }) test_that("preserves ANSI characters", { withr::local_options(cli.num_colors = 256) pkg <- local_pkgdown_site() expect_snapshot( markdown_text(pkg, sprintf("prefer %s", cli::col_blue("a"))) ) }) pkgdown/tests/testthat.R0000644000176200001440000000061215074163153015054 0ustar liggesusers# This file is part of the standard setup for testthat. # It is recommended that you do not modify it. # # Where should you do additional test configuration? # Learn more about the roles of various files in: # * https://r-pkgs.org/testing-design.html#sec-tests-files-overview # * https://testthat.r-lib.org/articles/special-files.html library(testthat) library(pkgdown) test_check("pkgdown") pkgdown/MD50000644000176200001440000007060115103035714012236 0ustar liggesusers5e8e98e4591242149023792a3f43872c *DESCRIPTION e7043cd3eea22b67565025f9b47efb96 *LICENSE ed1265df10381b8fbf578e3e1cb7e530 *NAMESPACE 28e7028e6cd0d34c93f9b26cafffd5af *NEWS.md bc875fd90de379da32251017cfe28134 *R/build-404.R 9fd9458b0647b47e0d5da5de69a6173c *R/build-article.R 3ba1b27f12dc01ca41b9d3a4c7c9e342 *R/build-articles.R 3a2d49b8bd21a6eeb805d9e1078ba8a8 *R/build-favicons.R 6909c5d9b1925dceca4cb5d3c42c6edf *R/build-footer.R 86243643b1700fbce81845e53375a354 *R/build-github.R b411e26ad16885a8ca94c3173cce0ec2 *R/build-home-authors.R e684a26f02ba50f34a81d5af3d2745e0 *R/build-home-community.R 2513e42b380da6463844ac826188d6a3 *R/build-home-index.R 66feb3760c864e7d955060b568bc3e14 *R/build-home-license.R 54bb04d614ed16778fefa7434e1aa9e5 *R/build-home-md.R b4a88e6603bf2abb736397bdf545bf18 *R/build-home.R e2732a40df135c9ad497629b15bc29e2 *R/build-llm-dl.R edb9ecdc87a45b2ebfbe87a316bb1386 *R/build-llm.R 2fc675da885ca6871765d5b8ea7bc67a *R/build-logo.R 5c362c0e07708ee7d8f65ef2f7fb2081 *R/build-news.R fb965c27df6bed7e9169f8081dbff429 *R/build-quarto-articles.R d6a983c17b0fc6db1f36130fa080815a *R/build-redirects.R 02d42e7d3b1996d55347dbcff08fbde8 *R/build-reference-index.R 7ce74c8d2482f4253944f10736f993b9 *R/build-reference.R fe451da9a6f7547b8f74bd3b69a77159 *R/build-search-docs.R 6f0833e1d12ba598cdaf59088f57a1fe *R/build-tutorials.R fe495c06b19ee0115cc96c86f66d64d1 *R/build.R 1b9e69f3e1f45a7ddc8b9b6fc4f1e657 *R/check-built.R 046fe267947490b2d2790620480f6a0f *R/check.R fe8ef22033af276867b61bb15de5f666 *R/clean.R 866d97cb90b747b486c733886179fc75 *R/config.R 1fec8aa8ad4dc45dd265370dfe4ed5a2 *R/context.R c62f2bb3a6c2a10275624364c1aedcf1 *R/deploy-site.R 042c499e88c8e2c3c22f5585244fbddd *R/development.R e1e5ebcc0eb9c4e52e25fedc3b9d71fa *R/external-deps.R ed66bfda0264a106b353eed6dfefbc32 *R/figure.R 517d5f17dc2f7e589949047225fd00de *R/highlight.R 6d500c8474e1260b0a92c30a588c2a32 *R/html-build.R fd54960d42e75f4f586bd613da5edca8 *R/import-standalone-obj-type.R d14482fe474ef5cb76b60c9c4777ebe2 *R/import-standalone-types-check.R 29fb85832ac06920a9aba1736693034a *R/init.R 68e499f1c824596dd6e91a1d9dab2e34 *R/markdown.R 75ef2c98821034ab8b395ab7122f2b2a *R/navbar-menu.R 3a60817e16ffb5c8f700e08aed0b32c8 *R/navbar.R 1b8375386cb7d38da0e364dc8351707d *R/package.R cd3aadc96f9858d9b443b3955784b2f6 *R/pkgdown-package.R 22b0c043d827123d17e59ecb216601ed *R/pkgdown.R c7764db1981f7300cb70944471c982e5 *R/pkgdown_print.R 2c187e3a0aaa27e50f710856ae7edb18 *R/preview.R 41cc461fef0fbfd467356f595968dfce *R/rd-data.R ecb158e1f23d14c72f1ee4094f214cec *R/rd-example.R 17d513e3f717d45ae10f19fd6427274c *R/rd-html.R 55809f33d1c5a2582b7ce0ba7f35f516 *R/rd.R a472900e02a1fc7ffd09146fb15cc038 *R/render.R a03627823fe163dbfb9773fb20cff41e *R/repo.R cc6db878266050cc5f8d68a5c3962901 *R/template.R b30b22af596dce749c9e0711569ec17f *R/templates.R 21c520814272c1f6e046a30268ccc841 *R/test.R 266b693f068fe12ba4085e96437e66b0 *R/theme.R cb58e0d8d803cf82eee98d21550a88bf *R/topics-external.R b36ebb108c4c28dfb87c003c6df5ac77 *R/topics.R 41a9c8e9125e3bb3c1f15d93bd2cf5d3 *R/tweak-homepage.R 1e8a0013cd6b562cbd6639e4aab3460f *R/tweak-navbar.R be69083d7b595ca591e021b5d5eb0db8 *R/tweak-page.R 663a11c62457de9501c5cb517b38b2a4 *R/tweak-reference.R 0e466e2cdd0b9fd5164f7c00f5a4f389 *R/tweak-tabset.R 264af632e7874feaae9ee2964bc45e75 *R/tweak-tags.R 780ef4186f76f95c1c83c8a424c6a58b *R/tweak.R 58702ed89021c6f2432408b04343f56f *R/usage.R 845742c7435b974636bfbf7b3ee6b880 *R/utils-fs.R ca8a5bebe487965dea696f5ccbc1380d *R/utils-io.R 3dcca33c3f23310c446775f72b8698f0 *R/utils-pdf.R fdcd0b82879182341f0b4799e0120007 *R/utils.R 573eb4e0d68afc39009922d808752bbd *README.md 2606715c406a708c390b0b431390d52b *build/stage23.rdb 04da728d37c6933b18381dd6a18553b1 *build/vignette.rds 5eec6702c35b15a8c2c123301987735d *inst/BS3/assets/bootstrap-toc.css aaa610b29d895e1128447e76b9bc0076 *inst/BS3/assets/bootstrap-toc.js 828dbea96017a994efccb7c30c041577 *inst/BS3/assets/docsearch.css 2f3c1f7995c9f4f966323f008e3984ad *inst/BS3/assets/docsearch.js 4759f31f8a585e9af173fc579d730265 *inst/BS3/assets/link.svg 9cd7da30627ce8d0e18fd1cf1f48c83f *inst/BS3/assets/pkgdown.css 916db342671c073ca830f33df8c36adc *inst/BS3/assets/pkgdown.js c7d93982b5bd95d8bfd02dcc203089cf *inst/BS3/templates/after-body.html 99da4d763bfd415fbf8a47d39e3e327f *inst/BS3/templates/before-body.html be694e1085f52eacbbdc67538154715f *inst/BS3/templates/config-docsearch.json 6ca9f48641134d2ea7308d4152153d77 *inst/BS3/templates/content-article-index.html 794d01127b89987c3edcd901e880c3f0 *inst/BS3/templates/content-article.html b17e8d987ad6cc164911dda22dda7a4e *inst/BS3/templates/content-citation-authors.html 27498f778ae1162bb9043470bc33e1ac *inst/BS3/templates/content-home.html d53bc0b8cbacf5659165f56b0eb1f445 *inst/BS3/templates/content-news-index.html 4767a06ed1ff33b0812cae1053919b49 *inst/BS3/templates/content-news.html 149a3968aa95318544ce87d3422ef2eb *inst/BS3/templates/content-reference-index.html 27dadcf6406485ef9b4bc8d8e9f35d93 *inst/BS3/templates/content-reference-topic.html 2effb010f58761192bb8d310baf05fb4 *inst/BS3/templates/content-title-body.html a973fbc8726549edd09bd0a2aebb991e *inst/BS3/templates/content-tutorial-index.html 9173209b61812d79bae347eaddd96cd4 *inst/BS3/templates/content-tutorial.html a18f6f4b69cc626b06d89759168b8463 *inst/BS3/templates/docsearch.html 3aac39beb5aeb1049269e6bbf02b1afe *inst/BS3/templates/footer.html 43538f207d7d9cc0b43954138915feb4 *inst/BS3/templates/head.html d41d8cd98f00b204e9800998ecf8427e *inst/BS3/templates/header.html 24c32452b796b57ffa959d2c414ec2a4 *inst/BS3/templates/in-header.html b02b9d96ff878bfcfa3cecfc62c34d83 *inst/BS3/templates/layout-redirect.html f7780ff5acfd913ddc3e2797290328ee *inst/BS3/templates/layout.html 9fc50d0e252d74e2dd44b55bba668b57 *inst/BS3/templates/navbar.html b890f6fad8eb9ce3a32eea2239934274 *inst/BS5/assets/katex-auto.js fede8a6a6ba71fd2cacb48c55533a081 *inst/BS5/assets/lightswitch.js 4759f31f8a585e9af173fc579d730265 *inst/BS5/assets/link.svg 1c9c0d6bf54c521a9993e0b2d23c5d08 *inst/BS5/assets/pkgdown.js 0379da8c5d5516e0c70d937afcc74952 *inst/BS5/assets/pkgdown.scss c7d93982b5bd95d8bfd02dcc203089cf *inst/BS5/templates/after-body.html 99da4d763bfd415fbf8a47d39e3e327f *inst/BS5/templates/before-body.html 9f93e2654920065cd7f29b601c90ff82 *inst/BS5/templates/config-docsearch.json e231175debcc602eccb667037cb54213 *inst/BS5/templates/content-article-index.html 023a84df71c1f1df98132f7ff752fba0 *inst/BS5/templates/content-article.html a11f4161a8058dbf2a5fad00af9fa9c6 *inst/BS5/templates/content-authors.html ccf2563b90552387d272037998e00c88 *inst/BS5/templates/content-citation-authors.html 24e9ad1721b278a24b325163de6617ba *inst/BS5/templates/content-home.html bff9cff56c781de05cab62382d553799 *inst/BS5/templates/content-news-index.html 8f3894fa33760d67e9d3ebe0eb74cc9d *inst/BS5/templates/content-news.html 7fce554cf19be5f108718fa5855b041c *inst/BS5/templates/content-quarto.html 0461219b1e08dbbbcfbf25022d960485 *inst/BS5/templates/content-reference-index.html ae9620c485f580c2692d9087e8690cc0 *inst/BS5/templates/content-reference-topic.html 12b955cf7dd62c34f50c5b419edec9bd *inst/BS5/templates/content-title-body.html 35bec3727d15b529a9f128143258d5d9 *inst/BS5/templates/content-tutorial-index.html 64d8b70e89e4044c389e3608d50bb4b1 *inst/BS5/templates/content-tutorial.html 841f25541730c73bcac04bb73c81a556 *inst/BS5/templates/footer.html 22a5f0ed71685de0ddaf8840fa8fc54f *inst/BS5/templates/head.html d41d8cd98f00b204e9800998ecf8427e *inst/BS5/templates/header.html 24c32452b796b57ffa959d2c414ec2a4 *inst/BS5/templates/in-header.html b02b9d96ff878bfcfa3cecfc62c34d83 *inst/BS5/templates/layout-redirect.html bac5ba630c20ff8470b808d6f50de783 *inst/BS5/templates/layout.html 9575d50f193bcd9e69ebb9a5244c36f4 *inst/BS5/templates/navbar.html 9be2b49542c0d0aa909d4ee420bcfa70 *inst/doc/accessibility.R 73dea842d77d620f63b0ecf85283534b *inst/doc/accessibility.Rmd fc34da4ef781017a15106a551443e682 *inst/doc/accessibility.html 9be2b49542c0d0aa909d4ee420bcfa70 *inst/doc/customise.R 1c1582a54c2610ece8a0321ea9637caa *inst/doc/customise.Rmd b3155a488a70f2432e3e620b21a714ce *inst/doc/customise.html 3394e181a634fb81ff9add238b087f30 *inst/doc/how-to-update-released-site.R 258af8e6bbf38600816f718ba0cce89f *inst/doc/how-to-update-released-site.Rmd 754c5d11aa939cf7d155b8b8d7b46ac8 *inst/doc/how-to-update-released-site.html ca78ea2b731dc25b7695c582ece4144c *inst/doc/linking.R 70383c38cd3188fb0079ec4f67ff2ade *inst/doc/linking.Rmd 0df6ba44494e09d131133c62ff978eee *inst/doc/linking.html ca78ea2b731dc25b7695c582ece4144c *inst/doc/metadata.R ad6f0ff3108d23d4fa6de0dfadcf6e36 *inst/doc/metadata.Rmd a400c171f6b9b605ee1656a2b887ac9c *inst/doc/metadata.html c1c7a0b1bb498d90c8d439fdb1383b40 *inst/doc/pkgdown.R 6207e6c15e6bf614e0b47a41a56174d3 *inst/doc/pkgdown.Rmd d0e190876ff910d40df2f9a31e6b9942 *inst/doc/pkgdown.html 322a2ba7847648320ea45f5ad940a424 *inst/doc/quarto.R 401d5c92a2e3bc97c71e85f46c924fd9 *inst/doc/quarto.html 37ef9a8104d68a68fd7dcac1abc5b10e *inst/doc/quarto.qmd 3ab2f5b8e514f90b9d9c0e6c0f2f88f0 *inst/doc/translations.R 494a3aa83a9a9bd2443539c3853b737b *inst/doc/translations.Rmd 262c5c718f78f908fa7455e0f5a4f683 *inst/doc/translations.html 831eee68f858583f6c95e60dbf36838f *inst/highlight-styles/a11y-dark.scss 04792c4fb02a33db1ef2a14c8ed06651 *inst/highlight-styles/a11y-light.scss 8bcef9022dd99d22fa9dd9624b95cea6 *inst/highlight-styles/arrow-dark.scss a4fe28ce5e988ce796410495aefd89f5 *inst/highlight-styles/arrow-light.scss 36f195fd2c403d417a43c5cbfe6736c3 *inst/highlight-styles/atom-one-dark.scss b83625ac725d3b7fce2deaf59ae29554 *inst/highlight-styles/atom-one-light.scss d1edda7764a9e58e0ab2efc1e212464d *inst/highlight-styles/ayu-dark.scss 78028498193515e9fe41fdde2fab480f *inst/highlight-styles/ayu-light.scss 824c7f8a16f2a5dbdbcb0addd6449a04 *inst/highlight-styles/ayu-mirage.scss 1830891b18652e65a34b0769e81ef563 *inst/highlight-styles/breeze-dark.scss 6315ad3dfd7aa79b37056147f6effff2 *inst/highlight-styles/breeze-light.scss 864175b7283294b26b2c4812a74786d3 *inst/highlight-styles/breezedark.scss 0525c7deac0ef80d0a70360f797ef6f2 *inst/highlight-styles/dracula.scss 38645fe4c988cc50ca5dd21400e3aa66 *inst/highlight-styles/espresso.scss e1dc9c2ed27598164f7fef3f025cab18 *inst/highlight-styles/github-dark.scss 6079553439a2d52a95d03b2e355f6612 *inst/highlight-styles/github-light.scss 168bb91cd28645fd384c7f05ab4d8df4 *inst/highlight-styles/gruvbox-dark.scss 2d65f57381db7b1ea7c3082901b877ea *inst/highlight-styles/gruvbox-light.scss dbcfda0230811b9a4ae7e40c043b928e *inst/highlight-styles/haddock.scss b1bbf9da25d9c2c56f747e830c4eaa81 *inst/highlight-styles/kate.scss 0592e8498787c952ec19c01a4fe806e3 *inst/highlight-styles/monochrome-dark.scss 6b6e4c361c40198cabfc94c1187e9c75 *inst/highlight-styles/monochrome-light.scss ff10c6adfc88a5b8106d57a309e2cf2b *inst/highlight-styles/monochrome.scss 545bcaea882a705e53696f573d42ff8b *inst/highlight-styles/monokai.scss 6875924895d1226bc27110be2da04666 *inst/highlight-styles/nord.scss 9e16c08a089007339160ed0958a41720 *inst/highlight-styles/oblivion.scss a1b3f1b986e5c32ffa9e7929632ea34c *inst/highlight-styles/printing.scss 8a0bb5551bcb9d90efc5884231f13527 *inst/highlight-styles/pygments.scss f9dc01c62de94948508853856192da5b *inst/highlight-styles/radical.scss 67474264129e6689dd93cb3fd17aec26 *inst/highlight-styles/solarized-dark.scss c1f970d3a36d50b3a7b5f1c39db21a3d *inst/highlight-styles/solarized-light.scss c1f970d3a36d50b3a7b5f1c39db21a3d *inst/highlight-styles/solarized.scss fcb59ae3dc9b0cd37deb35e332fb80e9 *inst/highlight-styles/tango.scss 5f9ec3e22735a2cea4cb7e5d401aa028 *inst/highlight-styles/vim-dark.scss ac49e3cdc01a34d9122772a8819df68b *inst/highlight-styles/zenburn.scss 32b679475e27c664d160b55dbb99bdd0 *inst/po/ca/LC_MESSAGES/R-pkgdown.mo 45c8662d4e26bd689e19c8fb2865ec09 *inst/po/de/LC_MESSAGES/R-pkgdown.mo 12d40dd4238f6b9c5205e6c205ed382f *inst/po/dk/LC_MESSAGES/R-pkgdown.mo d6d79d3a4024b66aa94390fd31efd7d5 *inst/po/es/LC_MESSAGES/R-pkgdown.mo 428742d23d047305a3c575656e8ffb64 *inst/po/fr/LC_MESSAGES/R-pkgdown.mo 328243582dcf5b45196e637d6b3f723f *inst/po/ja/LC_MESSAGES/R-pkgdown.mo 7a8895ca51af4156479f56bde01c8f33 *inst/po/ko/LC_MESSAGES/R-pkgdown.mo 75d9e3293fa74cd6199d5f8effd20aae *inst/po/kr/LC_MESSAGES/R-pkgdown.mo b79a3adfc7db6cb802e360896ac327e2 *inst/po/nl/LC_MESSAGES/R-pkgdown.mo 79dc778edeb0a248b30104425f3eb213 *inst/po/pt/LC_MESSAGES/R-pkgdown.mo 6532a6a574a9f9d84c50082fb17e04c0 *inst/po/tr/LC_MESSAGES/R-pkgdown.mo c42c7831005ad62fcf2c0da8b7b2db65 *inst/po/zh_CN/LC_MESSAGES/R-pkgdown.mo 8436355ba20233f185ed7186339d27ff *inst/quarto/template.html dcedbfdf96d8ef6fb3f0c301d65d095c *inst/rstudio/addins.dcf 73623a9540cea9fffbeb18a9951da0fc *man/as_pkgdown.Rd b8441ede6225e53c881b4174ced4084e *man/build_articles.Rd 7fc13c950a83841ff0f0301562c181a0 *man/build_favicons.Rd c09eba761ad3d92b1d1ab550ae0b2ced *man/build_home.Rd a271866a2551eeab18d2986da6b80059 *man/build_llm_docs.Rd c222c39cfb5ed18b67b9c29e9521846b *man/build_news.Rd aeb24558af7aeb38c9a8bec9f3566c1f *man/build_redirects.Rd cedf20b2d7afc53ffa0daa57413d49e0 *man/build_reference.Rd 01baf22c4ed5fa6cf9887a368198d05d *man/build_search.Rd 0cf92066705beeafcdc5f98200003e24 *man/build_site.Rd 078f6ac1d1f04084bd58ed401a24331b *man/build_site_github_pages.Rd feb392c47509e6624ab8e4b1c91ba989 *man/build_tutorials.Rd 890bc41be0204477dd7d8903db72ba27 *man/check_pkgdown.Rd bceebe84d3e6efd84f6fed51d9dfd313 *man/clean.Rd 42fb78fc70bfb815db8c001d19cf6d4f *man/deploy_site_github.Rd ab81d70c8f5043dc0540c77c073787e9 *man/deploy_to_branch.Rd 10c212ea9868aa62ee069de9e1a37b9c *man/fig_settings.Rd 4ee979c4c83a85a557030d69863e9d13 *man/figures/bacon.jpg cb1e46f469cfbbbde29c8b5113e1d789 *man/figures/lifecycle-archived.svg c0d2e5a54f1fa4ff02bf9533079dd1f7 *man/figures/lifecycle-defunct.svg 391f696f961e28914508628a7af31b74 *man/figures/lifecycle-deprecated.svg 691b1eb2aec9e1bec96b79d11ba5e631 *man/figures/lifecycle-experimental.svg 952b59dc07b171b97d5d982924244f61 *man/figures/lifecycle-maturing.svg 27b879bf3677ea76e3991d56ab324081 *man/figures/lifecycle-questioning.svg ed42e3fbd7cc30bc6ca8fa9b658e24a8 *man/figures/lifecycle-stable.svg bf2f1ad432ecccee3400afe533404113 *man/figures/lifecycle-superseded.svg 366e0dcbc8404aa04fe73e97caa90585 *man/figures/logo.png 85e8b6d1bcba89ebfd10a182a94447fb *man/in_pkgdown.Rd 60daf2be5532d8ddb50038cd12074050 *man/index.Rd e0f9c43e6c75dadaadacd6db0b3f7da1 *man/init_site.Rd 07e69f7ff29a780692c0be55d03813bf *man/pkgdown-package.Rd 74fdb77c11822aa805e8e119af841a10 *man/pkgdown_print.Rd 76d93d4feb43250ccd8008a976bd4897 *man/preview_site.Rd e2ff3f4601be509c687dbec163154568 *man/rd2html.Rd af0d91bbe60a0a95f737438f58bee0db *man/render_page.Rd 38e60aa25bbe7657e70d3de9a04869d5 *man/templates.Rd 44c83639665d55f0d45ff9fe7367a899 *man/test-crayon.Rd 2851a857a0f4b151126f26fb2de575a6 *man/test-dont.Rd f1c0c61bf553aee32629ecb54ffc705b *man/test-figures.Rd ad5d8c1a9fe839162ed20dc15961d4df *man/test-links.Rd f378fbd94be2ecc73c6984519ae3d503 *man/test-lists.Rd 0b6ef934c218b667b476c4107bfb75e3 *man/test-long-lines.Rd 36b9a303bf1cddc91321a2db95306fc7 *man/test-math-examples.Rd 640905f93284a6b1a79053b395d72548 *man/test-output-styles.Rd 7be0ad2c3299442c0e50cdb4c2f81189 *man/test-params.Rd d4aeabd36afb5cf9bfc37607f50d6896 *man/test-sexpr-title.Rd abdc6e960001e14e0078ecf81f9f70ea *man/test-tables.Rd 66cb3a8cb417c877f7066e838b982989 *man/test-verbatim.Rd caa197aaee6a57a901c687eed0c62256 *po/R-ca.po 27bd3d548cd830dea63ec3bf4fc84961 *po/R-de.po b902e4fe3a6034f7ba2a34b5a4188eac *po/R-dk.po 9582473b4f12d5eadcb476d3adaab50c *po/R-es.po 704c4582fc086317cc194c857dd072ba *po/R-fr.po 62334d1aa7b098a9c8f2f7e711195cf4 *po/R-ja.po 42d1b93ff3d952747de25101bbeec280 *po/R-ko.po cde2f3497ee4cf23a990978e9b599f13 *po/R-nl.po da4ea782ae3dc522e6323e50ce0047c8 *po/R-pkgdown.pot 2029652c0807fc167468ddfc269834d0 *po/R-pt.po 8a00d3ac3ece551faf2929916d9d353b *po/R-tr.po f8e2d99d0afeceff42d2535fe057d8ea *po/R-zh_CN.po 221d608a1d3b1a3018b5b73cb0673ef0 *tests/testthat.R 368060bba9bd4fa8f6d8298c189cfdb6 *tests/testthat/_snaps/build-article.md c448731e5928c7737eed793459233077 *tests/testthat/_snaps/build-articles.md ac80fd97a6bea6873aa06a9dc0052ad8 *tests/testthat/_snaps/build-favicons.md e4e28e4ca51fd12c6b062200a3c79d06 *tests/testthat/_snaps/build-footer.md 74f816823109729aa9c12f16dcef4b7c *tests/testthat/_snaps/build-github.md 85e3a3144debcb3b2bbf6125462d8ce0 *tests/testthat/_snaps/build-home-authors.md 8d2299d35caad375f285c8ceefae4150 *tests/testthat/_snaps/build-home-community.md 97ac715b8c17d9dca9b3d174603c05b4 *tests/testthat/_snaps/build-home-index.md f3f8e71e6684012f6938651b999c1345 *tests/testthat/_snaps/build-llm-dl.md 041f250fe7d802221e3d70f9c0acdc27 *tests/testthat/_snaps/build-llm.md 61e556ae55f36cf952394029f884b9db *tests/testthat/_snaps/build-news.md ab771cae9d479dc4781de8cf80594308 *tests/testthat/_snaps/build-quarto-articles.md b8fa5127d3bffa2735bd9fe8225dc0bb *tests/testthat/_snaps/build-redirects.md 4cdcedb78a812ce640e8238108387ef0 *tests/testthat/_snaps/build-reference-index.md 90dab12f0d57255fe7a121eefb4aa402 *tests/testthat/_snaps/build-reference.md 6143ca0e704bfe904cfbf8382ce0bef1 *tests/testthat/_snaps/build-search-docs.md 8c89eb9d79af0f7a6fab82cd7d6c79a4 *tests/testthat/_snaps/check-built.md 0bc1ccc6c61716b3f4f30399dea81d44 *tests/testthat/_snaps/check.md 03fcf6987a51e2712497d07edfa45852 *tests/testthat/_snaps/config.md 700558efec2442751e989fa3c849a8fd *tests/testthat/_snaps/development.md b4e8c693cd973d78317800e3f71bcd5c *tests/testthat/_snaps/external-deps.md cde374550da93185d319d82495a22a31 *tests/testthat/_snaps/highlight.md 37cccb26eee8c2ddcd4dadcce2a56e58 *tests/testthat/_snaps/init.md fc642152bd0f78e7061690b1bed49236 *tests/testthat/_snaps/markdown.md 7fb5aee5787971df3570b9389c753ebd *tests/testthat/_snaps/navbar-menu.md 8a20ff938fb10286f9681235c7f3c1df *tests/testthat/_snaps/navbar.md 05c20a9d2eadb5722434a5e64ec561ab *tests/testthat/_snaps/not-in-rcmcheck/build-article.md 07d0e2259f2715f381f6748784f76873 *tests/testthat/_snaps/package.md f7311fa3dc40ffca37838278693adb4e *tests/testthat/_snaps/preview.md 5906a40fe701eefb80615b34e2d98f72 *tests/testthat/_snaps/rcmdcheck/build-article.md 6e5fb10dda98068d82f5516c8957c2ab *tests/testthat/_snaps/rd-example.md 7a6582f4647a117bf9e12a8c060907ee *tests/testthat/_snaps/rd-html.md 582b9c78ea4e17cf725711377c8f6ecf *tests/testthat/_snaps/render.md 70b653aa2476a7b0306e13001932017a *tests/testthat/_snaps/repo.md 155a409d21ac65e87e1a164eb6824610 *tests/testthat/_snaps/templates.md dedbc5c6248a914216046f7cd3aec891 *tests/testthat/_snaps/theme.md 425a565cfd9cebb233a745151a73100e *tests/testthat/_snaps/topics-external.md 3532028ce238eb52545d54e9423152a8 *tests/testthat/_snaps/topics.md 3348176674ba4aa1747e88ca23f943cf *tests/testthat/_snaps/tweak-homepage.md 25e6e274b5a9870ac48571c45dfdbc65 *tests/testthat/_snaps/tweak-tabset.md fac8fe2d0ebad1ae9f83df595e0ce76b *tests/testthat/_snaps/tweak-tags.md bf0162b1b1765b2b92aad86783c3ef45 *tests/testthat/_snaps/usage.md 3a6f8b805da753ec980e7f2701e9aec2 *tests/testthat/_snaps/utils-fs.md 7b44e56c5112271e83d79663d8bea30e *tests/testthat/assets/-find-assets.html 8ba5b489bcd50e8ec4f297593c276c2a *tests/testthat/assets/articles-images/DESCRIPTION 0534fdafdbad1ab9cdee7473880cd993 *tests/testthat/assets/articles-images/README.md 9fbe5b7d712dc924a19010f9cf32e750 *tests/testthat/assets/articles-images/_pkgdown.yml 10ec14048dae2c7313542736845d6f9f *tests/testthat/assets/articles-images/docs/articles/another-kitten.jpg effa016b0241915948bff14e6c64f333 *tests/testthat/assets/articles-images/docs/articles/kitten.html 25800a2464eb26fd916872b93fda2773 *tests/testthat/assets/articles-images/docs/articles/kitten_files/figure-html/magick-1.png e257fff4113e5a4b3008c556052f457f *tests/testthat/assets/articles-images/docs/articles/kitten_files/figure-html/plot-1.jpg c3f6623e38ac7c247d0173d972ba6aea *tests/testthat/assets/articles-images/docs/reference/figures/kitten.jpg c3f6623e38ac7c247d0173d972ba6aea *tests/testthat/assets/articles-images/man/figures/kitten.jpg 08511ffc2e39637dfb78c61713c1d01d *tests/testthat/assets/articles-images/man/kitten.Rd 10ec14048dae2c7313542736845d6f9f *tests/testthat/assets/articles-images/vignettes/another-kitten.jpg 39ff937065d8f892263e6a5def85451d *tests/testthat/assets/articles-images/vignettes/kitten.Rmd 0f28f7215a3207baa4defa481a925d4f *tests/testthat/assets/figure/DESCRIPTION 9fbe5b7d712dc924a19010f9cf32e750 *tests/testthat/assets/figure/_pkgdown.yml 4d450d94a52928bc83ae0d161cf9d587 *tests/testthat/assets/figure/man/figure.Rd bbace9b1a4aa8108214a6097457f1d04 *tests/testthat/assets/figure/vignettes/figures.Rmd c3f6623e38ac7c247d0173d972ba6aea *tests/testthat/assets/kitten.jpg bf1f8f217201014e17d814f3cdd6c615 *tests/testthat/assets/llm.html 847e4eab3395d08167eb6e4c6fc17812 *tests/testthat/assets/reference-fail/DESCRIPTION b1e120dca82a29d5d40c7505dc7e7e44 *tests/testthat/assets/reference-fail/NAMESPACE 850eb905cdd788797aed8f9ebb4b964d *tests/testthat/assets/reference-fail/R/f.R a315840c7c60841e105270f40923ac7c *tests/testthat/assets/reference-fail/man/f.Rd 9436efe6d9f02cdeade7dd29c1b92656 *tests/testthat/assets/reference-html-dep/DESCRIPTION 11d4074aae3b53656376ed92581f1fe9 *tests/testthat/assets/reference-html-dep/NAMESPACE 1cfc8be4f8cc64383042092f626e4259 *tests/testthat/assets/reference-html-dep/R/funs.R a626ef04b37b4659aa5a1d46b80fc1cb *tests/testthat/assets/reference-html-dep/_pkgdown.yml e579ace400ecf275f93f77478312fb44 *tests/testthat/assets/reference-html-dep/man/a.Rd 328b98c4f7216ad0b5d23b1605d111c2 *tests/testthat/assets/reference-language/one/DESCRIPTION 53ecc70f1200da6a7e663d3a2c7c6992 *tests/testthat/assets/reference-language/two/DESCRIPTION 847e4eab3395d08167eb6e4c6fc17812 *tests/testthat/assets/reference-pre-post/DESCRIPTION 43d2ff36c439c2a0f21b078e260f50df *tests/testthat/assets/reference-pre-post/pkgdown/post-reference.R 26813d0f7f8e272af05102662163c53b *tests/testthat/assets/reference-pre-post/pkgdown/pre-reference.R e14fc358b147815d9a8807b93a35a08b *tests/testthat/assets/reference-selector/DESCRIPTION 03a62fe3fa9a58a0321495fb291e4d5c *tests/testthat/assets/reference-selector/NAMESPACE faca304d0486d794a2506709dd46c0b2 *tests/testthat/assets/reference-selector/NEWS.md 490567409e22b2e559a8e5b7d7f3de65 *tests/testthat/assets/reference-selector/R/funs.R a626ef04b37b4659aa5a1d46b80fc1cb *tests/testthat/assets/reference-selector/_pkgdown.yml 14f1c6c50b986edcbbadda0e8d855af2 *tests/testthat/assets/reference-selector/man/A.Rd d1923bdd40f3626c9de781acb053456c *tests/testthat/assets/reference-selector/man/matches.Rd e14fc358b147815d9a8807b93a35a08b *tests/testthat/assets/reference/DESCRIPTION e61830d6a1d246c9887de8cb4c9bab7c *tests/testthat/assets/reference/NAMESPACE 1f948dfacf3d7ba96c175c9c0a08ab15 *tests/testthat/assets/reference/R/funs.R a626ef04b37b4659aa5a1d46b80fc1cb *tests/testthat/assets/reference/_pkgdown.yml 0e0724089bbdf105db1b51c8dfde8a5f *tests/testthat/assets/reference/man/a.Rd 6c8954c41172f6586c5e4723b67cf461 *tests/testthat/assets/reference/man/b.Rd 7f2d535ded2a310396ed40f3fa0342ae *tests/testthat/assets/reference/man/c.Rd 82bcef0710eefb001571557b5c7dc976 *tests/testthat/assets/reference/man/e.Rd d38e65103dbf88388891f12f465190b2 *tests/testthat/assets/reference/man/f.Rd 06841ddd2937d03fb976eabb50aeeddf *tests/testthat/assets/reference/man/g.Rd b7db9245402493ac1473b6830af151d2 *tests/testthat/assets/reference/man/help.Rd 638a76ef2dd9af66ad2043814f781b57 *tests/testthat/assets/sitemaps-schema-0.9.xsd 0f28f7215a3207baa4defa481a925d4f *tests/testthat/assets/templates-local/DESCRIPTION b51f979e9bd14376f1f80349d9cd1997 *tests/testthat/assets/templates-local/pkgdown/templates/content-article.html 40e2285974dda0a37186b53ebca56f6d *tests/testthat/assets/templates-local/pkgdown/templates/footer-article.html 869c46a3d503242305c0865454a2dc67 *tests/testthat/helper.R 787b87c807eac66f69e430c450a7bc02 *tests/testthat/test-build-article.R f28d1eb8badd0b6fa3c825bb9a4a3635 *tests/testthat/test-build-articles.R 31c51e83f4b6f7f7e869588666d0457e *tests/testthat/test-build-favicons.R 930c58188ad9446eb0371e6b17491f3c *tests/testthat/test-build-footer.R 203703698cd9c937b5da3e57581785e4 *tests/testthat/test-build-github.R 06d74ab7f96257d0c3391c8cda1216b9 *tests/testthat/test-build-home-authors.R 2e2417a3196e27e899d16dcd80bec92b *tests/testthat/test-build-home-community.R 5c4ca4d37580dad7aed0770a8f82e6e6 *tests/testthat/test-build-home-index.R 4f6d1c11125fcc3d17ddf6ec30c2dd3e *tests/testthat/test-build-home-license.R 8654913b8d790c8bc887ac2cba00ec8e *tests/testthat/test-build-home-md.R acb583291fbccdae628cbb63c18d4e3b *tests/testthat/test-build-home.R 20854bc1676ac912c73c9b0bc8321910 *tests/testthat/test-build-llm-dl.R 77f31bb3664f039bda677d2573d3f82f *tests/testthat/test-build-llm.R 493f955fb5d70b13a4fce28d0b8329d1 *tests/testthat/test-build-logo.R a484818531d40a1fecd7cbb7743bbe5a *tests/testthat/test-build-news.R ea1c1f170e526e7ea3acb7d0ec99ce07 *tests/testthat/test-build-quarto-articles.R ea4d581bd3e3d93dffabf8a2d5552359 *tests/testthat/test-build-redirects.R b83cfa3dc7e1e9105dcbd9e210e4bed2 *tests/testthat/test-build-reference-index.R ef2fd188f226e137c803e385cdd2bc2a *tests/testthat/test-build-reference.R eb5e8abec843a3d82a7b084d4c58aa7b *tests/testthat/test-build-search-docs.R 6bcf884631ebe9b747668ecc8882c5a5 *tests/testthat/test-build-tutorials.R 7952d34a86f18d484c23aa81c7106008 *tests/testthat/test-build.R b9f63bd40496459fa8b6ebc3ddb683a8 *tests/testthat/test-check-built.R 96afc100c23b5b39fbb1c0319ccd497d *tests/testthat/test-check.R a5d3e7880fb9258ee91f479b5a32c0da *tests/testthat/test-config.R d74f456c6ba687026239c4e315542dd0 *tests/testthat/test-deploy-site.R 5d5509a649f773fd528895c888bcac3c *tests/testthat/test-development.R 37f25e7cb619d96b80bd8c76f9888b0d *tests/testthat/test-external-deps.R a9c0d7dca05f03d0d982aac5a0492f23 *tests/testthat/test-figure.R f730676627afbf94b47b76c76bbf59e7 *tests/testthat/test-highlight.R 5574d50f1932a64782cf95168c571f0b *tests/testthat/test-html-build.R fff1e237f6aebf093d8c73a1df7e16bd *tests/testthat/test-init.R 69b5a17f3f913b98c1e52831749507d9 *tests/testthat/test-markdown.R 853be04db38ee7ffb5cb37a40bcd3c7c *tests/testthat/test-navbar-menu.R 111cdb5724976c0f4e91de5b9fca2716 *tests/testthat/test-navbar.R 7a1f3a452817b94da505670c85e219c9 *tests/testthat/test-package.R 5dc2286701a77f0c0168a4cde29f7d1d *tests/testthat/test-pkgdown_print.R 6566330395ac78758d8fe57db655823f *tests/testthat/test-preview.R 0fdb55c306e8a788ffc200e57507675c *tests/testthat/test-rd-data.R 77592aabeea233041b0196ef3b73ae05 *tests/testthat/test-rd-example.R 2b9c1d30b6674542bdaf5ca176f62349 *tests/testthat/test-rd-html.R eec82dcb53db37abdc921f171251d693 *tests/testthat/test-render.R 28404b265a22ddeb6f898bfa7928b6f5 *tests/testthat/test-repo.R 54f7536c75cf0e8be0a4b4210a0691b6 *tests/testthat/test-templates.R 289f2a228285c7f472cac939c49cb4c6 *tests/testthat/test-theme.R b347ed944c4ee7e84fb4c0f6b1dc238c *tests/testthat/test-topics-external.R cbaca1581feab789ca5906879c7fdf19 *tests/testthat/test-topics.R 7b0c643e62ea38faff89b95342f5863a *tests/testthat/test-tweak-homepage.R 2376e0863a8f8ef647062d1a8085c73f *tests/testthat/test-tweak-navbar.R df7881969cd93e4b375944b0e7bb93b9 *tests/testthat/test-tweak-page.R dcb714ca370815841ad41fa9c0804a1b *tests/testthat/test-tweak-reference.R 7b65c9c3f6898440d00d79bdffd7f111 *tests/testthat/test-tweak-tabset.R dcabaa4cb7873ce7e0906308f6b71627 *tests/testthat/test-tweak-tags.R c5e7e8fa37b89639a1682e81508e7dfe *tests/testthat/test-usage.R 55a91821f0f195b2f868270061e0935c *tests/testthat/test-utils-fs.R ccce0aa9007c180dcf206dfa886dade5 *tests/testthat/test-utils.R 73dea842d77d620f63b0ecf85283534b *vignettes/accessibility.Rmd 1c1582a54c2610ece8a0321ea9637caa *vignettes/customise.Rmd 258af8e6bbf38600816f718ba0cce89f *vignettes/how-to-update-released-site.Rmd 70383c38cd3188fb0079ec4f67ff2ade *vignettes/linking.Rmd ad6f0ff3108d23d4fa6de0dfadcf6e36 *vignettes/metadata.Rmd 1e11c14c42755cd47b4bc7b3551f1158 *vignettes/pitbull.jpg 6207e6c15e6bf614e0b47a41a56174d3 *vignettes/pkgdown.Rmd 37ef9a8104d68a68fd7dcac1abc5b10e *vignettes/quarto.qmd 1e677b785c965ccc22aa9ad079051765 *vignettes/shar-pei.jpg 4ee979c4c83a85a557030d69863e9d13 *vignettes/test/bacon.jpg 67624f50ef5e6dd6e984bc57792fde16 *vignettes/test/jss.Rmd bc1703f56a03b0f237091ab4426ce580 *vignettes/test/jss.bib 9e13367ef4850e3c0d4fa27c607e2137 *vignettes/test/jss.bst 4d890e205f4c9db08835f10b6bb3febd *vignettes/test/jss.cls 7a2d50683e0eb1babb7d047ca2007ee6 *vignettes/test/jss.log 9c67cc56ac2c896944706843d90e4766 *vignettes/test/long-toc.Rmd 6ee7d1c05a1f58328015aab801a6c071 *vignettes/test/pdf.Rmd f650f97d9b766091d61238e3e270d40a *vignettes/test/quarto-features.qmd c3484bacd61918761324d9c1415edb57 *vignettes/test/rendering.Rmd 107c3fe335059d0162ca671a1611b937 *vignettes/test/short.Rmd 47ece2e49e5c0333677fc34e044d8257 *vignettes/test/test.txt 27ec3f090077fb6af7bf578d6fdf5346 *vignettes/test/widgets.Rmd 494a3aa83a9a9bd2443539c3853b737b *vignettes/translations.Rmd pkgdown/po/0000755000176200001440000000000015100735002012332 5ustar liggesuserspkgdown/po/R-dk.po0000644000176200001440000001353415075503660013513 0ustar liggesusersmsgid "" msgstr "" "Project-Id-Version: pkgdown 2.0.1.9000\n" "POT-Creation-Date: 2025-10-17 18:07-0600\n" "PO-Revision-Date: 2021-12-20 18:48+0100\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" "Language: dk\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: build-404.R:12 msgid "Page not found (404)" msgstr "Side ikke fundet (404)" #: build-404.R:13 msgid "Content not found. Please use links in the navbar." msgstr "Indhold ikke fundet. Brug venligst links i menuen" #: build-articles.R:281 navbar.R:193 navbar.R:203 navbar.R:232 msgid "Articles" msgstr "Artikler" #: build-articles.R:436 msgid "All vignettes" msgstr "Alle vignetter" #: build-footer.R:42 msgid "Developed by" msgstr "Udviklet af" #: build-footer.R:49 msgid "Site built with pkgdown %s." msgstr "Side bygget med pkgdown %s." #: build-home-authors.R:12 msgid "Authors and Citation" msgstr "Forfattere og citation" #: build-home-authors.R:110 msgid "More about authors..." msgstr "Mere om forfatterene" #: build-home-authors.R:113 msgid "Developers" msgstr "Udviklere" #: build-home-authors.R:220 msgid "author" msgstr "forfatter" #: build-home-authors.R:221 msgid "compiler" msgstr "compiler" #: build-home-authors.R:222 msgid "contractor" msgstr "leverandør" #: build-home-authors.R:223 msgid "contributor" msgstr "Bidragsyder" #: build-home-authors.R:224 msgid "copyright holder" msgstr "Indehaver af ophavsret" #: build-home-authors.R:225 msgid "maintainer" msgstr "maintainer" #: build-home-authors.R:226 msgid "data contributor" msgstr "dataleverandør" #: build-home-authors.R:227 msgid "funder" msgstr "bevilgingsgiver" #: build-home-authors.R:228 msgid "reviewer" msgstr "bedømmer" #: build-home-authors.R:229 msgid "thesis advisor" msgstr "vejleder" #: build-home-authors.R:230 msgid "translator" msgstr "oversætter" #: build-home-authors.R:286 render.R:108 msgid "Citation" msgstr "Reference" #: build-home-authors.R:287 msgid "Citing %s" msgstr "Citér %s" #: build-home-community.R:22 msgid "Contributing guide" msgstr "Guide til bidragsydere" #: build-home-community.R:26 msgid "Code of conduct" msgstr "Etisk regelsæt" #: build-home-community.R:30 msgid "Getting help" msgstr "Få hjælp" #: build-home-community.R:37 msgid "Community" msgstr "Fællesskab" #: build-home-index.R:118 msgid "Dev Status" msgstr "Udviklingsstatus" #: build-home-index.R:190 msgid "View on %s" msgstr "Se på %s" #: build-home-index.R:191 msgid "Browse source code" msgstr "Se kildekode" #: build-home-index.R:192 msgid "Report a bug" msgstr "Rapportér en fejl" #: build-home-index.R:196 msgid "Links" msgstr "Links" #: build-home-index.R:201 render.R:110 msgid "Table of contents" msgstr "Indholdsfortegnelse" #: build-home-license.R:14 build-home-license.R:36 msgid "License" msgstr "Licens" #: build-home-license.R:31 msgid "Full license" msgstr "Fuld licens" #: build-news.R:101 build-news.R:262 build-news.R:266 msgid "Changelog" msgstr "Ændringslog" #: build-news.R:128 msgid "Version %s" msgstr "Version %s" #: build-news.R:140 build-news.R:257 msgid "News" msgstr "Nyheder" #: build-news.R:259 msgid "Releases" msgstr "Udgivelser" #: build-news.R:314 msgid "CRAN release: %s" msgstr "CRAN udgivelse: %s" #: build-reference-index.R:23 msgid "Package index" msgstr "Pakke indeks" #: build-reference-index.R:187 msgid "All functions" msgstr "Alle funktioner" #: build-reference.R:377 msgid "Usage" msgstr "Brug" #: build-tutorials.R:49 navbar.R:158 msgid "Tutorials" msgstr "Vejledning" #: development.R:82 msgid "Released version" msgstr "Udgivet version" #: development.R:83 msgid "In-development version" msgstr "Version under udvikling" #: development.R:84 msgid "Unreleased version" msgstr "Ikke-udgivet version" #: navbar-menu.R:212 msgid "Search site" msgstr "Søg" #: navbar-menu.R:213 msgid "Search for" msgstr "Søg" #: navbar.R:135 msgid "Reference" msgstr "Reference" #: navbar.R:146 msgid "Light switch" msgstr "Lyskontakt" #: navbar.R:149 msgid "Light" msgstr "Lys" #: navbar.R:150 msgid "Dark" msgstr "Mørk" #: navbar.R:151 msgid "Auto" msgstr "Auto" #: navbar.R:187 msgid "Get started" msgstr "Kom igang" #: navbar.R:228 msgid "More articles..." msgstr "Flere artikler..." #: package.R:317 msgid "deprecated" msgstr "udfaset" #: package.R:318 msgid "superseded" msgstr "erstattet" #: package.R:319 msgid "experimental" msgstr "eksperimentel" #: package.R:320 msgid "stable" msgstr "stabil" #: rd-data.R:23 msgid "Details" msgstr "Detaljer" #: rd-data.R:27 msgid "Description" msgstr "Beskrivelse" #: rd-data.R:31 msgid "References" msgstr "Referencer" #: rd-data.R:35 render.R:103 msgid "Source" msgstr "Kilde" #: rd-data.R:39 msgid "Format" msgstr "Format" #: rd-data.R:43 msgid "Note" msgstr "Note" #: rd-data.R:47 msgid "Author" msgstr "Forfatter" #: rd-data.R:51 msgid "See also" msgstr "Se også" #: rd-data.R:67 msgid "Arguments" msgstr "Argumenter" #: rd-data.R:75 msgid "Value" msgstr "Værdi" #: render.R:100 msgid "Skip to contents" msgstr "Spring til indhold" #: render.R:101 msgid "Toggle navigation" msgstr "Slå navigation til og fra" #: render.R:102 msgid "On this page" msgstr "På denne side" #: render.R:104 msgid "Abstract" msgstr "Sammenfatning" #: render.R:105 msgid "Authors" msgstr "Forfattere" #: render.R:106 msgid "Version" msgstr "Version" #: render.R:107 msgid "Examples" msgstr "Eksempler" #: render.R:109 msgid "Additional details" msgstr "Yderligere detaljer" #: render.R:111 msgid "Site navigation" msgstr "Navigation på siden" #: repo.R:37 msgid "Source:" msgstr "Kilde:" #: tweak-homepage.R:68 msgid "Dev status" msgstr "Udviklingsstatus" #: usage.R:52 msgid "# Default %s method" msgstr "# Standard %s metode" #: usage.R:54 msgid "# %s method for class '%s'" msgstr "# %s metode for '%s'" #~ msgid "Function reference" #~ msgstr "Funktionsoversigt" pkgdown/po/R-nl.po0000644000176200001440000001360215100735002013504 0ustar liggesusersmsgid "" msgstr "" "Project-Id-Version: pkgdown 2.0.9.9000\n" "POT-Creation-Date: 2025-10-20 18:57-0600\n" "PO-Revision-Date: 2025-10-16 23:28+1\n" "Last-Translator: Pepijn de Vries \n" "Language-Team: @pepijn-devries\n" "Language: nl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: build-404.R:12 msgid "Page not found (404)" msgstr "Pagina niet gevonden (404)" #: build-404.R:13 msgid "Content not found. Please use links in the navbar." msgstr "Inhoud niet gevonden. Gebruik alstublieft de links in de navigatiebalk." #: build-articles.R:281 navbar.R:193 navbar.R:203 navbar.R:232 msgid "Articles" msgstr "Artikelen" #: build-articles.R:436 msgid "All vignettes" msgstr "Alle vignetten" #: build-footer.R:42 msgid "Developed by" msgstr "Ontwikkeld door" #: build-footer.R:49 msgid "Site built with pkgdown %s." msgstr "Website gebouwd met pkgdown %s." #: build-home-authors.R:12 msgid "Authors and Citation" msgstr "Auteurs en citatie" #: build-home-authors.R:110 msgid "More about authors..." msgstr "Meer over de auteurs..." #: build-home-authors.R:113 msgid "Developers" msgstr "Ontwikkelaars" #: build-home-authors.R:220 msgid "author" msgstr "auteur" #: build-home-authors.R:221 msgid "compiler" msgstr "samensteller" #: build-home-authors.R:222 msgid "contractor" msgstr "aannemer" #: build-home-authors.R:223 msgid "contributor" msgstr "bijdrager" #: build-home-authors.R:224 msgid "copyright holder" msgstr "auteursrechthebbende" #: build-home-authors.R:225 msgid "maintainer" msgstr "beheerder" #: build-home-authors.R:226 msgid "data contributor" msgstr "databijdrager" #: build-home-authors.R:227 msgid "funder" msgstr "financier" #: build-home-authors.R:228 msgid "reviewer" msgstr "recensent" #: build-home-authors.R:229 msgid "thesis advisor" msgstr "scriptiebegeleider" #: build-home-authors.R:230 msgid "translator" msgstr "vertaler" #: build-home-authors.R:286 render.R:108 msgid "Citation" msgstr "Citatie" #: build-home-authors.R:287 msgid "Citing %s" msgstr "%s citeren" #: build-home-community.R:22 msgid "Contributing guide" msgstr "Gids om bij te dragen" #: build-home-community.R:26 msgid "Code of conduct" msgstr "Gedragscode" #: build-home-community.R:30 msgid "Getting help" msgstr "Hulp krijgen" #: build-home-community.R:37 msgid "Community" msgstr "Gemeenschap" #: build-home-index.R:118 msgid "Dev Status" msgstr "Ontwikkelingsstatus" #: build-home-index.R:190 msgid "View on %s" msgstr "Op %s bekijken" #: build-home-index.R:191 msgid "Browse source code" msgstr "Broncode bekijken" #: build-home-index.R:192 msgid "Report a bug" msgstr "Bug melden" #: build-home-index.R:196 msgid "Links" msgstr "Links" #: build-home-index.R:201 render.R:110 msgid "Table of contents" msgstr "Inhoudsopgave" #: build-home-license.R:14 build-home-license.R:36 msgid "License" msgstr "Licentie" #: build-home-license.R:31 msgid "Full license" msgstr "Volledige licentie" #: build-news.R:101 build-news.R:262 build-news.R:266 msgid "Changelog" msgstr "Wijzigingslogboek" #: build-news.R:128 msgid "Version %s" msgstr "Versie %s" #: build-news.R:140 build-news.R:257 msgid "News" msgstr "Nieuws" #: build-news.R:259 msgid "Releases" msgstr "Uitgaven" #: build-news.R:314 msgid "CRAN release: %s" msgstr "CRAN uitgave: %s" #: build-reference-index.R:23 msgid "Package index" msgstr "Pakketindex" #: build-reference-index.R:187 msgid "All functions" msgstr "Alle functies" #: build-reference.R:377 msgid "Usage" msgstr "Gebruik" #: build-tutorials.R:49 navbar.R:158 msgid "Tutorials" msgstr "Handleidingen" #: development.R:82 msgid "Released version" msgstr "Uitgebrachte versie" #: development.R:83 msgid "In-development version" msgstr "Versie in ontwikkeling" #: development.R:84 msgid "Unreleased version" msgstr "Onuitgebrachte versie" #: navbar-menu.R:212 msgid "Search site" msgstr "Zoeken op site" #: navbar-menu.R:213 msgid "Search for" msgstr "Zoeken naar" #: navbar.R:135 msgid "Reference" msgstr "Referentie" #: navbar.R:146 msgid "Light switch" msgstr "Lichtknop" #: navbar.R:149 msgid "Light" msgstr "Licht" #: navbar.R:150 msgid "Dark" msgstr "Donker" #: navbar.R:151 msgid "Auto" msgstr "Automatisch" #: navbar.R:187 msgid "Get started" msgstr "Beginnen" #: navbar.R:228 msgid "More articles..." msgstr "Meer artikelen..." #: package.R:317 msgid "deprecated" msgstr "verouderd" #: package.R:318 msgid "superseded" msgstr "vervangen" #: package.R:319 msgid "experimental" msgstr "experimenteel" #: package.R:320 msgid "stable" msgstr "stabiel" #: rd-data.R:23 msgid "Details" msgstr "Details" #: rd-data.R:27 msgid "Description" msgstr "Omschrijving" #: rd-data.R:31 msgid "References" msgstr "Referenties" #: rd-data.R:35 render.R:103 msgid "Source" msgstr "Bron" #: rd-data.R:39 msgid "Format" msgstr "Formaat" #: rd-data.R:43 msgid "Note" msgstr "Aantekening" #: rd-data.R:47 msgid "Author" msgstr "Auteur" #: rd-data.R:51 msgid "See also" msgstr "Zie ook" #: rd-data.R:67 msgid "Arguments" msgstr "Argumenten" #: rd-data.R:75 msgid "Value" msgstr "Waarde" #: render.R:100 msgid "Skip to contents" msgstr "Ga naar inhoud" #: render.R:101 msgid "Toggle navigation" msgstr "Schakel navigatie in" #: render.R:102 msgid "On this page" msgstr "Op deze pagina" #: render.R:104 msgid "Abstract" msgstr "Samenvatting" #: render.R:105 msgid "Authors" msgstr "Auteurs" #: render.R:106 msgid "Version" msgstr "Versie" #: render.R:107 msgid "Examples" msgstr "Voorbeelden" #: render.R:109 msgid "Additional details" msgstr "Aanvullende details" #: render.R:111 msgid "Site navigation" msgstr "Website navigatie" #: repo.R:37 msgid "Source:" msgstr "Bron:" #: tweak-homepage.R:68 msgid "Dev status" msgstr "Ontwikkelingsstatus" #: usage.R:52 msgid "# Default %s method" msgstr "# Standaard %s methode" #: usage.R:54 msgid "# %s method for class '%s'" msgstr "# %s methode voor klasse '%s'" pkgdown/po/R-ca.po0000644000176200001440000001416015075503625013475 0ustar liggesusersmsgid "" msgstr "" "Project-Id-Version: pkgdown 2.0.6.9000\n" "POT-Creation-Date: 2025-10-17 18:07-0600\n" "PO-Revision-Date: 2024-06-16 09:24+0200\n" "Last-Translator: Joan Maspons \n" "Language-Team: Catalan <>\n" "Language: ca\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Generator: Lokalize 24.05.0\n" #: build-404.R:12 msgid "Page not found (404)" msgstr "No s'ha trobat la pàgina (404)" #: build-404.R:13 msgid "Content not found. Please use links in the navbar." msgstr "No s'ha trobat el contingut. Useu els enllaços de la barra de navegació." #: build-articles.R:281 navbar.R:193 navbar.R:203 navbar.R:232 msgid "Articles" msgstr "Articles" #: build-articles.R:436 msgid "All vignettes" msgstr "Totes les vinyetes" #: build-footer.R:42 msgid "Developed by" msgstr "Desenvolupat per" #: build-footer.R:49 msgid "Site built with pkgdown %s." msgstr "Lloc construït amb pkgdown %s." #: build-home-authors.R:12 msgid "Authors and Citation" msgstr "Autors i citació" #: build-home-authors.R:110 msgid "More about authors..." msgstr "Més sobre els autors..." #: build-home-authors.R:113 msgid "Developers" msgstr "Desenvolupadors" #: build-home-authors.R:220 msgid "author" msgstr "autor" #: build-home-authors.R:221 msgid "compiler" msgstr "compilador" #: build-home-authors.R:222 msgid "contractor" msgstr "contractista" #: build-home-authors.R:223 msgid "contributor" msgstr "col·laborador" #: build-home-authors.R:224 msgid "copyright holder" msgstr "titular dels drets d'autor" #: build-home-authors.R:225 msgid "maintainer" msgstr "mantenidor" #: build-home-authors.R:226 msgid "data contributor" msgstr "col·laborador de dades" #: build-home-authors.R:227 msgid "funder" msgstr "finançador" #: build-home-authors.R:228 msgid "reviewer" msgstr "revisor" #: build-home-authors.R:229 msgid "thesis advisor" msgstr "supervisor de tesi" #: build-home-authors.R:230 msgid "translator" msgstr "traductor" #: build-home-authors.R:286 render.R:108 msgid "Citation" msgstr "Citació" #: build-home-authors.R:287 msgid "Citing %s" msgstr "Citant %s" #: build-home-community.R:22 msgid "Contributing guide" msgstr "Guia per contribuir" #: build-home-community.R:26 msgid "Code of conduct" msgstr "Codi de conducta" #: build-home-community.R:30 msgid "Getting help" msgstr "Obtenció d'ajuda" #: build-home-community.R:37 msgid "Community" msgstr "Comunitat" #: build-home-index.R:118 msgid "Dev Status" msgstr "Estat de desenvolupament" #: build-home-index.R:190 msgid "View on %s" msgstr "Mostra a %s" #: build-home-index.R:191 msgid "Browse source code" msgstr "Navega pel codi font" #: build-home-index.R:192 msgid "Report a bug" msgstr "Informa d'un error" #: build-home-index.R:196 msgid "Links" msgstr "Enllaços" #: build-home-index.R:201 render.R:110 msgid "Table of contents" msgstr "Taula de continguts" #: build-home-license.R:14 build-home-license.R:36 msgid "License" msgstr "Llicència" #: build-home-license.R:31 msgid "Full license" msgstr "Llicència completa" #: build-news.R:101 build-news.R:262 build-news.R:266 msgid "Changelog" msgstr "Registre de canvis" #: build-news.R:128 msgid "Version %s" msgstr "Versió %s" #: build-news.R:140 build-news.R:257 msgid "News" msgstr "Novetats" #: build-news.R:259 msgid "Releases" msgstr "Versions" #: build-news.R:314 msgid "CRAN release: %s" msgstr "Versió del CRAN: %s" #: build-reference-index.R:23 msgid "Package index" msgstr "Índex del paquet" #: build-reference-index.R:187 msgid "All functions" msgstr "Totes les funcions" #: build-reference.R:377 msgid "Usage" msgstr "Ús" #: build-tutorials.R:49 navbar.R:158 msgid "Tutorials" msgstr "Guies d'aprenentatge" #: development.R:82 msgid "Released version" msgstr "Versió publicada" #: development.R:83 msgid "In-development version" msgstr "Versió en desenvolupament" #: development.R:84 msgid "Unreleased version" msgstr "Versió no publicada" #: navbar-menu.R:212 msgid "Search site" msgstr "Cerca al lloc" #: navbar-menu.R:213 msgid "Search for" msgstr "Cerca" #: navbar.R:135 msgid "Reference" msgstr "Referència" #: navbar.R:146 msgid "Light switch" msgstr "Interruptor de color" #: navbar.R:149 msgid "Light" msgstr "Clar" #: navbar.R:150 msgid "Dark" msgstr "Fosc" #: navbar.R:151 msgid "Auto" msgstr "Automàtic" #: navbar.R:187 msgid "Get started" msgstr "Comenceu" #: navbar.R:228 msgid "More articles..." msgstr "Més articles..." #: package.R:317 msgid "deprecated" msgstr "obsoleta" #: package.R:318 msgid "superseded" msgstr "reemplaçada" #: package.R:319 msgid "experimental" msgstr "experimental" #: package.R:320 msgid "stable" msgstr "estable" #: rd-data.R:23 msgid "Details" msgstr "Detalls" #: rd-data.R:27 msgid "Description" msgstr "Descripció" #: rd-data.R:31 msgid "References" msgstr "Referències" #: rd-data.R:35 render.R:103 msgid "Source" msgstr "Font" #: rd-data.R:39 msgid "Format" msgstr "Format" #: rd-data.R:43 msgid "Note" msgstr "Nota" #: rd-data.R:47 msgid "Author" msgstr "Autor" #: rd-data.R:51 msgid "See also" msgstr "Vegeu també" #: rd-data.R:67 msgid "Arguments" msgstr "Paràmetres" #: rd-data.R:75 msgid "Value" msgstr "Valor" #: render.R:100 msgid "Skip to contents" msgstr "Salta als continguts" #: render.R:101 msgid "Toggle navigation" msgstr "Commuta la navegació" #: render.R:102 msgid "On this page" msgstr "En aquesta pàgina" #: render.R:104 msgid "Abstract" msgstr "Resum" #: render.R:105 msgid "Authors" msgstr "Autors" #: render.R:106 msgid "Version" msgstr "Versió" #: render.R:107 msgid "Examples" msgstr "Exemples" #: render.R:109 msgid "Additional details" msgstr "Detalls addicionals" #: render.R:111 msgid "Site navigation" msgstr "Navegació del lloc" #: repo.R:37 msgid "Source:" msgstr "Font:" #: tweak-homepage.R:68 msgid "Dev status" msgstr "Estat de desenvolupament" #: usage.R:52 msgid "# Default %s method" msgstr "# Mètode %s per defecte" #: usage.R:54 msgid "# %s method for class '%s'" msgstr "# Mètode %s per a la classe «%s»" #~ msgid "Function reference" #~ msgstr "Llistat de funcions" pkgdown/po/R-fr.po0000644000176200001440000001431715075503625013525 0ustar liggesusersmsgid "" msgstr "" "Project-Id-Version: pkgdown 2.0.9.9000\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-10-17 18:07-0600\n" "PO-Revision-Date: 2024-06-15 20:28-0400\n" "Last-Translator: J.P. Le Cavalier \n" "Language-Team: fr\n" "Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: potools 0.2.2\n" #: build-404.R:12 msgid "Page not found (404)" msgstr "Page introuvable (404)" #: build-404.R:13 msgid "Content not found. Please use links in the navbar." msgstr "" "Contenu introuvable. Merci d'utiliser les liens de la barre de navigation." #: build-articles.R:281 navbar.R:193 navbar.R:203 navbar.R:232 msgid "Articles" msgstr "Articles" #: build-articles.R:436 msgid "All vignettes" msgstr "Tous les articles" #: build-footer.R:42 msgid "Developed by" msgstr "Développé par" #: build-footer.R:49 msgid "Site built with pkgdown %s." msgstr "Site créé avec pkgdown %s." #: build-home-authors.R:12 msgid "Authors and Citation" msgstr "Auteur·rice·s et Citation" #: build-home-authors.R:110 msgid "More about authors..." msgstr "À propos des auteur·rice·s..." #: build-home-authors.R:113 msgid "Developers" msgstr "Développeur·se·s" #: build-home-authors.R:220 msgid "author" msgstr "auteur·rice" #: build-home-authors.R:221 msgid "compiler" msgstr "compilateur·rice" #: build-home-authors.R:222 msgid "contractor" msgstr "fournisseur·se" #: build-home-authors.R:223 msgid "contributor" msgstr "contributeur·rice" #: build-home-authors.R:224 msgid "copyright holder" msgstr "titulaire des droits d'auteur" #: build-home-authors.R:225 msgid "maintainer" msgstr "mainteneur·se" #: build-home-authors.R:226 msgid "data contributor" msgstr "contributeur·rice des données" #: build-home-authors.R:227 msgid "funder" msgstr "fondateur·rice" #: build-home-authors.R:228 msgid "reviewer" msgstr "réviseur·se" #: build-home-authors.R:229 msgid "thesis advisor" msgstr "directeur·rice de thèse" #: build-home-authors.R:230 msgid "translator" msgstr "traducteur·rice" #: build-home-authors.R:286 render.R:108 msgid "Citation" msgstr "Citation" #: build-home-authors.R:287 msgid "Citing %s" msgstr "Citer %s" #: build-home-community.R:22 msgid "Contributing guide" msgstr "Guide de contribution" #: build-home-community.R:26 msgid "Code of conduct" msgstr "Code de conduite" #: build-home-community.R:30 msgid "Getting help" msgstr "Obtenir de l'aide" #: build-home-community.R:37 msgid "Community" msgstr "Communauté" #: build-home-index.R:118 msgid "Dev Status" msgstr "Statut de développement" #: build-home-index.R:190 msgid "View on %s" msgstr "Voir sur %s" #: build-home-index.R:191 msgid "Browse source code" msgstr "Naviguer le code source" #: build-home-index.R:192 msgid "Report a bug" msgstr "Signaler un bogue" #: build-home-index.R:196 msgid "Links" msgstr "Liens" #: build-home-index.R:201 render.R:110 msgid "Table of contents" msgstr "Table des matières" #: build-home-license.R:14 build-home-license.R:36 msgid "License" msgstr "Licence" #: build-home-license.R:31 msgid "Full license" msgstr "Licence complète" #: build-news.R:101 build-news.R:262 build-news.R:266 msgid "Changelog" msgstr "Changements" #: build-news.R:128 msgid "Version %s" msgstr "Version %s" #: build-news.R:140 build-news.R:257 msgid "News" msgstr "Nouveautés" #: build-news.R:259 msgid "Releases" msgstr "Versions" #: build-news.R:314 msgid "CRAN release: %s" msgstr "Version CRAN : %s" #: build-reference-index.R:23 msgid "Package index" msgstr "Index du paquet" #: build-reference-index.R:187 msgid "All functions" msgstr "Toutes les fonctions" #: build-reference.R:377 msgid "Usage" msgstr "Utilisation" #: build-tutorials.R:49 navbar.R:158 msgid "Tutorials" msgstr "Tutoriels" #: development.R:82 msgid "Released version" msgstr "Dernière version publiée" #: development.R:83 msgid "In-development version" msgstr "Version en développement" #: development.R:84 msgid "Unreleased version" msgstr "Version inédite" #: navbar-menu.R:212 msgid "Search site" msgstr "Rechercher sur le site" #: navbar-menu.R:213 msgid "Search for" msgstr "Rechercher" #: navbar.R:135 msgid "Reference" msgstr "Référence" #: navbar.R:146 msgid "Light switch" msgstr "Interrupteur" #: navbar.R:149 msgid "Light" msgstr "Clair" #: navbar.R:150 msgid "Dark" msgstr "Sombre" #: navbar.R:151 msgid "Auto" msgstr "Automatique" #: navbar.R:187 msgid "Get started" msgstr "Prise en main" #: navbar.R:228 msgid "More articles..." msgstr "Plus d'articles..." #: package.R:317 msgid "deprecated" msgstr "obsolète" #: package.R:318 msgid "superseded" msgstr "remplacée" #: package.R:319 msgid "experimental" msgstr "expérimentale" #: package.R:320 msgid "stable" msgstr "stable" #: rd-data.R:23 msgid "Details" msgstr "Détails" #: rd-data.R:27 msgid "Description" msgstr "Description" #: rd-data.R:31 msgid "References" msgstr "Références" #: rd-data.R:35 render.R:103 msgid "Source" msgstr "Source" #: rd-data.R:39 msgid "Format" msgstr "Format" #: rd-data.R:43 msgid "Note" msgstr "Note" #: rd-data.R:47 msgid "Author" msgstr "Auteur·rice" #: rd-data.R:51 msgid "See also" msgstr "Voir également" #: rd-data.R:67 msgid "Arguments" msgstr "Arguments" #: rd-data.R:75 msgid "Value" msgstr "Valeur de retour" #: render.R:100 msgid "Skip to contents" msgstr "Passer au contenu" #: render.R:101 msgid "Toggle navigation" msgstr "Activer la navigation" #: render.R:102 msgid "On this page" msgstr "Sur cette page" #: render.R:104 msgid "Abstract" msgstr "Résumé" #: render.R:105 msgid "Authors" msgstr "Auteur·rice·s" #: render.R:106 msgid "Version" msgstr "Version" #: render.R:107 msgid "Examples" msgstr "Exemples" #: render.R:109 msgid "Additional details" msgstr "Détails supplémentaires" #: render.R:111 msgid "Site navigation" msgstr "Navigation sur le site" #: repo.R:37 msgid "Source:" msgstr "Source :" #: tweak-homepage.R:68 msgid "Dev status" msgstr "Statut de développement" #: usage.R:52 msgid "# Default %s method" msgstr "# Méthode %s par défaut" #: usage.R:54 msgid "# %s method for class '%s'" msgstr "# Méthode %s pour la classe %s" #~ msgid "Function reference" #~ msgstr "Documentation des fonctions" pkgdown/po/R-pkgdown.pot0000644000176200001440000001144115102677663014753 0ustar liggesusersmsgid "" msgstr "" "Project-Id-Version: pkgdown 2.2.0\n" "POT-Creation-Date: 2025-11-05 10:47-0600\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: build-404.R:12 msgid "Page not found (404)" msgstr "" #: build-404.R:13 msgid "Content not found. Please use links in the navbar." msgstr "" #: build-articles.R:281 navbar.R:193 navbar.R:203 navbar.R:232 msgid "Articles" msgstr "" #: build-articles.R:436 msgid "All vignettes" msgstr "" #: build-footer.R:42 msgid "Developed by" msgstr "" #: build-footer.R:49 msgid "Site built with pkgdown %s." msgstr "" #: build-home-authors.R:12 msgid "Authors and Citation" msgstr "" #: build-home-authors.R:110 msgid "More about authors..." msgstr "" #: build-home-authors.R:113 msgid "Developers" msgstr "" #: build-home-authors.R:220 msgid "author" msgstr "" #: build-home-authors.R:221 msgid "compiler" msgstr "" #: build-home-authors.R:222 msgid "contractor" msgstr "" #: build-home-authors.R:223 msgid "contributor" msgstr "" #: build-home-authors.R:224 msgid "copyright holder" msgstr "" #: build-home-authors.R:225 msgid "maintainer" msgstr "" #: build-home-authors.R:226 msgid "data contributor" msgstr "" #: build-home-authors.R:227 msgid "funder" msgstr "" #: build-home-authors.R:228 msgid "reviewer" msgstr "" #: build-home-authors.R:229 msgid "thesis advisor" msgstr "" #: build-home-authors.R:230 msgid "translator" msgstr "" #: build-home-authors.R:286 render.R:108 msgid "Citation" msgstr "" #: build-home-authors.R:287 msgid "Citing %s" msgstr "" #: build-home-community.R:22 msgid "Contributing guide" msgstr "" #: build-home-community.R:26 msgid "Code of conduct" msgstr "" #: build-home-community.R:30 msgid "Getting help" msgstr "" #: build-home-community.R:37 msgid "Community" msgstr "" #: build-home-index.R:118 msgid "Dev Status" msgstr "" #: build-home-index.R:190 msgid "View on %s" msgstr "" #: build-home-index.R:191 msgid "Browse source code" msgstr "" #: build-home-index.R:192 msgid "Report a bug" msgstr "" #: build-home-index.R:196 msgid "Links" msgstr "" #: build-home-index.R:201 render.R:110 msgid "Table of contents" msgstr "" #: build-home-license.R:14 build-home-license.R:36 msgid "License" msgstr "" #: build-home-license.R:31 msgid "Full license" msgstr "" #: build-news.R:101 build-news.R:262 build-news.R:266 msgid "Changelog" msgstr "" #: build-news.R:128 msgid "Version %s" msgstr "" #: build-news.R:140 build-news.R:257 msgid "News" msgstr "" #: build-news.R:259 msgid "Releases" msgstr "" #: build-news.R:314 msgid "CRAN release: %s" msgstr "" #: build-reference-index.R:23 msgid "Package index" msgstr "" #: build-reference-index.R:187 msgid "All functions" msgstr "" #: build-reference.R:377 msgid "Usage" msgstr "" #: build-tutorials.R:49 navbar.R:158 msgid "Tutorials" msgstr "" #: development.R:82 msgid "Released version" msgstr "" #: development.R:83 msgid "In-development version" msgstr "" #: development.R:84 msgid "Unreleased version" msgstr "" #: navbar-menu.R:212 msgid "Search site" msgstr "" #: navbar-menu.R:213 msgid "Search for" msgstr "" #: navbar.R:135 msgid "Reference" msgstr "" #: navbar.R:146 msgid "Light switch" msgstr "" #: navbar.R:149 msgid "Light" msgstr "" #: navbar.R:150 msgid "Dark" msgstr "" #: navbar.R:151 msgid "Auto" msgstr "" #: navbar.R:187 msgid "Get started" msgstr "" #: navbar.R:228 msgid "More articles..." msgstr "" #: package.R:317 msgid "deprecated" msgstr "" #: package.R:318 msgid "superseded" msgstr "" #: package.R:319 msgid "experimental" msgstr "" #: package.R:320 msgid "stable" msgstr "" #: rd-data.R:23 msgid "Details" msgstr "" #: rd-data.R:27 msgid "Description" msgstr "" #: rd-data.R:31 msgid "References" msgstr "" #: rd-data.R:35 render.R:103 msgid "Source" msgstr "" #: rd-data.R:39 msgid "Format" msgstr "" #: rd-data.R:43 msgid "Note" msgstr "" #: rd-data.R:47 msgid "Author" msgstr "" #: rd-data.R:51 msgid "See also" msgstr "" #: rd-data.R:67 msgid "Arguments" msgstr "" #: rd-data.R:75 msgid "Value" msgstr "" #: render.R:100 msgid "Skip to contents" msgstr "" #: render.R:101 msgid "Toggle navigation" msgstr "" #: render.R:102 msgid "On this page" msgstr "" #: render.R:104 msgid "Abstract" msgstr "" #: render.R:105 msgid "Authors" msgstr "" #: render.R:106 msgid "Version" msgstr "" #: render.R:107 msgid "Examples" msgstr "" #: render.R:109 msgid "Additional details" msgstr "" #: render.R:111 msgid "Site navigation" msgstr "" #: repo.R:37 msgid "Source:" msgstr "" #: tweak-homepage.R:68 msgid "Dev status" msgstr "" #: usage.R:52 msgid "# Default %s method" msgstr "" #: usage.R:54 msgid "# %s method for class '%s'" msgstr "" pkgdown/po/R-es.po0000644000176200001440000001461015075503625013521 0ustar liggesusersmsgid "" msgstr "" "Project-Id-Version: pkgdown 2.0.9.9000\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-10-17 18:07-0600\n" "PO-Revision-Date: 2024-06-17 07:31+0000\n" "Last-Translator: @dieghernan\n" "Language-Team: es\n" "Language: es\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" "X-Loco-Source-Locale: es_ES\n" "X-Generator: Loco https://localise.biz/\n" "X-Loco-Parser: loco_parse_po\n" #: build-404.R:12 msgid "Page not found (404)" msgstr "Página no encontrada (404)" #: build-404.R:13 msgid "Content not found. Please use links in the navbar." msgstr "" "Contenido no encontrado. Por favor utilice los enlaces de la barra de " "navegación." #: build-articles.R:281 navbar.R:193 navbar.R:203 navbar.R:232 msgid "Articles" msgstr "Artículos" #: build-articles.R:436 msgid "All vignettes" msgstr "Todos los artículos" #: build-footer.R:42 msgid "Developed by" msgstr "Desarrollado por" #: build-footer.R:49 msgid "Site built with pkgdown %s." msgstr "Sitio creado con pkgdown %s." #: build-home-authors.R:12 msgid "Authors and Citation" msgstr "Autores y Citas" #: build-home-authors.R:110 msgid "More about authors..." msgstr "Más sobre los autores..." #: build-home-authors.R:113 msgid "Developers" msgstr "Desarrolladores" #: build-home-authors.R:220 msgid "author" msgstr "autor-a" #: build-home-authors.R:221 msgid "compiler" msgstr "compilador-a" #: build-home-authors.R:222 msgid "contractor" msgstr "contratista" #: build-home-authors.R:223 msgid "contributor" msgstr "colaborador-a" #: build-home-authors.R:224 msgid "copyright holder" msgstr "titular de los derechos de autor" #: build-home-authors.R:225 msgid "maintainer" msgstr "mantenedor-a" #: build-home-authors.R:226 msgid "data contributor" msgstr "colaborador-a de datos" #: build-home-authors.R:227 msgid "funder" msgstr "patrocinador-a" #: build-home-authors.R:228 msgid "reviewer" msgstr "revisor-a" #: build-home-authors.R:229 msgid "thesis advisor" msgstr "director-a de tesis" #: build-home-authors.R:230 msgid "translator" msgstr "traductor-a" #: build-home-authors.R:286 render.R:108 msgid "Citation" msgstr "Cita" #: build-home-authors.R:287 msgid "Citing %s" msgstr "Cómo citar %s" #: build-home-community.R:22 msgid "Contributing guide" msgstr "Guía para colaboradores" #: build-home-community.R:26 msgid "Code of conduct" msgstr "Código de conducta" #: build-home-community.R:30 msgid "Getting help" msgstr "Ayuda y soporte" #: build-home-community.R:37 msgid "Community" msgstr "Comunidad" #: build-home-index.R:118 msgid "Dev Status" msgstr "Estado de Desarrollo" #: build-home-index.R:190 msgid "View on %s" msgstr "Ver en %s" #: build-home-index.R:191 msgid "Browse source code" msgstr "Ir al código fuente" #: build-home-index.R:192 msgid "Report a bug" msgstr "Informar de un problema" #: build-home-index.R:196 msgid "Links" msgstr "Enlaces" #: build-home-index.R:201 render.R:110 msgid "Table of contents" msgstr "Índice de contenidos" #: build-home-license.R:14 build-home-license.R:36 msgid "License" msgstr "Licencia" #: build-home-license.R:31 msgid "Full license" msgstr "Licencia completa" #: build-news.R:101 build-news.R:262 build-news.R:266 msgid "Changelog" msgstr "Registro de cambios" #: build-news.R:128 msgid "Version %s" msgstr "Versión %s" #: build-news.R:140 build-news.R:257 msgid "News" msgstr "Noticias" #: build-news.R:259 msgid "Releases" msgstr "Lanzamientos" #: build-news.R:314 msgid "CRAN release: %s" msgstr "Versión CRAN: %s" #: build-reference-index.R:23 msgid "Package index" msgstr "Índice del paquete" #: build-reference-index.R:187 msgid "All functions" msgstr "Todas las funciones" #: build-reference.R:377 msgid "Usage" msgstr "Uso" #: build-tutorials.R:49 navbar.R:158 msgid "Tutorials" msgstr "Tutoriales" #: development.R:82 msgid "Released version" msgstr "Versión publicada" #: development.R:83 msgid "In-development version" msgstr "Versión en desarrollo" #: development.R:84 msgid "Unreleased version" msgstr "Versión no publicada" #: navbar-menu.R:212 msgid "Search site" msgstr "Buscar en el sitio" #: navbar-menu.R:213 msgid "Search for" msgstr "Buscar" #: navbar.R:135 msgid "Reference" msgstr "Índice" #: navbar.R:146 msgid "Light switch" msgstr "Interruptor de color" #: navbar.R:149 msgid "Light" msgstr "Claro" #: navbar.R:150 msgid "Dark" msgstr "Oscuro" #: navbar.R:151 msgid "Auto" msgstr "Auto" #: navbar.R:187 msgid "Get started" msgstr "Primeros pasos" #: navbar.R:228 msgid "More articles..." msgstr "Más artículos..." # Assuming feminine (e.g. functions). Arguments in Spanish are masculine (e.g. obsoleto) #: package.R:317 msgid "deprecated" msgstr "obsoleta" # Assuming feminine (e.g. functions). Arguments in Spanish are masculine (e.g. reemplazado) #: package.R:318 msgid "superseded" msgstr "reemplazada" #: package.R:319 msgid "experimental" msgstr "experimental" #: package.R:320 msgid "stable" msgstr "estable" #: rd-data.R:23 msgid "Details" msgstr "Detalles" #: rd-data.R:27 msgid "Description" msgstr "Descripción" #: rd-data.R:31 msgid "References" msgstr "Referencias" #: rd-data.R:35 render.R:103 msgid "Source" msgstr "Fuente" #: rd-data.R:39 msgid "Format" msgstr "Formato" #: rd-data.R:43 msgid "Note" msgstr "Nota" #: rd-data.R:47 msgid "Author" msgstr "Autor-a" #: rd-data.R:51 msgid "See also" msgstr "Ver también" #: rd-data.R:67 msgid "Arguments" msgstr "Argumentos" #: rd-data.R:75 msgid "Value" msgstr "Valor" #: render.R:100 msgid "Skip to contents" msgstr "Ir al contenido" #: render.R:101 msgid "Toggle navigation" msgstr "Cambiar la navegación" #: render.R:102 msgid "On this page" msgstr "En esta página" #: render.R:104 msgid "Abstract" msgstr "Resumen" #: render.R:105 msgid "Authors" msgstr "Autores" #: render.R:106 msgid "Version" msgstr "Versión" #: render.R:107 msgid "Examples" msgstr "Ejemplos" #: render.R:109 msgid "Additional details" msgstr "Detalles adicionales" #: render.R:111 msgid "Site navigation" msgstr "Navegación del sitio" #: repo.R:37 msgid "Source:" msgstr "Código:" #: tweak-homepage.R:68 msgid "Dev status" msgstr "Estado de desarrollo" #: usage.R:52 msgid "# Default %s method" msgstr "# Método %s por defecto" #: usage.R:54 msgid "# %s method for class '%s'" msgstr "# Método %s para la clase '%s'" #~ msgid "Function reference" #~ msgstr "Índice de funciones" pkgdown/po/R-ja.po0000644000176200001440000001410415100735002013463 0ustar liggesusersmsgid "" msgstr "" "Project-Id-Version: pkgdown 2.0.9.9000\n" "POT-Creation-Date: 2025-10-20 18:57-0600\n" "PO-Revision-Date: 2024-05-24 09:36-0500\n" "Last-Translator: Positron Assistant (Claude Sonnet 4)\n" "Language-Team: none\n" "Language: ja\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" #: build-404.R:12 msgid "Page not found (404)" msgstr "ページが見つかりません (404)" #: build-404.R:13 msgid "Content not found. Please use links in the navbar." msgstr "コンテンツが見つかりません。ナビゲーションからお探しください。" #: build-articles.R:281 navbar.R:193 navbar.R:203 navbar.R:232 msgid "Articles" msgstr "記事" #: build-articles.R:436 msgid "All vignettes" msgstr "すべての解説記事" #: build-footer.R:42 msgid "Developed by" msgstr "開発者" #: build-footer.R:49 msgid "Site built with pkgdown %s." msgstr "pkgdown %s で構築されたサイト。" #: build-home-authors.R:12 msgid "Authors and Citation" msgstr "作者と引用" #: build-home-authors.R:110 msgid "More about authors..." msgstr "作者情報..." #: build-home-authors.R:113 msgid "Developers" msgstr "開発者" #: build-home-authors.R:220 msgid "author" msgstr "作者" #: build-home-authors.R:221 msgid "compiler" msgstr "編集者" #: build-home-authors.R:222 msgid "contractor" msgstr "契約者" #: build-home-authors.R:223 msgid "contributor" msgstr "貢献者" #: build-home-authors.R:224 msgid "copyright holder" msgstr "著作権者" #: build-home-authors.R:225 msgid "maintainer" msgstr "メンテナ" #: build-home-authors.R:226 msgid "data contributor" msgstr "データ提供者" #: build-home-authors.R:227 msgid "funder" msgstr "資金提供者" #: build-home-authors.R:228 msgid "reviewer" msgstr "査読者" #: build-home-authors.R:229 msgid "thesis advisor" msgstr "論文指導教員" #: build-home-authors.R:230 msgid "translator" msgstr "翻訳者" #: build-home-authors.R:286 render.R:108 msgid "Citation" msgstr "引用" #: build-home-authors.R:287 msgid "Citing %s" msgstr "%s の引用" #: build-home-community.R:22 msgid "Contributing guide" msgstr "貢献ガイド" #: build-home-community.R:26 msgid "Code of conduct" msgstr "行動規範" #: build-home-community.R:30 msgid "Getting help" msgstr "ヘルプ" #: build-home-community.R:37 msgid "Community" msgstr "コミュニティ" #: build-home-index.R:118 msgid "Dev Status" msgstr "開発ステータス" #: build-home-index.R:190 msgid "View on %s" msgstr "%s で見る" #: build-home-index.R:191 msgid "Browse source code" msgstr "ソースコードを見る" #: build-home-index.R:192 msgid "Report a bug" msgstr "バグを報告" #: build-home-index.R:196 msgid "Links" msgstr "リンク" #: build-home-index.R:201 render.R:110 msgid "Table of contents" msgstr "目次" #: build-home-license.R:14 build-home-license.R:36 msgid "License" msgstr "ライセンス" #: build-home-license.R:31 msgid "Full license" msgstr "ライセンス全文" #: build-news.R:101 build-news.R:262 build-news.R:266 msgid "Changelog" msgstr "変更履歴" #: build-news.R:128 msgid "Version %s" msgstr "バージョン %s" #: build-news.R:140 build-news.R:257 msgid "News" msgstr "ニュース" #: build-news.R:259 msgid "Releases" msgstr "リリース" #: build-news.R:314 msgid "CRAN release: %s" msgstr "CRANリリース: %s" #: build-reference-index.R:23 msgid "Package index" msgstr "パッケージ索引" #: build-reference-index.R:187 msgid "All functions" msgstr "すべての関数" #: build-reference.R:377 msgid "Usage" msgstr "使用法" #: build-tutorials.R:49 navbar.R:158 msgid "Tutorials" msgstr "チュートリアル" #: development.R:82 msgid "Released version" msgstr "リリース版" #: development.R:83 msgid "In-development version" msgstr "開発版" #: development.R:84 msgid "Unreleased version" msgstr "未リリース版" #: navbar-menu.R:212 msgid "Search site" msgstr "サイト内検索" #: navbar-menu.R:213 msgid "Search for" msgstr "検索" #: navbar.R:135 msgid "Reference" msgstr "リファレンス" #: navbar.R:146 msgid "Light switch" msgstr "テーマ切替" #: navbar.R:149 msgid "Light" msgstr "ライト" #: navbar.R:150 msgid "Dark" msgstr "ダーク" #: navbar.R:151 msgid "Auto" msgstr "自動" #: navbar.R:187 msgid "Get started" msgstr "はじめに" #: navbar.R:228 msgid "More articles..." msgstr "さらに記事を見る..." #: package.R:317 msgid "deprecated" msgstr "非推奨" #: package.R:318 msgid "superseded" msgstr "後継があります" #: package.R:319 msgid "experimental" msgstr "実験的" #: package.R:320 msgid "stable" msgstr "安定版" #: rd-data.R:23 msgid "Details" msgstr "詳細" #: rd-data.R:27 msgid "Description" msgstr "説明" #: rd-data.R:31 msgid "References" msgstr "参考文献" #: rd-data.R:35 render.R:103 msgid "Source" msgstr "ソース" #: rd-data.R:39 msgid "Format" msgstr "形式" #: rd-data.R:43 msgid "Note" msgstr "注記" #: rd-data.R:47 msgid "Author" msgstr "作者" #: rd-data.R:51 msgid "See also" msgstr "参照" #: rd-data.R:67 msgid "Arguments" msgstr "引数" #: rd-data.R:75 msgid "Value" msgstr "戻り値" #: render.R:100 msgid "Skip to contents" msgstr "コンテンツへスキップ" #: render.R:101 msgid "Toggle navigation" msgstr "ナビゲーション切替" #: render.R:102 msgid "On this page" msgstr "このページ" #: render.R:104 msgid "Abstract" msgstr "概要" #: render.R:105 msgid "Authors" msgstr "作者" #: render.R:106 msgid "Version" msgstr "バージョン" #: render.R:107 msgid "Examples" msgstr "例" #: render.R:109 msgid "Additional details" msgstr "追加の詳細" #: render.R:111 msgid "Site navigation" msgstr "サイトナビゲーション" #: repo.R:37 msgid "Source:" msgstr "ソース:" #: tweak-homepage.R:68 msgid "Dev status" msgstr "開発ステータス" #: usage.R:52 msgid "# Default %s method" msgstr "# デフォルトの %s メソッド" #: usage.R:54 msgid "# %s method for class '%s'" msgstr "# クラス '%2$s' の %1$s メソッド" pkgdown/po/R-pt.po0000644000176200001440000001405315075503625013536 0ustar liggesusersmsgid "" msgstr "" "Project-Id-Version: pkgdown 2.0.9.9000\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-10-17 18:07-0600\n" "PO-Revision-Date: 2024-06-16 00:00-0500\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" "Language: pt\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: build-404.R:12 msgid "Page not found (404)" msgstr "Página não encontrada (404)" #: build-404.R:13 msgid "Content not found. Please use links in the navbar." msgstr "Conteúdo não encontrado. Por favor, use links na navbar." #: build-articles.R:281 navbar.R:193 navbar.R:203 navbar.R:232 msgid "Articles" msgstr "Artigos" #: build-articles.R:436 msgid "All vignettes" msgstr "Todas as vinhetas" #: build-footer.R:42 msgid "Developed by" msgstr "Desenvolvido por" #: build-footer.R:49 msgid "Site built with pkgdown %s." msgstr "Site criado com pkgdown %s." #: build-home-authors.R:12 msgid "Authors and Citation" msgstr "Autores e citação" #: build-home-authors.R:110 msgid "More about authors..." msgstr "Mais sobre autores..." #: build-home-authors.R:113 msgid "Developers" msgstr "Desenvolvedores" #: build-home-authors.R:220 msgid "author" msgstr "autor" #: build-home-authors.R:221 msgid "compiler" msgstr "compilador" #: build-home-authors.R:222 msgid "contractor" msgstr "contratante" #: build-home-authors.R:223 msgid "contributor" msgstr "contribuinte" #: build-home-authors.R:224 msgid "copyright holder" msgstr "titular dos direitos autorais" #: build-home-authors.R:225 msgid "maintainer" msgstr "mantenedor" #: build-home-authors.R:226 msgid "data contributor" msgstr "contribuidor de dados" #: build-home-authors.R:227 msgid "funder" msgstr "financiador" #: build-home-authors.R:228 msgid "reviewer" msgstr "revisor" #: build-home-authors.R:229 msgid "thesis advisor" msgstr "orientador de tese" #: build-home-authors.R:230 msgid "translator" msgstr "tradutor" #: build-home-authors.R:286 render.R:108 msgid "Citation" msgstr "Citação" #: build-home-authors.R:287 msgid "Citing %s" msgstr "Citando %s" #: build-home-community.R:22 msgid "Contributing guide" msgstr "Guia de contribuição" #: build-home-community.R:26 msgid "Code of conduct" msgstr "Código de conduta" #: build-home-community.R:30 msgid "Getting help" msgstr "Obter ajuda" #: build-home-community.R:37 msgid "Community" msgstr "Comunidade" #: build-home-index.R:118 msgid "Dev Status" msgstr "Estado de Desenvolvimento" #: build-home-index.R:190 msgid "View on %s" msgstr "Veja no %s" #: build-home-index.R:191 msgid "Browse source code" msgstr "Navegue pelo código-fonte" #: build-home-index.R:192 msgid "Report a bug" msgstr "Reportar um erro" #: build-home-index.R:196 msgid "Links" msgstr "Links" #: build-home-index.R:201 render.R:110 msgid "Table of contents" msgstr "Índice" #: build-home-license.R:14 build-home-license.R:36 msgid "License" msgstr "Licença" #: build-home-license.R:31 msgid "Full license" msgstr "Licença completa" #: build-news.R:101 build-news.R:262 build-news.R:266 msgid "Changelog" msgstr "Changelog" #: build-news.R:128 msgid "Version %s" msgstr "Versão %s" #: build-news.R:140 build-news.R:257 msgid "News" msgstr "Notícia" #: build-news.R:259 msgid "Releases" msgstr "Lançamentos" #: build-news.R:314 msgid "CRAN release: %s" msgstr "Lançamento CRAN: %s" #: build-reference-index.R:23 msgid "Package index" msgstr "Índice de pacotes" #: build-reference-index.R:187 msgid "All functions" msgstr "Todas as funções" #: build-reference.R:377 msgid "Usage" msgstr "Uso" #: build-tutorials.R:49 navbar.R:158 msgid "Tutorials" msgstr "Tutoriais" #: development.R:82 msgid "Released version" msgstr "Versão lançada" #: development.R:83 msgid "In-development version" msgstr "Versão em desenvolvimento" #: development.R:84 msgid "Unreleased version" msgstr "Versão não lançada" #: navbar-menu.R:212 msgid "Search site" msgstr "Pesquisar site" #: navbar-menu.R:213 msgid "Search for" msgstr "Procurar" #: navbar.R:135 msgid "Reference" msgstr "Referência" #: navbar.R:146 msgid "Light switch" msgstr "Interruptor de luz" #: navbar.R:149 msgid "Light" msgstr "Clara" #: navbar.R:150 msgid "Dark" msgstr "Escuro" #: navbar.R:151 msgid "Auto" msgstr "Auto" #: navbar.R:187 msgid "Get started" msgstr "Primeiros passos" #: navbar.R:228 msgid "More articles..." msgstr "Mais artigos..." #: package.R:317 msgid "deprecated" msgstr "obsoleta" #: package.R:318 msgid "superseded" msgstr "substituída" #: package.R:319 msgid "experimental" msgstr "experimental" #: package.R:320 msgid "stable" msgstr "estável" #: rd-data.R:23 msgid "Details" msgstr "Detalhes" #: rd-data.R:27 msgid "Description" msgstr "Descrição" #: rd-data.R:31 msgid "References" msgstr "Referências" #: rd-data.R:35 render.R:103 msgid "Source" msgstr "Fonte" #: rd-data.R:39 msgid "Format" msgstr "Formato" #: rd-data.R:43 msgid "Note" msgstr "Nota" #: rd-data.R:47 msgid "Author" msgstr "Autor" #: rd-data.R:51 msgid "See also" msgstr "Veja também" #: rd-data.R:67 msgid "Arguments" msgstr "Argumentos" #: rd-data.R:75 msgid "Value" msgstr "Valor" #: render.R:100 msgid "Skip to contents" msgstr "Avance para o conteúdo" #: render.R:101 msgid "Toggle navigation" msgstr "Alternar de navegação" #: render.R:102 msgid "On this page" msgstr "Nesta página" #: render.R:104 msgid "Abstract" msgstr "Resumo" #: render.R:105 msgid "Authors" msgstr "Autores" #: render.R:106 msgid "Version" msgstr "Versão" #: render.R:107 msgid "Examples" msgstr "Exemplos" #: render.R:109 msgid "Additional details" msgstr "Detalhes adicionais" #: render.R:111 msgid "Site navigation" msgstr "Navegação do site" #: repo.R:37 msgid "Source:" msgstr "Fonte:" #: tweak-homepage.R:68 msgid "Dev status" msgstr "Status de desenvolvimento" #: usage.R:52 msgid "# Default %s method" msgstr "# Método %s padrão" #: usage.R:54 msgid "# %s method for class '%s'" msgstr "# método %s para a classe '%s'" #~ msgid "Function reference" #~ msgstr "Referência para funções" pkgdown/po/R-tr.po0000644000176200001440000001377315075503625013550 0ustar liggesusersmsgid "" msgstr "" "Project-Id-Version: pkgdown 1.9000.9000.9000\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-10-17 18:07-0600\n" "PO-Revision-Date: 2021-10-28 08:02-0500\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" "Language: tr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: build-404.R:12 msgid "Page not found (404)" msgstr "Sayfa bulunamıyor (404)" #: build-404.R:13 msgid "Content not found. Please use links in the navbar." msgstr "" "İçerik bulunamıyor. Lütfen yukarıdaki gezinme çubuğundaki bağları kullanın." #: build-articles.R:281 navbar.R:193 navbar.R:203 navbar.R:232 msgid "Articles" msgstr "Makaleler" #: build-articles.R:436 msgid "All vignettes" msgstr "Bütün makaleler" #: build-footer.R:42 msgid "Developed by" msgstr "Geliştiren" #: build-footer.R:49 msgid "Site built with pkgdown %s." msgstr "Site pkgdown %s ile geliştirilmiştir." #: build-home-authors.R:12 msgid "Authors and Citation" msgstr "Yazarlar ve Alıntı" #: build-home-authors.R:110 msgid "More about authors..." msgstr "Yazarlar hakkında daha fazla bilgi..." #: build-home-authors.R:113 msgid "Developers" msgstr "Geliştiriciler" #: build-home-authors.R:220 msgid "author" msgstr "yazar" #: build-home-authors.R:221 msgid "compiler" msgstr "derleyici" #: build-home-authors.R:222 msgid "contractor" msgstr "yüklenici" #: build-home-authors.R:223 msgid "contributor" msgstr "katılımcı" #: build-home-authors.R:224 msgid "copyright holder" msgstr "telif hakkı sahibi" #: build-home-authors.R:225 msgid "maintainer" msgstr "bakımcı" #: build-home-authors.R:226 msgid "data contributor" msgstr "veri katılımcısı" #: build-home-authors.R:227 msgid "funder" msgstr "fon sağlayıcı" #: build-home-authors.R:228 msgid "reviewer" msgstr "eleştirmen" #: build-home-authors.R:229 msgid "thesis advisor" msgstr "tez danışmanı" #: build-home-authors.R:230 msgid "translator" msgstr "çevirmen" #: build-home-authors.R:286 render.R:108 msgid "Citation" msgstr "Alıntı" #: build-home-authors.R:287 msgid "Citing %s" msgstr "%s'ı kaynak gösterme" #: build-home-community.R:22 msgid "Contributing guide" msgstr "Katkıda bulunma rehberi" #: build-home-community.R:26 msgid "Code of conduct" msgstr "Davranış kuralları" #: build-home-community.R:30 msgid "Getting help" msgstr "Yardım" #: build-home-community.R:37 msgid "Community" msgstr "Komünite" #: build-home-index.R:118 msgid "Dev Status" msgstr "Geliştirme statüsü" #: build-home-index.R:190 msgid "View on %s" msgstr "%s'da gör" #: build-home-index.R:191 msgid "Browse source code" msgstr "Kaynak koduna göz at" #: build-home-index.R:192 msgid "Report a bug" msgstr "Hata bildir" #: build-home-index.R:196 msgid "Links" msgstr "Bağlantılar" #: build-home-index.R:201 render.R:110 msgid "Table of contents" msgstr "İçindekiler" #: build-home-license.R:14 build-home-license.R:36 msgid "License" msgstr "Lisans" #: build-home-license.R:31 msgid "Full license" msgstr "Tam lisans" #: build-news.R:101 build-news.R:262 build-news.R:266 msgid "Changelog" msgstr "Değişiklik günlüğü" #: build-news.R:128 msgid "Version %s" msgstr "Sürüm %s" #: build-news.R:140 build-news.R:257 msgid "News" msgstr "Haberler" #: build-news.R:259 msgid "Releases" msgstr "Yayınlar" #: build-news.R:314 msgid "CRAN release: %s" msgstr "CRAN yayını: %s" #: build-reference-index.R:23 msgid "Package index" msgstr "Paket dizini" #: build-reference-index.R:187 msgid "All functions" msgstr "Bütün fonksiyonlar" #: build-reference.R:377 msgid "Usage" msgstr "Kullanım" #: build-tutorials.R:49 navbar.R:158 msgid "Tutorials" msgstr "Öğreticiler" #: development.R:82 msgid "Released version" msgstr "Yayımlanan sürüm" #: development.R:83 msgid "In-development version" msgstr "Geliştirme aşamasındaki sürüm" #: development.R:84 msgid "Unreleased version" msgstr "Yayınlanmamış sürüm" #: navbar-menu.R:212 msgid "Search site" msgstr "Ara" #: navbar-menu.R:213 msgid "Search for" msgstr "Ara" #: navbar.R:135 msgid "Reference" msgstr "Referans" #: navbar.R:146 msgid "Light switch" msgstr "Koyu/açık" #: navbar.R:149 msgid "Light" msgstr "Açık" #: navbar.R:150 msgid "Dark" msgstr "Koyu" #: navbar.R:151 msgid "Auto" msgstr "Otomatik" #: navbar.R:187 msgid "Get started" msgstr "Başla" #: navbar.R:228 msgid "More articles..." msgstr "Diğer makaleler..." #: package.R:317 msgid "deprecated" msgstr "artık kullanılmayan" #: package.R:318 msgid "superseded" msgstr "yerine gelen" #: package.R:319 msgid "experimental" msgstr "deneysel" #: package.R:320 msgid "stable" msgstr "sabit" #: rd-data.R:23 msgid "Details" msgstr "Detaylar" #: rd-data.R:27 msgid "Description" msgstr "Açıklama" #: rd-data.R:31 msgid "References" msgstr "Referanslar" #: rd-data.R:35 render.R:103 msgid "Source" msgstr "Kaynak" #: rd-data.R:39 msgid "Format" msgstr "Format" #: rd-data.R:43 msgid "Note" msgstr "Not" #: rd-data.R:47 msgid "Author" msgstr "Yazar" #: rd-data.R:51 msgid "See also" msgstr "Ayrıca bak" #: rd-data.R:67 msgid "Arguments" msgstr "Argümanlar" #: rd-data.R:75 msgid "Value" msgstr "Değer" #: render.R:100 msgid "Skip to contents" msgstr "İçeriğe atla" #: render.R:101 msgid "Toggle navigation" msgstr "Gezinmeyi aç/kapat" #: render.R:102 msgid "On this page" msgstr "Bu sayfada" #: render.R:104 msgid "Abstract" msgstr "Özet" #: render.R:105 msgid "Authors" msgstr "Yazarlar" #: render.R:106 msgid "Version" msgstr "Sürüm" #: render.R:107 msgid "Examples" msgstr "Örnekler" #: render.R:109 msgid "Additional details" msgstr "Ek detaylar" #: render.R:111 msgid "Site navigation" msgstr "Site navigasyonu" #: repo.R:37 msgid "Source:" msgstr "Kaynak:" #: tweak-homepage.R:68 msgid "Dev status" msgstr "Geliştirme statüsü" #: usage.R:52 msgid "# Default %s method" msgstr "# Varsayılan %s metodu" #: usage.R:54 msgid "# %s method for class '%s'" msgstr "# %s için %s metodu" pkgdown/po/R-de.po0000644000176200001440000001421515075503625013503 0ustar liggesusersmsgid "" msgstr "" "Project-Id-Version: pkgdown 1.9000.9000.9000\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-10-17 18:07-0600\n" "PO-Revision-Date: 2021-10-28 08:02-0500\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" "Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: build-404.R:12 msgid "Page not found (404)" msgstr "Seite nicht gefunden (404)" #: build-404.R:13 msgid "Content not found. Please use links in the navbar." msgstr "Inhalt nicht gefunden. Bitte die Navigationleiste benutzen." #: build-articles.R:281 navbar.R:193 navbar.R:203 navbar.R:232 msgid "Articles" msgstr "Artikel" #: build-articles.R:436 msgid "All vignettes" msgstr "Alle Artikel" #: build-footer.R:42 msgid "Developed by" msgstr "Entwickelt von" #: build-footer.R:49 msgid "Site built with pkgdown %s." msgstr "Seite erstellt mit pkgdown %s." #: build-home-authors.R:12 msgid "Authors and Citation" msgstr "Autor:innen und Zitation" #: build-home-authors.R:110 msgid "More about authors..." msgstr "Mehr zu den Autor:innen" #: build-home-authors.R:113 msgid "Developers" msgstr "Entwicker:innen" #: build-home-authors.R:220 msgid "author" msgstr "Autor:in" #: build-home-authors.R:221 msgid "compiler" msgstr "Zusammensteller:in" #: build-home-authors.R:222 msgid "contractor" msgstr "Auftragnehmer:in" #: build-home-authors.R:223 msgid "contributor" msgstr "Beitragende:r" #: build-home-authors.R:224 msgid "copyright holder" msgstr "Urheberrechtsinhaber:in" #: build-home-authors.R:225 msgid "maintainer" msgstr "Maintainer:in" #: build-home-authors.R:226 msgid "data contributor" msgstr "Datenbeitragende:r" #: build-home-authors.R:227 msgid "funder" msgstr "Sponsor:in" #: build-home-authors.R:228 msgid "reviewer" msgstr "Gutachter:in" #: build-home-authors.R:229 msgid "thesis advisor" msgstr "Betreuer:in der Abschlussarbeit" #: build-home-authors.R:230 msgid "translator" msgstr "Übersetzer:in" #: build-home-authors.R:286 render.R:108 msgid "Citation" msgstr "Zitationsvorschlag" #: build-home-authors.R:287 msgid "Citing %s" msgstr "%s zitieren" #: build-home-community.R:22 msgid "Contributing guide" msgstr "Leitfaden zum Mitwirken" #: build-home-community.R:26 msgid "Code of conduct" msgstr "Verhaltensregeln" #: build-home-community.R:30 msgid "Getting help" msgstr "Hilfe erhalten" #: build-home-community.R:37 msgid "Community" msgstr "Community" #: build-home-index.R:118 msgid "Dev Status" msgstr "Entwicklungsstatus" #: build-home-index.R:190 msgid "View on %s" msgstr "Auf %s ansehen" #: build-home-index.R:191 msgid "Browse source code" msgstr "Quellcode ansehen" #: build-home-index.R:192 msgid "Report a bug" msgstr "Bug melden" #: build-home-index.R:196 msgid "Links" msgstr "Links" #: build-home-index.R:201 render.R:110 msgid "Table of contents" msgstr "Inhaltsverzeichnis" #: build-home-license.R:14 build-home-license.R:36 msgid "License" msgstr "Lizenz" #: build-home-license.R:31 msgid "Full license" msgstr "Vollständige Lizenz" #: build-news.R:101 build-news.R:262 build-news.R:266 msgid "Changelog" msgstr "Änderungsprotokoll" #: build-news.R:128 msgid "Version %s" msgstr "Version %s" #: build-news.R:140 build-news.R:257 msgid "News" msgstr "Neuigkeiten" #: build-news.R:259 msgid "Releases" msgstr "Veröffentlichungen" #: build-news.R:314 msgid "CRAN release: %s" msgstr "CRAN-Veröffentlichung: %s" #: build-reference-index.R:23 msgid "Package index" msgstr "Paketindex" #: build-reference-index.R:187 msgid "All functions" msgstr "Alle Funktionen" #: build-reference.R:377 msgid "Usage" msgstr "Verwendung" #: build-tutorials.R:49 navbar.R:158 msgid "Tutorials" msgstr "Tutorien" #: development.R:82 msgid "Released version" msgstr "Veröffentlichte Version" #: development.R:83 msgid "In-development version" msgstr "Version in Entwicklung" #: development.R:84 msgid "Unreleased version" msgstr "Unveröffentlichte Version" #: navbar-menu.R:212 msgid "Search site" msgstr "Suchen nach" #: navbar-menu.R:213 msgid "Search for" msgstr "Suchen nach" #: navbar.R:135 msgid "Reference" msgstr "Verzeichnis" #: navbar.R:146 msgid "Light switch" msgstr "Erscheinungsbild" #: navbar.R:149 msgid "Light" msgstr "Hell" #: navbar.R:150 msgid "Dark" msgstr "Dunkel" #: navbar.R:151 msgid "Auto" msgstr "Automatisch" #: navbar.R:187 msgid "Get started" msgstr "Erste Schritte" #: navbar.R:228 msgid "More articles..." msgstr "Mehr Artikel ..." #: package.R:317 msgid "deprecated" msgstr "veraltet" #: package.R:318 msgid "superseded" msgstr "überholt" #: package.R:319 msgid "experimental" msgstr "experimentell" #: package.R:320 msgid "stable" msgstr "stabil" #: rd-data.R:23 msgid "Details" msgstr "Details" #: rd-data.R:27 msgid "Description" msgstr "Beschreibung" #: rd-data.R:31 msgid "References" msgstr "Literaturverzeichnis" #: rd-data.R:35 render.R:103 msgid "Source" msgstr "Quelle" #: rd-data.R:39 msgid "Format" msgstr "Format" #: rd-data.R:43 msgid "Note" msgstr "Notiz" #: rd-data.R:47 msgid "Author" msgstr "Autor:in" #: rd-data.R:51 msgid "See also" msgstr "Siehe auch" #: rd-data.R:67 msgid "Arguments" msgstr "Argumente" #: rd-data.R:75 msgid "Value" msgstr "Rückgabewert" #: render.R:100 msgid "Skip to contents" msgstr "Direkt zum Inhalt springen" #: render.R:101 msgid "Toggle navigation" msgstr "Navigation ein-/ausschalten" #: render.R:102 msgid "On this page" msgstr "Auf dieser Seite" #: render.R:104 msgid "Abstract" msgstr "Kurzzusammenfassung" #: render.R:105 msgid "Authors" msgstr "Autor:innen" #: render.R:106 msgid "Version" msgstr "Version" #: render.R:107 msgid "Examples" msgstr "Beispiele" #: render.R:109 msgid "Additional details" msgstr "Zusätzliche Details" #: render.R:111 msgid "Site navigation" msgstr "Seitennavigation" #: repo.R:37 msgid "Source:" msgstr "Quelle:" #: tweak-homepage.R:68 msgid "Dev status" msgstr "Entwicklungsstatus" #: usage.R:52 msgid "# Default %s method" msgstr "# Standard-%s-Methode" #: usage.R:54 msgid "# %s method for class '%s'" msgstr "# %s-Methode für '%s'" #~ msgid "Function reference" #~ msgstr "Funktionsverzeichnis" pkgdown/po/R-ko.po0000644000176200001440000001402715075503625013525 0ustar liggesusersmsgid "" msgstr "" "Project-Id-Version: pkgdown 1.9000.9000.9000\n" "POT-Creation-Date: 2025-10-17 18:07-0600\n" "PO-Revision-Date: 2021-11-26 15:57-0600\n" "Last-Translator: Chanyub Park \n" "Language-Team: @mrchypark\n" "Language: ko\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: build-404.R:12 msgid "Page not found (404)" msgstr "페이지를 찾을 수 없습니다 (404)" #: build-404.R:13 msgid "Content not found. Please use links in the navbar." msgstr "콘텐츠를 찾을 수 없습니다. 네비게이션 바의 링크를 이용해 주세요." #: build-articles.R:281 navbar.R:193 navbar.R:203 navbar.R:232 msgid "Articles" msgstr "관련 글 목록" #: build-articles.R:436 msgid "All vignettes" msgstr "전체 사용설명서(비네트)" #: build-footer.R:42 msgid "Developed by" msgstr "개발자:" #: build-footer.R:49 msgid "Site built with pkgdown %s." msgstr "" "현재 사이트는 다음 패키지로 생성하였습니다. - pkgdown %s" #: build-home-authors.R:12 msgid "Authors and Citation" msgstr "저자와 인용" #: build-home-authors.R:110 msgid "More about authors..." msgstr "저자에 대한 부분은..." #: build-home-authors.R:113 msgid "Developers" msgstr "개발자들" #: build-home-authors.R:220 msgid "author" msgstr "저자" #: build-home-authors.R:221 msgid "compiler" msgstr "편집자" #: build-home-authors.R:222 msgid "contractor" msgstr "계약자" #: build-home-authors.R:223 msgid "contributor" msgstr "기여자" #: build-home-authors.R:224 msgid "copyright holder" msgstr "저작권자" #: build-home-authors.R:225 msgid "maintainer" msgstr "관리자" #: build-home-authors.R:226 msgid "data contributor" msgstr "데이터 기여자" #: build-home-authors.R:227 msgid "funder" msgstr "자금 제공자" #: build-home-authors.R:228 msgid "reviewer" msgstr "리뷰어" #: build-home-authors.R:229 msgid "thesis advisor" msgstr "지도교수" #: build-home-authors.R:230 msgid "translator" msgstr "번역자" #: build-home-authors.R:286 render.R:108 msgid "Citation" msgstr "인용" #: build-home-authors.R:287 msgid "Citing %s" msgstr "%s 인용하기" #: build-home-community.R:22 msgid "Contributing guide" msgstr "기여 가이드" #: build-home-community.R:26 msgid "Code of conduct" msgstr "행동강령" #: build-home-community.R:30 msgid "Getting help" msgstr "도움말" #: build-home-community.R:37 msgid "Community" msgstr "커뮤니티" #: build-home-index.R:118 msgid "Dev Status" msgstr "개발 상태" #: build-home-index.R:190 msgid "View on %s" msgstr "%s에서 보기" #: build-home-index.R:191 msgid "Browse source code" msgstr "소스코드 보기" #: build-home-index.R:192 msgid "Report a bug" msgstr "버그 신고" #: build-home-index.R:196 msgid "Links" msgstr "링크" #: build-home-index.R:201 render.R:110 msgid "Table of contents" msgstr "목차" #: build-home-license.R:14 build-home-license.R:36 msgid "License" msgstr "라이선스" #: build-home-license.R:31 msgid "Full license" msgstr "전체 라이선스" #: build-news.R:101 build-news.R:262 build-news.R:266 msgid "Changelog" msgstr "변경 사항" #: build-news.R:128 msgid "Version %s" msgstr "버전 %s" #: build-news.R:140 build-news.R:257 msgid "News" msgstr "뉴스" #: build-news.R:259 msgid "Releases" msgstr "릴리즈" #: build-news.R:314 msgid "CRAN release: %s" msgstr "CRAN 배포: %s" #: build-reference-index.R:23 msgid "Package index" msgstr "패키지 색인" #: build-reference-index.R:187 msgid "All functions" msgstr "모든 함수" #: build-reference.R:377 msgid "Usage" msgstr "사용법" #: build-tutorials.R:49 navbar.R:158 msgid "Tutorials" msgstr "튜토리얼" #: development.R:82 msgid "Released version" msgstr "배포 버전" #: development.R:83 msgid "In-development version" msgstr "개발 버전" #: development.R:84 msgid "Unreleased version" msgstr "배포전 버전" #: navbar-menu.R:212 msgid "Search site" msgstr "사이트 검색" #: navbar-menu.R:213 msgid "Search for" msgstr "검색" #: navbar.R:135 msgid "Reference" msgstr "참조" #: navbar.R:146 msgid "Light switch" msgstr "테마 전환" #: navbar.R:149 msgid "Light" msgstr "밝음" #: navbar.R:150 msgid "Dark" msgstr "어두움" #: navbar.R:151 msgid "Auto" msgstr "자동" #: navbar.R:187 msgid "Get started" msgstr "시작하기" #: navbar.R:228 msgid "More articles..." msgstr "더 보기..." #: package.R:317 msgid "deprecated" msgstr "더 이상 사용되지 않음" #: package.R:318 msgid "superseded" msgstr "대체됨" #: package.R:319 msgid "experimental" msgstr "실험적" #: package.R:320 msgid "stable" msgstr "안정" #: rd-data.R:23 msgid "Details" msgstr "세부사항" #: rd-data.R:27 msgid "Description" msgstr "설명" #: rd-data.R:31 msgid "References" msgstr "참조" #: rd-data.R:35 render.R:103 msgid "Source" msgstr "소스코드" #: rd-data.R:39 msgid "Format" msgstr "양식" #: rd-data.R:43 msgid "Note" msgstr "노트" #: rd-data.R:47 msgid "Author" msgstr "저자" #: rd-data.R:51 msgid "See also" msgstr "더 보기" #: rd-data.R:67 msgid "Arguments" msgstr "인수" #: rd-data.R:75 msgid "Value" msgstr "값" #: render.R:100 msgid "Skip to contents" msgstr "콘텐츠로 바로가기" #: render.R:101 msgid "Toggle navigation" msgstr "네비게이션바 열기" #: render.R:102 msgid "On this page" msgstr "목차" #: render.R:104 msgid "Abstract" msgstr "초록" #: render.R:105 msgid "Authors" msgstr "저자들" #: render.R:106 msgid "Version" msgstr "버전" #: render.R:107 msgid "Examples" msgstr "예시 코드" #: render.R:109 msgid "Additional details" msgstr "추가 정보" #: render.R:111 msgid "Site navigation" msgstr "사이트 탐색" #: repo.R:37 msgid "Source:" msgstr "소스코드:" #: tweak-homepage.R:68 msgid "Dev status" msgstr "개발 상태" #: usage.R:52 msgid "# Default %s method" msgstr "# 기본 %s 메서드" #: usage.R:54 msgid "# %s method for class '%s'" msgstr "# '%s' 클래스의 %s 메서드" #~ msgid "Function reference" #~ msgstr "함수 레퍼런스" pkgdown/po/R-zh_CN.po0000644000176200001440000001344415075503625014117 0ustar liggesusersmsgid "" msgstr "" "Project-Id-Version: pkgdown 1.9000.9000.9000\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2025-10-17 18:07-0600\n" "PO-Revision-Date: 2021-10-28 08:02-0500\n" "Last-Translator: Automatically generated\n" "Language-Team: none\n" "Language: zh_CN\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: build-404.R:12 msgid "Page not found (404)" msgstr "页面未找到(404)" #: build-404.R:13 msgid "Content not found. Please use links in the navbar." msgstr "请求的页面未找到。请使用导航栏内的链接。" #: build-articles.R:281 navbar.R:193 navbar.R:203 navbar.R:232 msgid "Articles" msgstr "文章" #: build-articles.R:436 msgid "All vignettes" msgstr "所有文章" #: build-footer.R:42 msgid "Developed by" msgstr "开发者:" #: build-footer.R:49 msgid "Site built with pkgdown %s." msgstr "该网站由 pkgdown %s 构建。" #: build-home-authors.R:12 msgid "Authors and Citation" msgstr "作者与引用" #: build-home-authors.R:110 msgid "More about authors..." msgstr "关于作者…" #: build-home-authors.R:113 msgid "Developers" msgstr "开发者" #: build-home-authors.R:220 msgid "author" msgstr "作者" #: build-home-authors.R:221 msgid "compiler" msgstr "编译者" #: build-home-authors.R:222 msgid "contractor" msgstr "合同员工" #: build-home-authors.R:223 msgid "contributor" msgstr "合作者" #: build-home-authors.R:224 msgid "copyright holder" msgstr "版权所有者" #: build-home-authors.R:225 msgid "maintainer" msgstr "维护者" #: build-home-authors.R:226 msgid "data contributor" msgstr "数据提供者" #: build-home-authors.R:227 msgid "funder" msgstr "赞助者" #: build-home-authors.R:228 msgid "reviewer" msgstr "审核者" #: build-home-authors.R:229 msgid "thesis advisor" msgstr "论文导师" #: build-home-authors.R:230 msgid "translator" msgstr "翻译者" #: build-home-authors.R:286 render.R:108 msgid "Citation" msgstr "引用" #: build-home-authors.R:287 msgid "Citing %s" msgstr "引用 %s" #: build-home-community.R:22 msgid "Contributing guide" msgstr "开发指南" #: build-home-community.R:26 msgid "Code of conduct" msgstr "行为准则" #: build-home-community.R:30 msgid "Getting help" msgstr "获取帮助" #: build-home-community.R:37 msgid "Community" msgstr "社区" #: build-home-index.R:118 msgid "Dev Status" msgstr "开发状态" #: build-home-index.R:190 msgid "View on %s" msgstr "访问%s" #: build-home-index.R:191 msgid "Browse source code" msgstr "浏览源代码" #: build-home-index.R:192 msgid "Report a bug" msgstr "缺陷报告" #: build-home-index.R:196 msgid "Links" msgstr "链接" #: build-home-index.R:201 render.R:110 msgid "Table of contents" msgstr "目录" #: build-home-license.R:14 build-home-license.R:36 msgid "License" msgstr "许可" #: build-home-license.R:31 msgid "Full license" msgstr "许可全部条款" #: build-news.R:101 build-news.R:262 build-news.R:266 msgid "Changelog" msgstr "更改日志" #: build-news.R:128 msgid "Version %s" msgstr "%s 版" #: build-news.R:140 build-news.R:257 msgid "News" msgstr "新闻" #: build-news.R:259 msgid "Releases" msgstr "发布版本" #: build-news.R:314 msgid "CRAN release: %s" msgstr "CRAN发布版本:%s" #: build-reference-index.R:23 msgid "Package index" msgstr "包索引" #: build-reference-index.R:187 msgid "All functions" msgstr "所有函数" #: build-reference.R:377 msgid "Usage" msgstr "用法" #: build-tutorials.R:49 navbar.R:158 msgid "Tutorials" msgstr "教程" #: development.R:82 msgid "Released version" msgstr "已发布的版本" #: development.R:83 msgid "In-development version" msgstr "开发中的版本" #: development.R:84 msgid "Unreleased version" msgstr "未发布的版本" #: navbar-menu.R:212 msgid "Search site" msgstr "搜索网站" #: navbar-menu.R:213 msgid "Search for" msgstr "搜索" #: navbar.R:135 msgid "Reference" msgstr "参考" #: navbar.R:146 msgid "Light switch" msgstr "主题切换" #: navbar.R:149 msgid "Light" msgstr "浅色" #: navbar.R:150 msgid "Dark" msgstr "深色" #: navbar.R:151 msgid "Auto" msgstr "自动" #: navbar.R:187 msgid "Get started" msgstr "入门简介" #: navbar.R:228 msgid "More articles..." msgstr "更多文章…" #: package.R:317 msgid "deprecated" msgstr "已弃用" #: package.R:318 msgid "superseded" msgstr "已取代" #: package.R:319 msgid "experimental" msgstr "实验性" #: package.R:320 msgid "stable" msgstr "稳定" #: rd-data.R:23 msgid "Details" msgstr "细节" #: rd-data.R:27 msgid "Description" msgstr "概述" #: rd-data.R:31 msgid "References" msgstr "参考文献" #: rd-data.R:35 render.R:103 msgid "Source" msgstr "参考文献出处" #: rd-data.R:39 msgid "Format" msgstr "格式" #: rd-data.R:43 msgid "Note" msgstr "注释" #: rd-data.R:47 msgid "Author" msgstr "作者" #: rd-data.R:51 msgid "See also" msgstr "相关话题" #: rd-data.R:67 msgid "Arguments" msgstr "参数" #: rd-data.R:75 msgid "Value" msgstr "值" #: render.R:100 msgid "Skip to contents" msgstr "跳到正文" #: render.R:101 msgid "Toggle navigation" msgstr "切换导航栏" #: render.R:102 msgid "On this page" msgstr "该页面" #: render.R:104 msgid "Abstract" msgstr "摘要" #: render.R:105 msgid "Authors" msgstr "作者" #: render.R:106 msgid "Version" msgstr "版本" #: render.R:107 msgid "Examples" msgstr "范例" #: render.R:109 msgid "Additional details" msgstr "附加信息" #: render.R:111 msgid "Site navigation" msgstr "网站导航" #: repo.R:37 msgid "Source:" msgstr "来源:" #: tweak-homepage.R:68 msgid "Dev status" msgstr "开发状态" #: usage.R:52 msgid "# Default %s method" msgstr "# 默认 %s 方法" #: usage.R:54 msgid "# %s method for class '%s'" msgstr "# %2$s 类的 %1$s 方法" #~ msgid "Function reference" #~ msgstr "函数参考" pkgdown/R/0000755000176200001440000000000015102677747012144 5ustar liggesuserspkgdown/R/build-redirects.R0000644000176200001440000000734014770274305015345 0ustar liggesusers#' Build redirects #' #' @description #' If you change the structure of your documentation (by renaming vignettes or #' help topics) you can setup redirects from the old content to the new content. #' One or several now-absent pages can be redirected to a new page (or to a new #' section of a new page). This works by creating a html page that performs a #' "meta refresh", which isn't the best way of doing a redirect but works #' everywhere that you might deploy your site. #' #' The syntax is the following, with old paths on the left, and new paths or #' URLs on the right. #' #' ```yaml #' redirects: #' - ["articles/old-vignette-name.html", "articles/new-vignette-name.html"] #' - ["articles/another-old-vignette-name.html", "articles/new-vignette-name.html"] #' - ["articles/yet-another-old-vignette-name.html", "https://pkgdown.r-lib.org/dev"] #' ``` #' #' If for some reason you choose to redirect an existing page make sure to #' exclude it from the search index, see `?build_search`. #' #' @inheritParams as_pkgdown #' @export build_redirects <- function(pkg = ".", override = list()) { pkg <- section_init(pkg, override = override) has_url <- !is.null(config_pluck_string(pkg, "url")) redirects <- data_redirects(pkg, has_url) if (length(redirects) == 0) { return(invisible()) } cli::cli_rule("Building redirects") if (!has_url) { config_abort(pkg, "{.field url} is required to generate redirects.") } # Ensure user redirects override automatic ones from <- purrr::map_chr(redirects, 1) redirects <- redirects[!duplicated(from)] purrr::iwalk(redirects, build_redirect, pkg = pkg) } build_redirect <- function(entry, index, pkg) { new <- entry[2] old <- path(pkg$dst_path, entry[1]) path <- find_template("layout", "redirect", pkg = pkg) template <- read_file(path) url <- sprintf("%s/%s%s", config_pluck_string(pkg, "url"), pkg$prefix, new) lines <- whisker::whisker.render(template, list(url = url)) dir_create(path_dir(old)) if (!file_exists(old)) { cli::cli_inform("Adding redirect from {entry[1]} to {entry[2]}.") } write_lines(lines, old) } data_redirects <- function(pkg, has_url = FALSE, call = caller_env()) { c( if (has_url) reference_redirects(pkg), if (has_url) article_redirects(pkg), config_pluck_redirects(pkg, call = call) ) } reference_redirects <- function(pkg) { aliases <- unname(pkg$topics$alias) aliases <- purrr::map2(aliases, pkg$topics$name, setdiff) names(aliases) <- pkg$topics$file_out redirects <- invert_index(aliases) if (length(redirects) == 0) { return(list()) } names(redirects) <- paste0(names(redirects), ".html") # Ensure we don't create an invalid file name redirects <- redirects[valid_filename(names(redirects))] # Ensure we don't override an existing file redirects <- redirects[setdiff(names(redirects), pkg$topics$file_out)] unname(purrr::imap( redirects, function(to, from) paste0("reference/", c(from, to)) )) } valid_filename <- function(x) { x == path_sanitize(x) } article_redirects <- function(pkg) { is_vig_in_articles <- path_has_parent(pkg$vignettes$name, "articles") if (!any(is_vig_in_articles)) { return(NULL) } articles <- pkg$vignettes$file_out[is_vig_in_articles] purrr::map(articles, ~ paste0(c("articles/", ""), .x)) } config_pluck_redirects <- function(pkg, call = caller_env()) { redirects <- config_pluck_list(pkg, "redirects", call = call) for (i in seq_along(redirects)) { redirect <- redirects[[i]] if (!is.character(redirect) || length(redirect) != 2) { not <- obj_type_friendly(redirect) config_abort( pkg, "{.field redirects[{i}]} must be a character vector of length 2, not {not}.", call = call ) } } redirects } pkgdown/R/rd.R0000644000176200001440000000300015074163153012652 0ustar liggesusersrd_text <- function(x, fragment = TRUE) { con <- textConnection(x) on.exit(close(con), add = TRUE) set_classes(tools::parse_Rd(con, fragment = fragment, encoding = "UTF-8")) } rd_file <- function(path, pkg_path = NULL) { macros <- tools::loadPkgRdMacros(pkg_path) set_classes(tools::parse_Rd(path, macros = macros, encoding = "UTF-8")) } #' Translate an Rd string to its HTML output #' #' @param x Rd string. Backslashes must be double-escaped ("\\\\"). #' @param fragment logical indicating whether this represents a complete Rd file #' @param ... additional arguments for as_html #' #' @examples #' rd2html("a\n%b\nc") #' #' rd2html("a & b") #' #' rd2html("\\strong{\\emph{x}}") #' #' @export rd2html <- function(x, fragment = TRUE, ...) { html <- as_html(rd_text(x, fragment = fragment), ...) str_trim(strsplit(str_trim(html), "\n")[[1]]) } print.Rd <- function(x, ...) { utils::str(x) } #' @export print.tag <- function(x, ...) { utils::str(x) } # Convert RD attributes to S3 classes ------------------------------------- set_classes <- function(rd) { if (is.list(rd)) { rd[] <- lapply(rd, set_classes) } set_class(rd) } set_class <- function(x) { structure( x, class = c(attr(x, "class"), tag(x), "tag"), Rd_tag = NULL, srcref = NULL, macros = NULL ) } tag <- function(x) { tag <- attr(x, "Rd_tag") if (is.null(tag)) { return() } gsub("\\", "tag_", tag, fixed = TRUE) } #' @export `[.tag` <- function(x, ...) { structure(NextMethod(), class = class(x)) } pkgdown/R/build-quarto-articles.R0000644000176200001440000001244615102647422016475 0ustar liggesusersbuild_quarto_articles <- function(pkg = ".", article = NULL, quiet = TRUE) { pkg <- as_pkgdown(pkg) qmds <- pkg$vignettes[pkg$vignettes$type == "qmd", ] if (!is.null(article)) { qmds <- qmds[qmds$name == article, ] } if (nrow(qmds) == 0) { return() } if (pkg$bs_version < 5) { cli::cli_abort( c( "Quarto articles require Bootstrap 5.", "i" = "See details at {.url https://pkgdown.r-lib.org/articles/customise.html#getting-started}" ), call = NULL ) } check_installed("quarto") if (quarto::quarto_version() < "1.5") { cli::cli_abort( "Quarto articles require version 1.5 and above.", call = NULL ) } # Let user know what's happening old_digest <- purrr::map_chr(path(pkg$dst_path, qmds$file_out), file_digest) for (file in qmds$file_in) { cli::cli_inform("Reading {src_path(file)}") } cli::cli_inform("Running {.code quarto render}") # If needed, temporarily make a quarto project so we can build entire dir if (is.null(article)) { project_path <- path(pkg$src_path, "vignettes", "_quarto.yaml") if (!file_exists(project_path)) { yaml::write_yaml( list(project = list(render = list("*.qmd"))), project_path ) withr::defer(file_delete(project_path)) } } if (is.null(article)) { src_path <- path(pkg$src_path, "vignettes") } else { src_path <- path(pkg$src_path, qmds$file_in) } output_dir <- quarto_render(pkg, src_path, quiet = quiet) # check for articles (in the `vignette/articles` sense) article_dir <- fs::path(output_dir, "articles") if (fs::dir_exists(article_dir)) { fs::file_move(dir_ls(article_dir), output_dir) } # Read generated data from quarto template and render into pkgdown template unwrap_purrr_error(purrr::walk2( qmds$file_in, qmds$file_out, function(input_file, output_file) { built_path <- path(output_dir, path_rel(output_file, "articles")) if (!file_exists(built_path)) { cli::cli_abort("No built file found for {.file {input_file}}") } if (path_ext(output_file) == "html") { data <- data_quarto_article(pkg, built_path, input_file) render_page(pkg, "quarto", data, output_file, quiet = TRUE) update_html(path(pkg$dst_path, output_file), tweak_quarto_html) } else { file_copy(built_path, path(pkg$dst_path, output_file), overwrite = TRUE) } } )) # Report on which files have changed new_digest <- purrr::map_chr(path(pkg$dst_path, qmds$file_out), file_digest) changed <- new_digest != old_digest for (file in qmds$file_out[changed]) { writing_file(path(pkg$dst_path, file), file) } # Copy resources resources <- setdiff( dir_ls(output_dir, recurse = TRUE, type = "file"), path(output_dir, path_rel(qmds$file_out, "articles")) ) file_copy_to( src_paths = resources, dst_paths = path(pkg$dst_path, "articles", path_rel(resources, output_dir)), src_root = output_dir, dst_root = pkg$dst_path, src_label = NULL ) invisible() } quarto_render <- function(pkg, path, quiet = TRUE, frame = caller_env()) { # Override default quarto format metadata_path <- withr::local_tempfile( fileext = ".yml", pattern = "pkgdown-quarto-metadata-", ) write_yaml(quarto_format(pkg), metadata_path) output_dir <- withr::local_tempdir("pkgdown-quarto-", .local_envir = frame) quarto::quarto_render( path, metadata_file = metadata_path, quarto_args = c("--output-dir", output_dir), quiet = quiet, as_job = FALSE ) output_dir } quarto_format <- function(pkg) { list( lang = pkg$lang, format = list( html = list( template = system_file("quarto", "template.html", package = "pkgdown"), minimal = TRUE, theme = "none", `html-math-method` = config_math_rendering(pkg), `embed-resources` = FALSE, `citations-hover` = TRUE, `link-citations` = TRUE, `section-divs` = TRUE, toc = FALSE # pkgdown generates with js ) ) ) } data_quarto_article <- function(pkg, path, input_path) { html <- xml2::read_html(path, encoding = "UTF-8") meta_div <- xml2::xml_find_first(html, "//body/div[@class='meta']") # Manually drop any jquery deps head <- xpath_xml(html, "//head/script|//head/link") head <- head[!grepl("jquery", xml2::xml_attr(head, "src"))] list( pagetitle = escape_html(xpath_text(html, "//head/title")), toc = TRUE, source = repo_source(pkg, input_path), includes = list( head = xml2str(head), before = xpath_contents(html, "//body/div[@class='includes-before']"), after = xpath_contents(html, "//body/div[@class='includes-after']"), style = xpath_text(html, "//head/style") ), meta = list( title = xpath_contents(meta_div, "./h1"), subtitle = xpath_contents(meta_div, "./p[@class='subtitle']"), author = xpath_contents(meta_div, "./p[@class='author']"), date = xpath_contents(meta_div, "./p[@class='date']"), abstract = xpath_contents(meta_div, "./div[@class='abstract']") ), body = xpath_contents(html, "//main") ) } tweak_quarto_html <- function(html) { # If top-level headings use h1, move everything down one level h1 <- xml2::xml_find_all(html, "//h1") if (length(h1) > 1) { tweak_section_levels(html) } } pkgdown/R/render.R0000644000176200001440000002024615074163153013537 0ustar liggesusers#' Render page with template #' #' Each page is composed of four templates: "head", "header", "content", and #' "footer". Each of these templates is rendered using the `data`, and #' then assembled into an overall page using the "layout" template. #' #' @param pkg Path to package to document. #' @param name Name of the template (e.g. "home", "vignette", "news") #' @param data Data for the template. #' #' This is automatically supplemented with three lists: #' #' * `site`: `title` and path to `root`. #' * `yaml`: the `template` key from `_pkgdown.yml`. #' * `package`: package metadata including `name` and`version`. #' #' See the full contents by running [data_template()]. #' @param path Location to create file; relative to destination directory. #' @param depth Depth of path relative to base directory. #' @param quiet If `quiet`, will suppress output messages #' @export render_page <- function( pkg = ".", name, data, path, depth = NULL, quiet = FALSE ) { pkg <- as_pkgdown(pkg) if (is.null(depth)) { depth <- dir_depth(path) } html <- render_page_html(pkg, name = name, data = data, depth = depth) tweak_page(html, name, pkg = pkg) activate_navbar(html, data$output_file %||% path, pkg) rendered <- as.character(html, options = character()) write_if_different(pkg, rendered, path, quiet = quiet) } render_page_html <- function(pkg, name, data = list(), depth = 0L) { data <- modify_list(data_template(pkg, depth = depth), data) # render template components pieces <- c( "head", "in-header", "before-body", "navbar", "content", "footer", "after-body", if (pkg$bs_version == 3) c("header", "docsearch") ) templates <- purrr::map_chr(pieces, find_template, name = name, pkg = pkg) components <- purrr::map(templates, render_template, data = data) components <- purrr::set_names(components, pieces) components$template <- name components$lang <- pkg$lang components$translate <- data$translate # render complete layout template <- find_template("layout", name, pkg = pkg) rendered <- render_template(template, components) # Strip trailing whitespace rendered <- gsub(" +\n", "\n", rendered, perl = TRUE) xml2::read_html(rendered, encoding = "UTF-8") } #' @export #' @rdname render_page data_template <- function(pkg = ".", depth = 0L) { pkg <- as_pkgdown(pkg) out <- list() # Basic metadata out$package <- list( name = pkg$package, version = as.character(pkg$version) ) if (has_logo(pkg)) { out$logo <- list(src = logo_path(pkg, depth = depth)) } out$site <- list( root = up_path(depth), title = config_pluck_string(pkg, "title", default = pkg$package) ) out$year <- strftime(Sys.time(), "%Y") # Language and translations out$lang <- pkg$lang out$translate <- list( skip = tr_("Skip to contents"), toggle_nav = tr_("Toggle navigation"), on_this_page = tr_("On this page"), source = tr_("Source"), abstract = tr_("Abstract"), authors = tr_("Authors"), version = tr_("Version"), examples = tr_("Examples"), citation = tr_("Citation"), author_details = tr_("Additional details"), toc = tr_("Table of contents"), site_nav = tr_("Site navigation") ) # Components that mostly end up in the out$has_favicons <- has_favicons(pkg) out$opengraph <- data_open_graph(pkg) out$extra <- list( css = path_first_existing(pkg$src_path, "pkgdown", "extra.css"), js = path_first_existing(pkg$src_path, "pkgdown", "extra.js") ) out$includes <- config_pluck(pkg, "template.includes") out$yaml <- config_pluck(pkg, "template.params") # Force inclusion so you can reliably refer to objects inside yaml # in the mustache templates out$yaml$.present <- TRUE if (pkg$bs_version > 3) { out$headdeps <- data_deps(pkg = pkg, depth = depth) } # Development settings; tooltip needs to be generated at render time out$development <- pkg$development out$development$version_tooltip <- version_tooltip(pkg$development$mode) out$navbar <- data_navbar(pkg, depth = depth) out$footer <- data_footer(pkg) out$lightswitch <- uses_lightswitch(pkg) out$uses_katex <- config_math_rendering(pkg) == "katex" out$uses_mathjax <- config_math_rendering(pkg) == "mathjax" print_yaml(out) } data_open_graph <- function(pkg = ".", call = caller_env()) { pkg <- as_pkgdown(pkg) og <- config_pluck_list(pkg, "template.opengraph", default = list()) og <- check_open_graph(pkg, og, call = call) logo <- find_logo(pkg$src_path) if (is.null(og$image) && !is.null(logo)) { og$image <- list(src = path_file(logo)) } if (!is.null(og$image) && !grepl("^http", og$image$src)) { site_url <- config_pluck(pkg, "url", default = "/") if (!grepl("/$", site_url)) { site_url <- paste0(site_url, "/") } og$image$src <- gsub("^man/figures/", "reference/figures/", og$image$src) og$image$src <- paste0(site_url, og$image$src) } if (!is.null(og$twitter)) { og$twitter$card <- og$twitter$card %||% "summary" og$twitter$creator <- og$twitter$creator %||% og$twitter$site og$twitter$site <- og$twitter$site %||% og$twitter$creator } og } check_open_graph <- function(pkg, og, file_path = NULL, call = caller_env()) { if (is.null(og)) { return() } is_yaml <- is.null(file_path) base_path <- if (is_yaml) "template.opengraph" else "opengraph" check_open_graph_list( pkg, og, file_path = file_path, error_path = base_path, error_call = call ) supported_fields <- c("image", "twitter") unsupported_fields <- setdiff(names(og), supported_fields) if (length(unsupported_fields)) { msg <- "{.field {base_path}} contains unsupported fields {.val {unsupported_fields}}." config_warn(pkg, msg, path = file_path, call = call) } check_open_graph_list( pkg, og$twitter, file_path = file_path, error_path = paste0(base_path, ".twitter"), error_call = call ) if ( !is.null(og$twitter) && is.null(og$twitter$creator) && is.null(og$twitter$site) ) { msg <- "{.field opengraph.twitter} must include either {.field creator} or {.field site}." config_abort(pkg, msg, path = file_path, call = call) } check_open_graph_list( pkg, og$image, file_path = file_path, error_path = paste0(base_path, ".image"), error_call = call ) og[intersect(supported_fields, names(og))] } render_template <- function(path, data) { template <- read_file(path) if (length(template) == 0) { return("") } whisker::whisker.render(template, data) } check_open_graph_list <- function( pkg, x, file_path, error_path, error_call = caller_env() ) { if (is.list(x) || is.null(x)) { return() } not <- obj_type_friendly(x) config_abort( pkg, "{.field {error_path}} must be a list, not {not}.", path = file_path, call = error_call ) } write_if_different <- function( pkg, contents, path, quiet = FALSE, check = TRUE ) { # Almost all uses are relative to destination, except for rmarkdown templates full_path <- path_abs(path, start = pkg$dst_path) if (check && !made_by_pkgdown(full_path)) { cli::cli_inform("Skipping {.file {path}}: not generated by pkgdown") return(FALSE) } if (same_contents(full_path, contents)) { # touching the file to update its modification time # which is important for proper lazy behavior file_touch(full_path) return(FALSE) } if (!quiet) { writing_file(path_rel(full_path, pkg$dst_path), path) } write_lines(contents, path = full_path) TRUE } same_contents <- function(path, contents) { if (!file_exists(path)) { return(FALSE) } new_hash <- rlang::hash(contents) cur_contents <- paste0(read_lines(path), collapse = "\n") cur_hash <- rlang::hash(cur_contents) identical(new_hash, cur_hash) } file_digest <- function(path) { if (file_exists(path)) { rlang::hash_file(path) } else { "MISSING" } } made_by_pkgdown <- function(path) { if (!file_exists(path)) { return(TRUE) } first <- paste(read_lines(path, n = 2), collapse = "\n") check_made_by(first) } check_made_by <- function(first) { if (length(first) == 0L) { return(FALSE) } grepl("` and #' ``, as e.g. created by `usethis::use_readme_md()` #' or `usethis::use_readme_rmd()`. There should always be an empty line after #' the `` line. If you divide badges into paragraphs, #' make sure to add an empty line before the `` line. #' #' - Any image-containing links within `
    `. #' #' - Within the first paragraph, if it only contains image-containing links. #' #' Identified badges are **removed** from the _main content_. #' They are shown or not in the _sidebar_ depending on the development mode and #' sidebar customization, see the sidebar section. #' #' # Authors #' #' By default, pkgdown will display author information in three places: #' #' * the sidebar, #' * the left part side of the footer, #' * the author page. #' #' This documentation describes how to customise the overall author display. #' See `?build_home` and `?build_site` for details about changing the location #' of the authors information within the home sidebar and the site footer. #' #' ## Authors ORCID, ROR and bio #' #' Author ORCID identification numbers in the `DESCRIPTION` are linked using #' the ORCID logo, #' author ROR identification numbers are linked using the ROR logo: #' #' ```r #' Authors@R: c( #' person("Hadley", "Wickham", , "hadley@rstudio.com", role = c("aut", "cre"), #' comment = c(ORCID = "0000-0003-4757-117X") #' ), #' person("Jay", "Hesselberth", role = "aut", #' comment = c(ORCID = "0000-0002-6299-179X") #' ), #' person("Posit Software, PBC", role = c("cph", "fnd"), #' comment = c(ROR = "03wc8by49")) #' ) #' ``` #' #' If you want to add more details about authors or their involvement with the #' package, you can use the comment field, which will be rendered on the #' authors page. #' #' ```r #' Authors@R: c( #' person("Hadley", "Wickham", , "hadley@rstudio.com", role = c("aut", "cre"), #' comment = c(ORCID = "0000-0003-4757-117X", "Indenter-in-chief") #' ), #' person("Jay", "Hesselberth", role = "aut", #' comment = c(ORCID = "0000-0002-6299-179X") #' ) #' ) #' ``` #' #' ## Additional control via YAML #' #' You can control additional aspects of the authors display via the `authors` #' YAML field: #' #' * display of each author in the footer, sidebar and authors page, #' * which authors (by role) are displayed in the sidebar and footer, #' * text before authors in the footer, #' * text before and after authors in the sidebar, #' * text before and after authors on the authors page. #' #' You can modify how each author's name is displayed by adding a subsection #' for `authors`. Each entry in `authors` should be named the author's name #' (matching `DESCRIPTION`) and can contain `href` and/or `html` fields: #' #' * If `href` is provided, the author's name will be linked to this URL. #' * If `html` is provided, it will be shown instead of the author's name. #' This is particularly useful if you want to display the logo of a corporate #' sponsor. Use an absolute URL to an image, not a relative link. Use an empty #' alternative text rather than no alternative text so a screen-reader would #' skip over it. #' #' ```yaml #' authors: #' firstname lastname: #' href: "http://name-website.com" #' html: "" #' ``` #' #' #' By default, the "developers" list shown in the sidebar and footer is #' populated by the maintainer ("cre"), authors ("aut"), and funder ("fnd") #' from the `DESCRIPTION`. You could choose other roles for filtering. #' With the configuration below: #' #' * only the maintainer and funder(s) appear in the footer, after the text #' "Crafted by", #' * all authors and contributors appear in the sidebar, #' * the authors list on the sidebar is preceded and followed by some text, #' * the authors list on the authors page is preceded and followed by some text. #' #' #' ```yaml #' authors: #' footer: #' roles: [cre, fnd] #' text: "Crafted by" #' sidebar: #' roles: [aut, ctb] #' before: "So *who* does the work?" #' after: "Thanks all!" #' before: "This package is proudly brought to you by:" #' after: "See the [changelog](news/index.html) for other contributors. :pray:" #' ``` #' #' If you want to filter authors based on something else than their roles, #' consider using a custom sidebar/footer component #' (see `?build_home`/`?build_site`, respectively). #' #' # Sidebar #' #' You can customise the homepage sidebar with the `home.sidebar` field. #' It's made up of two pieces: `structure`, which defines the overall layout, #' and `components`, which defines what each piece looks like. This organisation #' makes it easy to mix and match the pkgdown defaults with your own #' customisations. #' #' This is the default structure: #' #' ``` yaml #' home: #' sidebar: #' structure: [links, license, community, citation, authors, dev] #' ``` #' #' These are drawn from seven built-in components: #' #' - `links`: automated links generated from `URL` and `BugReports` fields #' from `DESCRIPTION` plus manual links from the `home.links` field: #' #' ``` yaml #' home: #' links: #' - text: Link text #' href: https://website.com #' - text: Roadmap #' href: /roadmap.html #' ``` #' #' - `license`: Licensing information if `LICENSE`/`LICENCE` or #' `LICENSE.md`/`LICENCE.md` files are present. #' #' - `community`: links to to `.github/CONTRIBUTING.md`, #' `.github/CODE_OF_CONDUCT.md`, etc. #' #' - `citation`: link to package citation information. Uses either #' `inst/CITATION` or, if absent, information from the `DESCRIPTION`. #' #' - `authors`: selected authors from the `DESCRIPTION`. #' #' - `dev`: development status badges extracted from `README.md`/`index.md`. #' This is only shown for "development" versions of websites; see #' "Development mode" in `?build_site` for details. #' #' - `toc`: a table of contents for the README (not shown by default). #' #' You can also add your own components, where `text` is markdown text: #' #' ``` yaml #' home: #' sidebar: #' structure: [authors, custom, toc, dev] #' components: #' custom: #' title: Funding #' text: We are *grateful* for funding! #' ``` #' #' Alternatively, you can provide a ready-made sidebar HTML: #' #' ``` yaml #' home: #' sidebar: #' html: path-to-sidebar.html #' ``` #' #' Or completely remove it: #' #' ``` yaml #' home: #' sidebar: FALSE #' ``` #' @inheritParams build_articles #' @family site components #' @export #' @order 1 build_home <- function( pkg = ".", override = list(), preview = FALSE, quiet = TRUE ) { pkg <- section_init(pkg, override = override) check_bool(quiet) cli::cli_rule("Building home") build_citation_authors(pkg) build_home_md(pkg) build_home_license(pkg) build_home_index(pkg, quiet = quiet) if (!pkg$development$in_dev) { build_404(pkg) } preview_site(pkg, "/", preview = preview) } pkgdown/R/templates.R0000644000176200001440000000335114634573316014263 0ustar liggesusersfind_template <- function(type, name, ext = ".html", pkg = ".") { pkg <- as_pkgdown(pkg) paths <- template_candidates(type = type, name = name, ext = ext, pkg = pkg) existing <- paths[file_exists(paths)] if (length(existing) == 0) { tname <- paste0(type, "-", name) cli::cli_abort( "Can't find template for {.val {tname}}.", call = caller_env() ) } existing[[1]] } # Used for testing read_template_html <- function(type, name, pkg = list()) { if (is_list(pkg)) { # promote to a shell "pkgdown" object so we don't need a complete pkg class(pkg) <- "pkgdown" } path <- find_template(type = type, name = name, pkg = pkg) xml2::read_html(path) } template_candidates <- function(type, name, ext = ".html", pkg = list()) { paths <- c( path(pkg$src_path, "pkgdown", "templates"), templates_dir(pkg), path_pkgdown(paste0("BS", pkg$bs_version), "templates") ) names <- c(paste0(type, "-", name, ext), paste0(type, ext)) all <- expand.grid(paths, names) path(all[[1]], all[[2]]) } # Find directory where custom templates might live: # * path supplied in `template.path` # * package supplied in `template.package` # * templates in package itself templates_dir <- function(pkg = list(), call = caller_env()) { config_pluck_list(pkg, "template") path <- config_pluck_string(pkg, "template.path") package <- config_pluck_string(pkg, "template.package") if (!is.null(path)) { if (!dir_exists(path)) { cli::cli_abort("Can't find templates path: {src_path(path)}", call = call) } path_abs(path, start = pkg$src_path) } else if (!is.null(package)) { path_package_pkgdown("templates", package, pkg$bs_version) } else { path(pkg$src_path, "pkgdown", "templates") } } pkgdown/R/build-home-index.R0000644000176200001440000001544715074163153015421 0ustar liggesusers#' @export #' @rdname build_home build_home_index <- function(pkg = ".", override = list(), quiet = TRUE) { pkg <- section_init(pkg, override = override) src_path <- path_index(pkg) dst_path <- path(pkg$dst_path, "index.html") data <- data_home(pkg) if (is.null(src_path)) { cli::cli_inform("Reading {.file DESCRIPTION}") data$index <- linkify(pkg$desc$get_field("Description", "")) } else { cli::cli_inform("Reading {src_path(path_rel(src_path, pkg$src_path))}") local_options_link(pkg, depth = 0L) data$index <- markdown_body(pkg, src_path) } cur_digest <- file_digest(dst_path) render_page(pkg, "home", data, "index.html", quiet = quiet) strip_header <- config_pluck_bool(pkg, "home.strip_header", default = FALSE) hide_badges <- pkg$development$mode == "release" && !pkg$development$in_dev update_html( dst_path, tweak_homepage_html, strip_header = strip_header, sidebar = !isFALSE(pkg$meta$home$sidebar), show_badges = !hide_badges, bs_version = pkg$bs_version, logo = logo_path(pkg, depth = 0) ) new_digest <- file_digest(dst_path) if (cur_digest != new_digest) { writing_file(path_rel(dst_path, pkg$dst_path), "index.html") } invisible() } path_index <- function(pkg) { path_first_existing( pkg$src_path, c("pkgdown/index.md", "index.md", "README.md") ) } data_home <- function(pkg = ".", call = caller_env()) { pkg <- as_pkgdown(pkg) config_pluck_list(pkg, "home", call = call) title <- config_pluck_string( pkg, "home.title", default = cran_unquote(pkg$desc$get_field("Title", "")), call = call ) description <- config_pluck_string( pkg, "home.description", default = cran_unquote(pkg$desc$get_field("Description", "")), call = call ) trailing_slash <- config_pluck_bool( pkg, "template.trailing_slash_redirect", default = FALSE, call = call ) print_yaml(list( pagetitle = title, sidebar = data_home_sidebar(pkg, call = call), opengraph = list(description = description), has_trailingslash = trailing_slash )) } data_home_sidebar <- function(pkg = ".", call = caller_env()) { pkg <- as_pkgdown(pkg) sidebar <- config_pluck(pkg, "home.sidebar") if (isFALSE(sidebar)) { return(FALSE) } config_pluck_list(pkg, "home", call = call) html_path <- config_pluck_string(pkg, "home.sidebar.html", call = call) if (!is.null(html_path)) { html_path_abs <- path(pkg$src_path, html_path) if (!file_exists(html_path_abs)) { msg <- "{.field home.sidebar.html} specifies a file that doesn't exist ({.file {html_path}})." config_abort(pkg, msg, call = call) } return(read_file(html_path_abs)) } structure <- config_pluck_character( pkg, "home.sidebar.structure", default = default_sidebar_structure(), call = call ) # compute all default sections default_components <- list( links = data_home_sidebar_links(pkg), license = data_home_sidebar_license(pkg), community = data_home_sidebar_community(pkg), citation = data_home_sidebar_citation(pkg), authors = data_home_sidebar_authors(pkg), dev = sidebar_section( tr_("Dev Status"), "placeholder", class = "dev-status" ), toc = data_home_toc(pkg) ) needs_components <- setdiff(structure, names(default_components)) custom_yaml <- config_pluck_sidebar_components( pkg, needs_components, call = call ) custom_components <- purrr::map(custom_yaml, function(x) { sidebar_section(x$title, markdown_text_block(pkg, x$text)) }) components <- modify_list(default_components, custom_components) sidebar <- purrr::compact(components[structure]) paste0(sidebar, collapse = "\n") } # Update sidebar-configuration.Rmd if this changes default_sidebar_structure <- function() { c("links", "license", "community", "citation", "authors", "dev") } config_pluck_sidebar_components <- function( pkg, new_components, call = caller_env() ) { base_path <- "home.sidebar.components" components <- config_pluck_list( pkg, base_path, has_names = new_components, call = call ) for (name in names(components)) { component <- components[[name]] component_path <- paste0(base_path, ".", name) config_pluck_list( pkg, component_path, has_names = c("title", "text"), call = call ) config_pluck_string(pkg, paste0(component_path, ".title"), call = call) config_pluck_string(pkg, paste0(component_path, ".text"), call = call) } components } data_home_sidebar_links <- function(pkg = ".") { pkg <- as_pkgdown(pkg) repo <- cran_link(pkg$package) links <- config_pluck(pkg, "home.links") bug_reports <- pkg$desc$get_field("BugReports", default = NULL) if ( !is.null(bug_reports) && grepl("@", bug_reports) && !startsWith(bug_reports, "http") ) { bug_reports <- paste0("mailto:", bug_reports) } links <- c( link_url(sprintf(tr_("View on %s"), repo$repo), repo$url), link_url(tr_("Browse source code"), repo_home(pkg)), link_url(tr_("Report a bug"), bug_reports), purrr::map_chr(links, ~ link_url(.$text, .$href)) ) sidebar_section(tr_("Links"), links) } data_home_toc <- function(pkg) { sidebar_section( tr_("Table of contents"), '' ) } sidebar_section <- function(heading, bullets, class = make_slug(heading)) { if (length(bullets) == 0) { return(character()) } paste0( "
    \n", "

    ", heading, "

    \n", "
      \n", paste0("
    • ", bullets, "
    • \n", collapse = ""), "
    \n", "
    \n" ) } cran_link <- function(pkg) { cran_url <- paste0("https://cloud.r-project.org/package=", pkg) req <- httr2::request(cran_url) req <- req_pkgdown_cache(req) req <- httr2::req_error(req, function(resp) FALSE) resp <- httr2::req_perform(req) if (!httr2::resp_is_error(resp)) { return(list(repo = "CRAN", url = cran_url)) } # bioconductor always returns a 200 status, redirecting to /removed-packages/ bioc_url <- paste0("https://www.bioconductor.org/packages/", pkg) req <- httr2::request(bioc_url) req <- req_pkgdown_cache(req) req <- httr2::req_error(req, function(resp) FALSE) req <- httr2::req_retry(req, max_tries = 3) resp <- httr2::req_perform(req) if ( !httr2::resp_is_error(resp) && !grepl("removed-packages", httr2::resp_url(resp)) ) { return(list(repo = "Bioconductor", url = bioc_url)) } NULL } req_pkgdown_cache <- function(req) { cache_path <- dir_create(path(tools::R_user_dir("pkgdown", "cache"), "http")) httr2::req_cache( req, path = cache_path, max_age = 86400 # 1 day ) } # authors forced to wrap words in '' to prevent spelling errors cran_unquote <- function(string) { gsub("\\'(.*?)\\'", "\\1", string) } pkgdown/R/navbar.R0000644000176200001440000001754115074163153013535 0ustar liggesusersdata_navbar <- function(pkg = ".", depth = 0L, call = caller_env()) { pkg <- as_pkgdown(pkg) navbar <- config_pluck(pkg, "navbar") if (uses_lightswitch(pkg)) { style <- NULL } else { style <- navbar_style( navbar = navbar, theme = get_bslib_theme(pkg), bs_version = pkg$bs_version ) } links <- navbar_links(pkg, depth = depth, call = call) c(style, links) } uses_lightswitch <- function(pkg) { config_pluck_bool(pkg, "template.light-switch", default = FALSE) } # Default navbar ---------------------------------------------------------- navbar_style <- function(navbar = list(), theme = "_default", bs_version = 3) { if (bs_version == 3) { list(type = navbar$type %||% "default") } else { # bg is usually light, dark, or primary, but can use any .bg-* bg <- navbar$bg %||% bootswatch_bg[[theme]] %||% "light" type <- navbar$type %||% if (bg == "light") "light" else "dark" list(bg = bg, type = type) } } navbar_structure <- function() { print_yaml(list( left = c("intro", "reference", "articles", "tutorials", "news"), right = c("search", "github", "lightswitch") )) } navbar_links <- function(pkg, depth = 0L, call = caller_env()) { components <- navbar_link_components(pkg, call = call) list( left = render_navbar_links( components$left, depth = depth, pkg = pkg, side = "left" ), right = render_navbar_links( components$right, depth = depth, pkg = pkg, side = "right" ) ) } navbar_link_components <- function(pkg, call = caller_env()) { # Combine default components with user supplied: must not merge recursively components <- navbar_components(pkg) components_meta <- config_pluck(pkg, "navbar.components", default = list()) components[names(components_meta)] <- components_meta components <- purrr::compact(components) # Combine default structure with user supplied # (must preserve NULLs in yaml to mean display nothing) pkg$meta$navbar$structure <- modify_list( navbar_structure(), config_pluck(pkg, "navbar.structure") ) right_comp <- intersect( config_pluck_character(pkg, "navbar.structure.right", call = call), names(components) ) left_comp <- intersect( config_pluck_character(pkg, "navbar.structure.left", call = call), names(components) ) # Backward compatibility left <- config_pluck(pkg, "navbar.left") %||% components[left_comp] right <- config_pluck(pkg, "navbar.right") %||% components[right_comp] list(left = left, right = right) } render_navbar_links <- function(x, depth = 0L, pkg, side = c("left", "right")) { if (!is.list(x)) { config_abort( pkg, c( "{.field navbar} is incorrectly specified.", i = "See details in {.vignette pkgdown::customise}." ), call = quote(data_template()) ) } check_number_whole(depth, min = 0) side <- arg_match(side) tweak <- function(x) { if (!is.null(x$menu)) { x$menu <- lapply(x$menu, tweak) x } else if (!is.null(x$href) && !grepl("://", x$href, fixed = TRUE)) { x$href <- paste0(up_path(depth), x$href) x } else { x } } if (depth != 0L) { x <- lapply(x, tweak) } if (pkg$bs_version == 3) { rmarkdown::navbar_links_html(x) } else { navbar_html_list(x, path_depth = depth, side = side) } } # Components -------------------------------------------------------------- navbar_components <- function(pkg = ".") { pkg <- as_pkgdown(pkg) menu <- list() menu$reference <- menu_link(tr_("Reference"), "reference/index.html") # in BS3, search is hardcoded in the template if (pkg$bs_version == 5) { menu$search <- menu_search() } if (uses_lightswitch(pkg)) { menu$lightswitch <- menu_submenu( text = NULL, icon = "fa-sun", label = tr_("Light switch"), id = "lightswitch", list( menu_theme(tr_("Light"), icon = "fa-sun", theme = "light"), menu_theme(tr_("Dark"), icon = "fa-moon", theme = "dark"), menu_theme(tr_("Auto"), icon = "fa-adjust", theme = "auto") ) ) } if (!is.null(pkg$tutorials)) { menu$tutorials <- menu_submenu( tr_("Tutorials"), menu_links(pkg$tutorials$title, pkg$tutorials$file_out) ) } menu$news <- navbar_news(pkg) menu$github <- switch( repo_type(pkg), github = menu_icon("fab fa-github fa-lg", repo_home(pkg), "GitHub"), gitlab = menu_icon("fab fa-gitlab fa-lg", repo_home(pkg), "GitLab"), codeberg = menu_icon("fas fa-code fa-lg", repo_home(pkg), "Codeberg"), NULL ) menu <- c(menu, navbar_articles(pkg)) print_yaml(menu) } navbar_articles <- function(pkg = ".") { pkg <- as_pkgdown(pkg) menu <- list() vignettes <- pkg$vignettes pkg_intro <- article_is_intro(vignettes$name, pkg$package) if (any(pkg_intro)) { intro <- vignettes[pkg_intro, , drop = FALSE] menu$intro <- menu_link(tr_("Get started"), intro$file_out) } if (!has_name(pkg$meta, "articles")) { vignettes <- vignettes[!pkg_intro, , drop = FALSE] menu$articles <- menu_submenu( tr_("Articles"), menu_links(vignettes$title, vignettes$file_out) ) } else { articles_index <- config_pluck(pkg, "articles") articles <- data_articles(pkg) navbar <- purrr::keep(articles_index, ~ has_name(.x, "navbar")) if (length(navbar) == 0) { # No articles to be included in navbar so just link to index menu$articles <- menu_link(tr_("Articles"), "articles/index.html") } else { sections <- purrr::imap(navbar, function(section, index) { idx <- select_topics( section$contents, articles, error_pkg = pkg, error_path = paste0("articles[", index, "].contents") ) vig <- articles[idx, , drop = FALSE] vig <- vig[vig$name != pkg$package, , drop = FALSE] c( if (!is.null(section$navbar)) { list(menu_separator(), menu_heading(section$navbar)) }, menu_links(vig$title, vig$href) ) }) children <- unlist(sections, recursive = FALSE, use.names = FALSE) if (length(navbar) != length(articles_index)) { children <- c( children, list( menu_separator(), menu_link(tr_("More articles..."), "articles/index.html") ) ) } menu$articles <- menu_submenu(tr_("Articles"), children) } } print_yaml(menu) } # Testing helpers --------------------------------------------------------- # Simulate minimal package structure so we can more easily test pkg_navbar <- function( meta = NULL, vignettes = pkg_navbar_vignettes(), github_url = NULL ) { structure( list( package = "test", src_path = file_temp(), meta = meta, vignettes = vignettes, repo = list(url = list(home = github_url)), bs_version = 5 ), class = "pkgdown" ) } pkg_navbar_vignettes <- function( name = character(), title = NULL, file_out = NULL ) { title <- title %||% paste0("Title ", name) file_out <- file_out %||% paste0(name, ".html") tibble::tibble(name = name, title = title, file_out, description = "desc") } # bootswatch defaults ----------------------------------------------------- # Scraped from bootswatch preivews, see code in # bootswatch_bg <- list( "_default" = "light", cerulean = "primary", cosmo = "primary", cyborg = "dark", darkly = "primary", flatly = "primary", journal = "light", litera = "light", lumen = "light", lux = "light", materia = "primary", minty = "primary", morph = "primary", pulse = "primary", quartz = "primary", sandstone = "primary", simplex = "light", sketchy = "light", slate = "primary", solar = "dark", spacelab = "light", superhero = "dark", united = "primary", vapor = "primary", yeti = "primary", zephyr = "primary" ) pkgdown/R/build-footer.R0000644000176200001440000000314014770274305014651 0ustar liggesusersdata_footer <- function(pkg = ".", call = caller_env()) { pkg <- as_pkgdown(pkg) config_pluck_list(pkg, "footer", call = call) meta_components <- config_pluck_list(pkg, "footer.components", call = call) components <- modify_list( footnote_components(pkg, call = call), meta_components ) meta_structure <- config_pluck_list(pkg, "footer.structure", call = call) structure <- modify_list(footnote_structure(), meta_structure) left <- markdown_text_block( pkg, paste0(components[structure$left], collapse = " ") ) right <- markdown_text_block( pkg, paste0(components[structure$right], collapse = " ") ) list(left = left, right = right) } footnote_components <- function(pkg = ".", call = caller_env()) { pkg <- as_pkgdown(pkg) # Authors roles <- config_pluck_character( pkg, "authors.footer.roles", default = default_roles(), call = call ) authors <- data_authors(pkg, roles = roles)$main authors_str <- paste(purrr::map_chr(authors, "name"), collapse = ", ") prefix <- config_pluck_string( pkg, "authors.footer.text", default = tr_("Developed by"), call = call ) developed_by <- paste0(trimws(prefix), " ", authors_str, ".") # pkgdown built_with <- sprintf( tr_('Site built with pkgdown %s.'), "https://pkgdown.r-lib.org/", utils::packageVersion("pkgdown") ) print_yaml(list( developed_by = developed_by, built_with = built_with, package = pkg[["package"]] )) } footnote_structure <- function() { print_yaml(list( left = "developed_by", right = "built_with" )) } pkgdown/R/pkgdown.R0000644000176200001440000000067014634573316013737 0ustar liggesusers#' Determine if code is executed by pkgdown #' #' This is occasionally useful when you need different behaviour by #' pkgdown and regular documentation. #' #' @export #' @examples #' in_pkgdown() in_pkgdown <- function() { identical(Sys.getenv("IN_PKGDOWN"), "true") } local_envvar_pkgdown <- function(pkg, scope = parent.frame()) { withr::local_envvar( IN_PKGDOWN = "true", LANGUAGE = pkg$lang, .local_envir = scope ) } pkgdown/R/rd-example.R0000644000176200001440000001307615074163153014321 0ustar liggesusersrd2ex <- function(x, ...) { x <- rd_text(paste0("\\examples{", x, "}"), fragment = FALSE)[[1]] x <- process_conditional_examples(x) x <- flatten_ex(x, ...) if (grepl("\n", x)) { strsplit(x, "\n")[[1]] } else { x } } run_examples <- function( x, topic = "unknown", env = globalenv(), run_dont_run = FALSE ) { if (!inherits(x, "tag")) { x <- rd_text(x) } # Trim newline that usually occurs after \examples{ if (is_newline(x[[1]], trim = TRUE)) { x <- x[-1] } x <- process_conditional_examples(x) code <- flatten_ex(x, run_dont_run = run_dont_run) if (!can_parse(code)) { cli::cli_warn("Failed to parse example for topic {.val {topic}}") return("") } if (!is.null(env)) { highlight_examples(code, topic, env = env) } else { highlight_text(code) } } process_conditional_examples <- function(rd) { if (is.list(rd)) { which_exif <- which(purrr::map_lgl(rd, function(x) { "tag_dontshow" %in% class(x) && is.character(x[[1]]) && grepl("# examplesIf$", x[[1]]) })) if (length(which_exif) == 0) { return(rd) } if (length(which_exif) %% 2 != 0) { cli::cli_abort("@examplesIf error, not closed?", call = caller_env()) } remove <- integer() modes <- c("begin", "end") for (idx in which_exif) { if (rd[[idx]] != "}) # examplesIf") { # Start of @examplesIf if (modes[1] == "end") { cli::cli_abort("@examplesIf error, not closed?", call = caller_env()) } cond_expr <- parse(text = paste0(rd[[idx]], "\n})"))[[1]][[2]] cond <- eval(cond_expr) if (isTRUE(cond)) { remove <- c(remove, idx, idx + 1L) } else { cond_expr_str <- deparse1(cond_expr) is_false <- cond_expr_str == "FALSE" if (!is_false) { new_cond <- paste0("if (FALSE) { # ", cond_expr_str) cli::cli_warn( "@examplesIf condition {.val {cond_expr_str}} is {.val FALSE}" ) } else { new_cond <- "if (FALSE) {" } rd[[idx]] <- structure(list(new_cond), class = c("RCODE", "tag")) } } else { # End of @examplesIf if (modes[1] == "begin") { cli::cli_abort( "@examplesIf error, closed twice?", call = caller_env() ) } if (isTRUE(cond)) { remove <- c(remove, idx, idx + 1L) } else { rd[[idx]] <- structure(list("}"), class = c("RCODE", "tag")) } } modes <- rev(modes) } if (length(remove)) { rd <- rd[-remove] } rd } else { rd } } # as_example -------------------------------------------------------------- as_example <- function(x, run_dont_run = FALSE) { UseMethod("as_example") } #' @export as_example.RCODE <- function(x, run_dont_run = FALSE) as.character(x) #' @export as_example.VERB <- as_example.RCODE #' @export as_example.TEXT <- as_example.RCODE #' @export as_example.COMMENT <- function(x, run_dont_run = FALSE) { if (grepl("^%[^ ]*%", x)) { meant <- gsub("%", "\\\\%", x) xun <- unclass(x) cli::cli_warn(c( "In the examples, {.val {xun}} is an Rd comment", "x" = "did you mean {.val {meant}}?" )) } "" } #' @export as_example.tag_dontrun <- function(x, run_dont_run = FALSE) { if (run_dont_run) { block_tag_to_comment("\\dontrun", x, run_dont_run = run_dont_run) } else { ex <- flatten_ex(x, run_dont_run = run_dont_run) if (is_newline(x[[1]], trim = TRUE)) { paste0("if (FALSE) { # \\dontrun{", ex, "} # }") } else { paste0("if (FALSE) ", ex, " # \\dontrun{}") } } } #' @export as_example.tag_donttest <- function(x, run_dont_run = FALSE) { block_tag_to_comment("\\donttest", x, run_dont_run = run_dont_run) } #' @export as_example.tag_dontshow <- function(x, run_dont_run = FALSE) { ex <- flatten_ex(x, run_dont_run = run_dont_run) paste0("DONTSHOW({", ex, "})") } #' @export as_example.tag_testonly <- function(x, run_dont_run = FALSE) { ex <- flatten_ex(x, run_dont_run = run_dont_run) paste0("TESTONLY({", ex, "})") } block_tag_to_comment <- function(tag, x, run_dont_run = FALSE) { ex <- flatten_ex(x, run_dont_run = run_dont_run) # Not easy to strip leading whitespace because it's attached to the previous # tag. So instead we add a comment to occupy that space if (is_newline(x[[1]], trim = TRUE)) { ex <- paste0("# ", tag, "{", ex, "# }") } ex } #' @export as_example.tag <- function(x, run_dont_run = FALSE) { untag <- paste(class(x), collapse = "/") cli::cli_warn("Unknown tag: {.val {untag}}") } #' @export as_example.tag_dots <- function(x, run_dont_run = FALSE) { "..." } #' @export as_example.tag_ldots <- as_example.tag_dots #' @export as_example.tag_if <- function(x, run_dont_run = FALSE) { if (x[[1]] == "html") { flatten_ex(x[[2]], run_dont_run = run_dont_run) } else { "" } } #' @export as_example.tag_ifelse <- function(x, run_dont_run = FALSE) { if (x[[1]] == "html") { flatten_ex(x[[2]], run_dont_run = run_dont_run) } else { flatten_ex(x[[3]], run_dont_run = run_dont_run) } } #' @export as_example.tag_out <- function(x, run_dont_run = FALSE) { flatten_ex(x, run_dont_run = run_dont_run) } # Helpers ----------------------------------------------------------------- flatten_ex <- function(x, run_dont_run = FALSE) { out <- purrr::map_chr(x, as_example, run_dont_run = run_dont_run) paste(out, collapse = "") } can_parse <- function(x) { tryCatch( { parse(text = x) TRUE }, error = function(e) FALSE ) } pkgdown/R/external-deps.R0000644000176200001440000000677514770274305015052 0ustar liggesusersexternal_dependencies <- function(pkg, call = caller_env()) { purrr::compact(list( fontawesome::fa_html_dependency(), cached_dependency( name = "headroom", version = "0.11.0", files = list( list( url = "https://cdnjs.cloudflare.com/ajax/libs/headroom/0.11.0/headroom.min.js", integrity = "sha256-AsUX4SJE1+yuDu5+mAVzJbuYNPHj/WroHuZ8Ir/CkE0=" ), list( url = "https://cdnjs.cloudflare.com/ajax/libs/headroom/0.11.0/jQuery.headroom.min.js", integrity = "sha256-ZX/yNShbjqsohH1k95liqY9Gd8uOiE1S4vZc+9KQ1K4=" ) ) ), cached_dependency( name = "bootstrap-toc", version = "1.0.1", files = list( list( url = "https://cdn.jsdelivr.net/gh/afeld/bootstrap-toc@v1.0.1/dist/bootstrap-toc.min.js", integrity = "sha256-4veVQbu7//Lk5TSmc7YV48MxtMy98e26cf5MrgZYnwo=" ) ) ), cached_dependency( name = "clipboard.js", version = "2.0.11", files = list( list( url = "https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.11/clipboard.min.js", integrity = "sha512-7O5pXpc0oCRrxk8RUfDYFgn0nO1t+jLuIOQdOMRp4APB7uZ4vSjspzp5y6YDtDs4VzUSTbWzBFZ/LKJhnyFOKw==" ) ) ), cached_dependency( name = "search", version = "1.0.0", files = list( list( url = "https://cdnjs.cloudflare.com/ajax/libs/fuse.js/6.4.6/fuse.min.js", integrity = "sha512-KnvCNMwWBGCfxdOtUpEtYgoM59HHgjHnsVGSxxgz7QH1DYeURk+am9p3J+gsOevfE29DV0V+/Dd52ykTKxN5fA==" ), list( url = "https://cdnjs.cloudflare.com/ajax/libs/autocomplete.js/0.38.0/autocomplete.jquery.min.js", integrity = "sha512-GU9ayf+66Xx2TmpxqJpliWbT5PiGYxpaG8rfnBEk1LL8l1KGkRShhngwdXK1UgqhAzWpZHSiYPc09/NwDQIGyg==" ), list( url = "https://cdnjs.cloudflare.com/ajax/libs/mark.js/8.11.1/mark.min.js", integrity = "sha512-5CYOlHXGh6QpOFA/TeTylKLWfB3ftPsde7AnmhuitiTX4K5SqCLBeKro6sPS8ilsz1Q4NRx3v8Ko2IBiszzdww==" ) ) ) )) } cached_dependency <- function(name, version, files) { cache_dir <- path(tools::R_user_dir("pkgdown", "cache"), name, version) dir_create(cache_dir) for (file in files) { cache_path <- path(cache_dir, path_file(file$url)) if (!file_exists(cache_path)) { utils::download.file(file$url, cache_path, quiet = TRUE, mode = "wb") check_integrity(cache_path, file$integrity) } } dep_files <- path_rel(dir_ls(cache_dir), cache_dir) htmltools::htmlDependency( name = name, version = version, src = cache_dir, script = dep_files[path_ext(dep_files) == "js"], stylesheet = dep_files[path_ext(dep_files) == "css"] ) } check_integrity <- function(path, integrity) { parsed <- parse_integrity(integrity) if (!parsed$size %in% c(256L, 384L, 512L)) { cli::cli_abort( "{.field integrity} must use SHA-256, SHA-384, or SHA-512", .internal = TRUE ) } hash <- compute_hash(path, parsed$size) if (hash != parsed$hash) { cli::cli_abort( "Downloaded asset does not match known integrity", .internal = TRUE ) } invisible() } compute_hash <- function(path, size) { con <- file(path, encoding = "UTF-8") openssl::base64_encode(openssl::sha2(con, size)) } parse_integrity <- function(x) { size <- as.integer(regmatches(x, regexpr("(?<=^sha)\\d{3}", x, perl = TRUE))) hash <- regmatches(x, regexpr("(?<=^sha\\d{3}-).+", x, perl = TRUE)) list(size = size, hash = hash) } pkgdown/R/build-llm.R0000644000176200001440000001302515100735002014122 0ustar liggesusers#' Build docs for LLMs #' #' @description #' `build_llm_docs()` creates an `LLMs.txt` at the root of your site #' that contains the contents of your `README.md`, your reference index, #' and your articles index. It also creates a `.md` file for every existing #' `.html` file in your site. Together, this gives an LLM an overview of your #' package and the ability to find out more by following links. #' #' If you don't want these files generated for your site, you can opt-out by #' adding the following to your `pkgdown.yml`: #' #' ```yaml #' llm-docs: false #' ``` #' #' @family site components #' @inheritParams build_site #' @export build_llm_docs <- function(pkg = ".") { pkg <- as_pkgdown(pkg) if (isFALSE(pkg$meta$`llm-docs`)) { return(invisible()) } cli::cli_rule("Building docs for llms") paths <- get_site_paths(pkg) purrr::walk(paths, \(path) { src_path <- path(pkg[["dst_path"]], path) dst_path <- path_ext_set(src_path, "md") convert_md(src_path, dst_path, full_url(pkg, path)) }) index <- c( read_lines(path(pkg$dst_path, "index.md")), "", read_file_if_exists(path(pkg$dst_path, "reference", "index.md")), "", read_file_if_exists(path(pkg$dst_path, "articles", "index.md")) ) write_lines(index, path(pkg$dst_path, "llms.txt")) invisible() } full_url <- function(pkg, path) { if (is.null(pkg$meta$url)) { return() } url <- paste0(pkg$meta$url, "/") if (pkg$development$in_dev) { url <- paste0(url, pkg$prefix) } xml2::url_absolute(paste0(path_dir(path), "/"), url) } convert_md <- function(src_path, dst_path, url = NULL) { html <- xml2::read_html(src_path) main_html <- xml2::xml_find_first(html, ".//main") if (length(main_html) == 0) { return() } simplify_page_header(main_html) simplify_anchors(main_html) simplify_code(main_html) simplify_popovers_to_footnotes(main_html) simplify_lifecycle_badges(main_html) simplify_dls(main_html) create_absolute_links(main_html, url) path <- file_temp() xml2::write_html(main_html, path, format = FALSE) on.exit(file_delete(path), add = TRUE) rmarkdown::pandoc_convert( input = path, output = dst_path, from = "html", to = "gfm+definition_lists-raw_html", ) } # Helpers --------------------------------------------------------------------- # simplify page header (which includes logo + source link) simplify_page_header <- function(html) { title <- xml2::xml_find_first(html, ".//h1") # website for a package without README/index.md if (length(title) > 0) { xml2::xml_remove(xml2::xml_find_first(html, ".//div[@class='page-header']")) xml2::xml_add_child(html, title, .where = 0) } invisible() } # drop internal anchors simplify_anchors <- function(html) { xml2::xml_remove(xml2::xml_find_all(html, ".//a[@class='anchor']")) invisible() } # strip extraneoous classes simplify_code <- function(html) { extract_lang <- function(class) { trimws(gsub("sourceCode|downlit", "", class)) } code <- xml2::xml_find_all(html, ".//pre[contains(@class, 'sourceCode')]") purrr::walk(code, \(x) { xml2::xml_attr(x, "class") <- extract_lang(xml2::xml_attr(x, "class")) }) invisible() } simplify_popovers_to_footnotes <- function(main_html) { popover_refs <- xml2::xml_find_all(main_html, ".//a[@class='footnote-ref']") if (length(popover_refs) == 0) { return() } # Create footnotes section footnotes_section <- xml2::xml_find_first( main_html, ".//section[@class='footnotes']" ) if (length(footnotes_section) == 0) { footnotes_section <- xml2::xml_add_child( main_html, "section", id = "footnotes", class = "footnotes footnotes-end-of-document", role = "doc-endnotes" ) xml2::xml_add_child(footnotes_section, "hr") footnotes_ol <- xml2::xml_add_child(footnotes_section, "ol") } else { footnotes_ol <- xml2::xml_find_first(footnotes_section, ".//ol") } purrr::iwalk(popover_refs, function(ref, i) { text_content <- xml2::xml_attr(ref, "data-bs-content") fn_id <- paste0("fn", i) fnref_id <- paste0("fnref", i) xml2::xml_attrs(ref) <- list( href = paste0("#", fn_id), id = fnref_id, role = "doc-noteref", class = "footnote-ref" ) fn_li <- xml2::xml_add_child(footnotes_ol, "li", id = fn_id) parsed_content <- xml2::read_html(text_content) |> xml2::xml_find_first(".//body") |> xml2::xml_children() purrr::walk(parsed_content, \(x) xml2::xml_add_child(fn_li, x)) }) } simplify_lifecycle_badges <- function(html) { # on reference index badges <- xml2::xml_find_all(html, "//span[contains(@class, 'lifecycle')]") xml2::xml_replace(badges, "strong", paste0("[", xml2::xml_text(badges), "]")) # on individual pages badges <- xml2::xml_find_all( html, "//a[.//img[starts-with(@src, 'figures/lifecycle-')]]" ) imgs <- xml2::xml_find_first(badges, ".//img") xml2::xml_replace(badges, "strong", tolower(xml2::xml_attr(imgs, "alt"))) invisible() } create_absolute_links <- function(main_html, url = NULL) { a <- xml2::xml_find_all(main_html, ".//a") xml2::xml_attr(a, "class") <- NULL href <- xml2::xml_attr(a, "href") is_internal <- !is.na(href) & !startsWith(href, "https") & !startsWith(href, "#") if (!is.null(url)) { href[is_internal] <- xml2::url_absolute(href[is_internal], url) } href[is_internal] <- sub("html$", "md", href[is_internal]) xml2::xml_attr(a[is_internal], "href") <- href[is_internal] invisible() } read_file_if_exists <- function(path) { if (file_exists(path)) { read_lines(path) } } pkgdown/R/tweak-page.R0000644000176200001440000000674615075440722014317 0ustar liggesusers# File level tweaks -------------------------------------------- tweak_page <- function(html, name, pkg = list(bs_version = 3)) { # Syntax highlighting and linking if (name == "reference-topic") { # Reference topic takes a minimal approach since some is # already handled by Rd processing tweak_reference_highlighting(html) tweak_extra_logo(html) } else { downlit::downlit_html_node(html) # Rescue highlighting of non-collapsed output - needed for ANSI escapes pre <- xml2::xml_find_all(html, ".//pre[not(contains(@class, 'downlit'))]") is_wrapped <- is_wrapped_pre(pre) purrr::walk(pre[!is_wrapped], tweak_highlight_r) } tweak_anchors(html) tweak_link_md(html) tweak_link_seealso(html) tweak_link_external(html, pkg = pkg) tweak_img_src(html) tweak_strip(html, !identical(pkg$development$mode, "release")) # BS3 uses table for layout of reference-index if (name != "reference-index") { tweak_tables(html) } if (pkg$bs_version > 3) { tweak_footnotes(html) tweak_tabsets(html) tweak_useless_toc(html) } if (!is.null(pkg$desc) && pkg$desc$has_dep("R6")) { tweak_link_R6(html, pkg$package) } } tweak_rmarkdown_html <- function(html, input_path, pkg = list(bs_version = 3)) { # Tweak classes of navbar toc <- xml2::xml_find_all(html, ".//div[@id='tocnav']//ul") xml2::xml_attr(toc, "class") <- "nav nav-pills nav-stacked" # Make sure all images use relative paths img <- xml2::xml_find_all(html, "//img") src <- xml2::xml_attr(img, "src") abs_src <- is_absolute_path(src) if (any(abs_src)) { img_target_nodes <- img[abs_src] img_src_real <- path_real(xml2::url_unescape(src[abs_src])) input_path_real <- path_real(xml2::url_unescape(input_path)) img_rel_paths <- path_rel(path = img_src_real, start = input_path_real) img_rel_paths <- xml2::url_escape(img_rel_paths, reserved = "/") purrr::walk2( .x = img_target_nodes, .y = img_rel_paths, .f = xml2::xml_set_attr, attr = "src" ) } # If top-level headings use h1, move everything down one level h1 <- xml2::xml_find_all(html, "//h1") if (length(h1) > 1) { tweak_section_levels(html) } # Has to occur after path normalisation # This get called twice on the contents of content-article.html, but that # should be harmless tweak_page(html, "article", pkg = pkg) invisible() } # Strip off #toc if it's not needed; easier to do this here than in js tweak_useless_toc <- function(html) { contents <- xml2::xml_find_all(html, ".//main") headings <- xml2::xml_find_all(contents, ".//h2|.//h3|.//h4|.//h5|.//h6") if (length(headings) > 1) { return() } toc <- xml2::xml_find_first(html, '//nav[@id="toc"]') sidebar <- xml2::xml_parent(toc) if (length(xml2::xml_children(sidebar)) == 1) { xml2::xml_remove(sidebar) } else { xml2::xml_remove(toc) } } # Update file on disk ----------------------------------------------------- read_html_keep_ansi <- function(path) { raw <- read_file(path) # Following the xml 1.0 spec, libxml2 drops low-bit ASCII characters # so we convert to \u2029, relying on downlit to convert back in # token_escape(). raw <- gsub("\033", "\u2029", raw, fixed = TRUE) # Use charToRaw() to always interpret as string, # even for length 1 vectors xml2::read_html(charToRaw(raw), encoding = "UTF-8") } update_html <- function(path, tweak, ...) { html <- read_html_keep_ansi(path) tweak(html, ...) xml2::write_html(html, path, format = FALSE) path } pkgdown/R/development.R0000644000176200001440000000365514770274305014613 0ustar liggesusersmeta_development <- function(pkg, call = caller_env()) { config_pluck_list(pkg, "development", call = call) mode <- dev_mode(pkg, call = call) destination <- config_pluck_string( pkg, "development.destination", default = "dev", call = call ) version_label <- config_pluck_string( pkg, "development.version_label", call = call ) if (is.null(version_label)) { if (mode %in% c("release", "default")) { version_label <- if (pkg$bs_version == 3) "default" else "muted" } else { version_label <- "danger" } } in_dev <- mode == "devel" list( destination = destination, mode = mode, version_label = version_label, in_dev = in_dev, prefix = if (in_dev) paste0(destination, "/") else "" ) } dev_mode <- function(pkg, call = caller_env()) { mode <- Sys.getenv("PKGDOWN_DEV_MODE") if (identical(mode, "")) { mode <- config_pluck_string( pkg, "development.mode", default = "default", call = call ) } if (mode == "auto") { mode <- dev_mode_auto(pkg$version) } else { valid_mode <- c("auto", "default", "release", "devel", "unreleased") if (!mode %in% valid_mode) { msg <- "{.field development.mode} must be one of {.or {valid_mode}}, not {mode}." config_abort(pkg, msg, call = call) } } mode } dev_mode_auto <- function(version) { version <- unclass(package_version(version))[[1]] if (length(version) < 3) { "release" } else if (length(version) == 3) { if (version[3] >= 9000) { "devel" } else { "release" } } else if (identical(version[1:3], c(0L, 0L, 0L))) { "unreleased" } else { "devel" } } # Called in render_page() so that LANG env var set up version_tooltip <- function(mode) { switch( mode, default = "", release = tr_("Released version"), devel = tr_("In-development version"), unreleased = tr_("Unreleased version") ) } pkgdown/R/build-reference-index.R0000644000176200001440000001141314770274305016420 0ustar liggesusersdata_reference_index <- function(pkg = ".", error_call = caller_env()) { pkg <- as_pkgdown(pkg) meta <- config_pluck_reference(pkg, error_call) if (length(meta) == 0) { return(list()) } rows <- unwrap_purrr_error(purrr::imap( meta, data_reference_index_rows, pkg = pkg, call = error_call )) rows <- purrr::list_c(rows) has_icons <- purrr::some(rows, ~ .x$row_has_icons %||% FALSE) check_missing_topics(rows, pkg, error_call = error_call) rows <- Filter(function(x) !x$is_internal, rows) print_yaml(list( pagetitle = tr_("Package index"), rows = rows, has_icons = has_icons )) } config_pluck_reference <- function(pkg, call = caller_env()) { ref <- config_pluck_list( pkg, "reference", default = default_reference_index(pkg) ) for (i in seq_along(ref)) { section <- ref[[i]] config_check_list( section, error_path = paste0("reference[", i, "]"), error_pkg = pkg, error_call = call ) config_check_string( section$title, error_path = paste0("reference[", i, "].title"), error_pkg = pkg, error_call = call ) config_check_string( section$subtitle, error_path = paste0("reference[", i, "].subtitle"), error_pkg = pkg, error_call = call ) if (has_name(section, "contents")) { check_contents( section$contents, i, pkg, prefix = "reference", call = call ) } } ref } check_contents <- function(contents, index, pkg, prefix, call = caller_env()) { if (length(contents) == 0) { config_abort( pkg, "{.field {prefix}[{index}].contents} is empty.", call = call ) } is_null <- purrr::map_lgl(contents, is.null) if (any(is_null)) { j <- which(is_null)[1] config_abort( pkg, "{.field {prefix}[{index}].contents[{j}]} is empty.", call = call ) } is_char <- purrr::map_lgl(contents, is.character) if (!all(is_char)) { j <- which(!is_char)[1] config_abort( pkg, c( "{.field {prefix}[{index}].contents[{j}]} must be a string.", i = "You might need to add '' around special YAML values like 'N' or 'off'" ), call = call ) } } data_reference_index_rows <- function( section, index, pkg, call = caller_env() ) { is_internal <- identical(section$title, "internal") rows <- list() if (has_name(section, "title")) { rows[[1]] <- list( title = markdown_text_inline( pkg, section$title, error_path = paste0("reference[", index, "].title"), error_call = call ), slug = make_slug(section$title), desc = markdown_text_block(pkg, section$desc), is_internal = is_internal ) } if (has_name(section, "subtitle")) { rows[[2]] <- list( subtitle = markdown_text_inline( pkg, section$subtitle, error_path = paste0("reference[", index, "].subtitle"), error_call = call ), slug = make_slug(section$subtitle), desc = markdown_text_block(pkg, section$desc), is_internal = is_internal ) } if (has_name(section, "contents")) { topics <- section_topics( pkg, section$contents, error_path = paste0("reference[", index, "].contents"), error_call = call ) names <- topics$name topics$name <- NULL rows[[3]] <- list( topics = purrr::transpose(topics), names = names, row_has_icons = !purrr::every(topics$icon, is.null), is_internal = is_internal ) } purrr::compact(rows) } find_icons <- function(x, path) { purrr::map(x, find_icon, path = path) } find_icon <- function(aliases, path) { names <- paste0(aliases, ".png") exists <- file_exists(path(path, names)) if (!any(exists)) { NULL } else { names[which(exists)[1]] } } default_reference_index <- function(pkg = ".") { pkg <- as_pkgdown(pkg) exported <- pkg$topics[!pkg$topics$internal, , drop = FALSE] if (nrow(exported) == 0) { return(list()) } print_yaml(list( list( title = tr_("All functions"), contents = auto_quote(unname(exported$name)) ) )) } check_missing_topics <- function(rows, pkg, error_call = caller_env()) { # Cross-reference complete list of topics vs. topics found in index page all_topics <- purrr::list_c(purrr::map(rows, "names")) in_index <- pkg$topics$name %in% all_topics missing <- !in_index & !pkg$topics$internal if (any(missing)) { config_abort( pkg, c( "{sum(missing)} topic{?s} missing from index: {.val {pkg$topics$name[missing]}}.", i = paste( "Either add to the reference index,", "or use {.code @keywords internal} to drop from the index." ) ), call = error_call ) } } pkgdown/R/build-home-community.R0000644000176200001440000000166214770274305016334 0ustar liggesusershas_contributing <- function(path = ".") { file_exists(path(path, 'CONTRIBUTING.md')) || file_exists(path(path, '.github', 'CONTRIBUTING.md')) } has_coc <- function(path = ".") { file_exists(path(path, 'CODE_OF_CONDUCT.md')) || file_exists(path(path, '.github', 'CODE_OF_CONDUCT.md')) } has_support <- function(path = ".") { file_exists(path(path, 'SUPPORT.md')) || file_exists(path(path, '.github', 'SUPPORT.md')) } data_home_sidebar_community <- function(pkg) { pkg <- as_pkgdown(pkg) links <- NULL if (has_contributing(pkg$src_path)) { links <- c(links, a(tr_("Contributing guide"), "CONTRIBUTING.html")) } if (has_coc(pkg$src_path)) { links <- c(links, a(tr_("Code of conduct"), "CODE_OF_CONDUCT.html")) } if (has_support(pkg$src_path)) { links <- c(links, a(tr_("Getting help"), "SUPPORT.html")) } if (is.null(links)) { return("") } sidebar_section(tr_("Community"), links) } pkgdown/R/usage.R0000644000176200001440000001554014770274305013371 0ustar liggesusers# Reference page --------------------------------------------------------------- # For testing usage2text <- function(x) { rd <- rd_text(paste0("\\usage{", x, "}"), FALSE)[[1]] strip_html_tags(as_data(rd)) } #' @export as_data.tag_usage <- function(x, ...) { text <- paste(flatten_text(x, ..., escape = FALSE), collapse = "\n") text <- str_trim(text) # Look for single line calls to non-syntactic functions (except for `=` # since that's probably a single argument on its own line) and then use # deparse1 to convert to standard style. We want to avoid reparsing # any other lines to avoid losing whitespace, comments etc. (These # are not generated by roxygen but can be added by the user.) lines <- strsplit(text, "\n", fixed = TRUE)[[1]] parsed <- lapply( lines, function(x) tryCatch(parse(text = x)[[1]], error = function(e) NULL) ) needs_tweak <- function(x) { is_call(x) && !is_call(x, "=") && (is_symbol(x[[1]]) && !is_syntactic(x[[1]])) } to_tweak <- vapply(parsed, needs_tweak, logical(1)) lines[to_tweak] <- vapply(parsed[to_tweak], deparse1, character(1)) text <- paste(lines, collapse = "\n") highlight_text(text) } #' @export as_html.tag_method <- function(x, ...) method_usage(x, "S3") #' @export as_html.tag_S3method <- function(x, ...) method_usage(x, "S3") #' @export as_html.tag_S4method <- function(x, ...) method_usage(x, "S4") method_usage <- function(x, type) { # Despite these being called from the as_html() generic, the target isn't # actually HTML, but R code, which is turned into HTML by the syntax # highlighting in as as_data.tag_usage() fun <- as_html(x[[1]], escape = FALSE) class <- as_html(x[[2]], escape = FALSE) if (x[[2]] == "default") { method <- sprintf(tr_("# Default %s method"), type) } else { method <- sprintf(tr_("# %s method for class '%s'"), type, class) } if (!is_syntactic(fun)) { fun <- paste0("`", fun, "`") } paste0(method, "\n", fun) } # Reference index -------------------------------------------------------------- topic_funs <- function(rd) { funs <- parse_usage(rd) # Remove all methods for generics documented in this file name <- purrr::map_chr(funs, "name") type <- purrr::map_chr(funs, "type") gens <- name[type == "fun"] self_meth <- (name %in% gens) & (type %in% c("s3", "s4")) funs <- purrr::map_chr( funs[!self_meth], ~ short_name(.$name, .$type, .$signature) ) unique(funs) } parse_usage <- function(x) { if (!inherits(x, "tag")) { usage <- paste0("\\usage{", x, "}") x <- rd_text(usage, fragment = FALSE) } r <- usage_code(x) if (length(r) == 0) { return(list()) } exprs <- tryCatch( parse_exprs(r), error = function(e) { cli::cli_warn("Failed to parse usage: {.code {r}}") list() } ) purrr::map(exprs, usage_type) } short_name <- function(name, type, signature) { name <- escape_html(name) qname <- auto_quote(name) if (type == "data") { qname } else if (type == "fun") { if (is_infix(name)) { qname } else { paste0(qname, "()") } } else { sig <- paste0("<", escape_html(signature), ">", collapse = ",") paste0(qname, "(", sig, ")") } } # Given single expression generated from usage_code, extract usage_type <- function(x) { if (is_symbol(x)) { list(type = "data", name = as.character(x)) } else if (is_call(x, "data")) { list(type = "data", name = as.character(x[[2]])) } else if (is.call(x)) { if (identical(x[[1]], quote(`<-`))) { replacement <- TRUE x <- x[[2]] } else { replacement <- FALSE } out <- fun_info(x) out$replacement <- replacement out$infix <- is_infix(out$name) if (replacement) { out$name <- paste0(out$name, "<-") } out } else { untype <- paste0(typeof(x), " (in ", as.character(x), ")") cli::cli_abort( "Unknown type: {.val {untype}}", call = caller_env() ) } } is_infix <- function(x) { if (is.null(x)) { return(FALSE) } x <- as.character(x) ops <- c( "+", "-", "*", "^", "/", "==", ">", "<", "!=", "<=", ">=", "&", "|", "[[", "[", "$" ) grepl("^%.*%$", x) || x %in% ops } fun_info <- function(fun) { stopifnot(is.call(fun)) if (is.call(fun[[1]])) { x <- fun[[1]] if (identical(x[[1]], quote(S3method))) { list( type = "s3", name = as.character(x[[2]]), signature = as.character(x[[3]]) ) } else if (identical(x[[1]], quote(S4method))) { list( type = "s4", name = as.character(x[[2]]), signature = sub("^`(.*)`$", "\\1", as.character(as.list(x[[3]])[-1])) ) } else if (is_call(x, c("::", ":::"))) { # TRUE if fun has a namespace, pkg::fun() list( type = "fun", name = call_name(fun) ) } else { cli::cli_abort( "Unknown call: {.val {as.character(x[[1]])}}", call = caller_env() ) } } else { list( type = "fun", name = as.character(fun[[1]]), signature = NULL ) } } # usage_code -------------------------------------------------------------- # Transform Rd embedded inside usage into parseable R code usage_code <- function(x) { UseMethod("usage_code") } #' @export usage_code.Rd <- function(x) { usage <- purrr::detect(x, inherits, "tag_usage") usage_code(usage) } #' @export usage_code.NULL <- function(x) character() # Tag without additional class use #' @export usage_code.tag <- function(x) { if (!identical(class(x), "tag")) { cli::cli_abort( "Undefined tag in usage: {.val class(x)[[1]]}}", call = caller_env() ) } paste0(purrr::flatten_chr(purrr::map(x, usage_code)), collapse = "") } #' @export usage_code.tag_special <- function(x) { paste0(purrr::flatten_chr(purrr::map(x, usage_code)), collapse = "") } #' @export usage_code.tag_dots <- function(x) "..." #' @export usage_code.tag_ldots <- function(x) "..." #' @export usage_code.TEXT <- function(x) as.character(x) #' @export usage_code.RCODE <- function(x) as.character(x) #' @export usage_code.VERB <- function(x) as.character(x) #' @export usage_code.COMMENT <- function(x) character() #' @export usage_code.tag_S3method <- function(x) { generic <- paste0(usage_code(x[[1]]), collapse = "") class <- paste0(usage_code(x[[2]]), collapse = "") paste0("S3method(`", generic, "`, ", class, ")") } #' @export usage_code.tag_method <- usage_code.tag_S3method #' @export usage_code.tag_S4method <- function(x) { generic <- paste0(usage_code(x[[1]]), collapse = "") class <- strsplit(usage_code(x[[2]]), ",")[[1]] class <- paste0("`", class, "`") class <- paste0(class, collapse = ",") paste0("S4method(`", generic, "`, list(", class, "))") } #' @export usage_code.tag_usage <- function(x) { paste0(purrr::flatten_chr(purrr::map(x, usage_code)), collapse = "") } pkgdown/R/theme.R0000644000176200001440000001461514770274305013371 0ustar liggesusersbuild_bslib <- function(pkg = ".", call = caller_env()) { pkg <- as_pkgdown(pkg) bs_theme <- bs_theme(pkg, call = call) cur_deps <- find_deps(pkg) cur_digest <- purrr::map_chr(cur_deps, file_digest) deps <- c(bslib::bs_theme_dependencies(bs_theme), external_dependencies(pkg)) deps <- lapply( deps, htmltools::copyDependencyToDir, path(pkg$dst_path, "deps") ) deps <- lapply(deps, htmltools::makeDependencyRelative, pkg$dst_path) new_deps <- find_deps(pkg) new_digest <- purrr::map_chr(cur_deps, file_digest) all_deps <- union(new_deps, cur_deps) diff <- (cur_digest[all_deps] == new_digest[all_deps]) changed <- all_deps[!diff | is.na(diff)] if (length(changed) > 0) { withr::local_locale(LC_COLLATE = "C") purrr::walk(sort(changed), function(dst) { cli::cli_inform("Updating {dst_path(path_rel(dst, pkg$dst_path))}") }) } head <- htmltools::renderDependencies(deps, srcType = "file") write_lines(head, data_deps_path(pkg)) } data_deps <- function(pkg, depth) { if (!file_exists(data_deps_path(pkg))) { # this is unlikely to occur after #2439 and #2571 cli::cli_abort( "Run {.fn pkgdown::init_site} first.", .internal = TRUE, call = caller_env() ) } deps_path <- paste0(up_path(depth), "deps") data_deps <- read_lines(data_deps_path(pkg)) data_deps <- gsub('src="deps', sprintf('src="%s', deps_path), data_deps) data_deps <- gsub('href="deps', sprintf('href="%s', deps_path), data_deps) paste0(data_deps, collapse = "") } data_deps_path <- function(pkg) { path(pkg$dst_path, "deps", "data-deps.txt") } find_deps <- function(pkg) { deps_path <- path(pkg$dst_path, "deps") if (!dir_exists(deps_path)) { character() } else { dir_ls(deps_path, type = "file", recurse = TRUE) } } bs_theme <- function(pkg = ".", call = caller_env()) { pkg <- as_pkgdown(pkg) bs_theme_args <- pkg$meta$template$bslib %||% list() bs_theme_args[["version"]] <- pkg$bs_version # In bslib >= 0.5.1, bs_theme() takes bootstrap preset theme via `preset` bs_theme_args[["preset"]] <- get_bslib_theme(pkg) bs_theme_args[["bootswatch"]] <- NULL bs_theme <- exec(bslib::bs_theme, !!!bs_theme_args) # Drop bs3 compat files added for shiny/RMarkdown bs_theme <- bslib::bs_remove(bs_theme, "bs3compat") # Add additional pkgdown rules rules <- bs_theme_rules(pkg, call = call) files <- lapply(rules, sass::sass_file) bs_theme <- bslib::bs_add_rules(bs_theme, files) # Add dark theme if needed if (uses_lightswitch(pkg)) { dark_theme <- config_pluck_string( pkg, "template.theme-dark", default = "arrow-dark" ) check_theme( dark_theme, error_pkg = pkg, error_path = "template.theme-dark", error_call = call ) path <- highlight_path(dark_theme) css <- c('[data-bs-theme="dark"] {', read_lines(path), '}') bs_theme <- bslib::bs_add_rules(bs_theme, css) } bs_theme } bs_theme_rules <- function(pkg, call = caller_env()) { paths <- path_pkgdown("BS5", "assets", "pkgdown.scss") theme <- config_pluck_string(pkg, "template.theme", default = "arrow-light") check_theme( theme, error_pkg = pkg, error_path = "template.theme", error_call = call ) paths <- c(paths, highlight_path(theme)) package <- config_pluck_string(pkg, "template.package") if (!is.null(package)) { package_extra <- path_package_pkgdown("extra.scss", package, pkg$bs_version) if (file_exists(package_extra)) { paths <- c(paths, package_extra) } } # Also look in site supplied site_extra <- path(pkg$src_path, "pkgdown", "extra.scss") if (file_exists(site_extra)) { paths <- c(paths, site_extra) } paths } check_theme <- function( theme, error_pkg, error_path, error_call = caller_env() ) { if (theme %in% highlight_styles()) { return() } config_abort( error_pkg, "{.field {error_path}} uses theme {.val {theme}}", call = error_call ) } highlight_path <- function(theme) { path_pkgdown("highlight-styles", paste0(theme, ".scss")) } highlight_styles <- function() { paths <- dir_ls(path_pkgdown("highlight-styles"), glob = "*.scss") path_ext_remove(path_file(paths)) } get_bslib_theme <- function(pkg) { themes <- list( "template.bslib.preset" = pkg$meta[["template"]]$bslib$preset, "template.bslib.bootswatch" = pkg$meta[["template"]]$bslib$bootswatch, "template.bootswatch" = pkg$meta[["template"]]$bootswatch, # Historically (< 0.2.0), bootswatch wasn't a top-level template field "template.params.bootswatch" = pkg$meta[["template"]]$params$bootswatch ) is_present <- !purrr::map_lgl(themes, is.null) n_present <- sum(is_present) n_unique <- length(unique(themes[is_present])) if (n_present == 0) { return("default") } if (n_present > 1 && n_unique > 1) { cli::cli_warn(c( "Multiple Bootstrap preset themes were set. Using {.val {themes[is_present][[1]]}} from {.field {names(themes)[is_present][1]}}.", x = "Found {.and {.field {names(themes)[is_present]}}}.", i = "Remove extraneous theme declarations to avoid this warning." )) } field <- names(themes)[which(is_present)[1]] check_bslib_theme(themes[[field]], pkg, field) } check_bslib_theme <- function( theme, pkg, field = "template.bootswatch", bs_version = pkg$bs_version ) { bslib_themes <- c( bslib::bootswatch_themes(bs_version), bslib::builtin_themes(bs_version), # bs_theme() recognizes both below as bare bootstrap "default", "bootstrap" ) if (theme %in% bslib_themes) { return(theme) } config_abort( pkg, c( x = "{.field {field}} contains unknown Bootswatch/bslib theme {.val {theme}}.", i = "Using Bootstrap version {.val {bs_version}} ({.field template.bootstrap})." ), call = caller_env() ) } bs_theme_deps_suppress <- function(deps = list()) { # jquery and bootstrap are provided by bslib # headr-attrs is included for pandoc 2.7.3 - 2.9.2.1 to improve accessibility # but includes javascript that breaks our HTML anchor system bs_dep_names <- c("jquery", "bootstrap", "header-attrs") bs_deps <- purrr::map(bs_dep_names, function(name) { # minimal version of htmltools::htmlDependency() (see suppressDependencies()) structure( list( name = name, version = "9999", src = list(href = ""), all_files = TRUE ), class = "html_dependency" ) }) c(deps, bs_deps) } pkgdown/R/utils-pdf.R0000644000176200001440000000160614770274305014172 0ustar liggesusers# Set various env vars (copied from tools::texi2dvi) to ensure that # latex can find bib and style files in the right places local_texi2dvi_envvars <- function(input_path, env = caller_env()) { withr::local_envvar( BSTINPUTS = bst_paths(input_path), TEXINPUTS = tex_paths(input_path), BIBINPUTS = bib_paths(input_path), .local_envir = env ) } bst_paths <- function(path) { paths <- c( Sys.getenv("BSTINPUTS"), path_dir(path), path(R.home("share"), "texmf", "bibtex", "bst") ) paste(paths, collapse = .Platform$path.sep) } tex_paths <- function(path) { paths <- c( Sys.getenv("TEXINPUTS"), path_dir(path), path(R.home("share"), "texmf", "tex", "latex") ) paste(paths, collapse = .Platform$path.sep) } bib_paths <- function(path) { paths <- c( Sys.getenv("BIBINPUTS"), tex_paths(path) ) paste(paths, collapse = .Platform$path.sep) } pkgdown/R/build-reference.R0000644000176200001440000003116515074163153015315 0ustar liggesusers#' Build reference section #' #' By default, pkgdown will generate an index that lists all functions in #' alphabetical order. To override this, provide a `reference` section in your #' `_pkgdown.yml` as described below. #' #' # Reference index #' To tweak the index page, add a section called `reference` to `_pkgdown.yml`. #' It can contain three different types of element: #' #' * A **title** (`title` + `desc`), which generates an row containing an `

    ` #' with optional paragraph description. #' * A **subtitle** (`subtitle` + `desc`), which generates an row containing an #' `

    ` with optional paragraph description. #' * A **list of topics** (`contents`), which generates one row for each topic, #' with a list of aliases for the topic on the left, and the topic title #' on the right. #' #' (For historical reasons you can include `contents` with a title or #' subtitle, but this is no longer recommended). #' #' Most packages will only need to use `title` and `contents` components. #' For example, here's a snippet from the YAML that pkgdown uses to generate #' its own reference index: #' #' ```yaml #' reference: #' - title: Build #' desc: Build a complete site or its individual section components. #' - contents: #' - starts_with("build_") #' - title: Templates #' - contents: #' - template_navbar #' - render_page #' ``` #' #' Bigger packages, e.g. ggplot2, may need an additional layer of #' structure in order to clearly organise large number of functions: #' #' ```yaml #' reference: #' - title: Layers #' - subtitle: Geoms #' desc: Geom is short for geometric element #' - contents: #' - starts_with("geom") #' - subtitle: Stats #' desc: Statistical transformations transform data before display. #' contents: #' - starts_with("stat") #' ``` #' #' `desc` can use markdown, and if you have a long description it's a good #' idea to take advantage of the YAML `>` notation: #' #' ```yaml #' desc: > #' This is a very _long_ and **overly** flowery description of a #' single simple function. By using `>`, it's easy to write a description #' that runs over multiple lines. #' ``` #' #' ## Topic matching #' `contents` can contain: #' #' * Individual function/topic names. #' * Weirdly named functions with doubled quoting, once for YAML and once for #' R, e.g. `` "`+.gg`" ``. #' * `starts_with("prefix")` to select all functions with common prefix. #' * `ends_with("suffix")` to select all functions with common suffix. #' * `matches("regexp")` for more complex regular expressions. #' * `has_keyword("x")` to select all topics with keyword "x"; #' `has_keyword("datasets")` selects all data documentation. #' * `has_concept("blah")` to select all topics with concept "blah". #' If you are using roxygen2, `has_concept()` also matches family tags, because #' roxygen2 converts them to concept tags. #' * `lacks_concepts(c("concept1", "concept2"))` to select all topics #' without those concepts. This is useful to capture topics not otherwise #' captured by `has_concepts()`. #' * Topics from other installed packages, e.g. `rlang::is_installed()` (function name) #' or `sass::font_face` (topic name). #' * `has_lifecycle("deprecated")` will select all topics with lifecycle #' deprecated. #' #' All functions (except for `has_keyword()`) automatically exclude internal #' topics (i.e. those with `\keyword{internal}`). You can choose to include #' with (e.g.) `starts_with("build_", internal = TRUE)`. #' #' Use a leading `-` to remove topics from a section, e.g. `-topic_name`, #' `-starts_with("foo")`. #' #' pkgdown will check that all non-internal topics are included on #' the reference index page, and error if you have missed any. #' #' ## Missing topics #' #' pkgdown will warn if there are (non-internal) topics that not listed #' in the reference index. You can suppress these warnings by listing the #' topics in section with "title: internal" (case sensitive) which will not be #' displayed on the reference index. #' #' ## Icons #' You can optionally supply an icon for each help topic. To do so, you'll need #' a top-level `icons` directory. This should contain `.png` files that are #' either 30x30 (for regular display) or 60x60 (if you want retina display). #' Icons are matched to topics by aliases. #' #' # Examples #' #' If you need to run extra code before or after all examples are run, you #' can create `pkgdown/pre-reference.R` and `pkgdown/post-reference.R`. #' #' # Figures #' #' You can control the default rendering of figures by specifying the `figures` #' field in `_pkgdown.yml`. The default settings are equivalent to: #' #' ```yaml #' figures: #' dev: ragg::agg_png #' dpi: 96 #' dev.args: [] #' fig.ext: png #' fig.width: 7.2916667 #' fig.height: ~ #' fig.retina: 2 #' fig.asp: 1.618 #' bg: NA #' other.parameters: [] #' ``` #' #' Most of these parameters are interpreted similarly to knitr chunk #' options. `other.parameters` is a list of parameters #' that will be available to custom graphics output devices such #' as HTML widgets. #' #' @inheritParams build_articles #' @family site components #' @param lazy If `TRUE`, only rebuild pages where the `.Rd` #' is more recent than the `.html`. This makes it much easier to #' rapidly prototype. It is set to `FALSE` by [build_site()]. #' @param run_dont_run Run examples that are surrounded in \\dontrun? #' @param examples Run examples? #' @param devel Determines how code is loaded in order to run examples. #' If `TRUE` (the default), assumes you are in a live development #' environment, and loads source package with [pkgload::load_all()]. #' If `FALSE`, uses the installed version of the package. #' @param topics Build only specified topics. If supplied, sets `lazy` #' and `preview` to `FALSE`. #' @export build_reference <- function( pkg = ".", lazy = TRUE, examples = TRUE, run_dont_run = FALSE, seed = 1014L, override = list(), preview = FALSE, devel = TRUE, topics = NULL ) { pkg <- section_init(pkg, "reference", override = override) check_bool(lazy) check_bool(examples) check_bool(run_dont_run) check_number_whole(seed, allow_null = TRUE) check_bool(devel) check_character(topics, allow_null = TRUE) cli::cli_rule("Building function reference") build_reference_index(pkg) copy_figures(pkg) if (examples) { examples_env <- examples_env(pkg, seed = seed, devel = devel) } else { examples_env <- NULL } if (!is.null(topics)) { topics <- purrr::transpose(pkg$topics[pkg$topics$name %in% topics, ]) lazy <- FALSE preview <- FALSE } else { topics <- purrr::transpose(pkg$topics) } unwrap_purrr_error(purrr::map( topics, build_reference_topic, pkg = pkg, lazy = lazy, examples_env = examples_env, run_dont_run = run_dont_run )) preview_site(pkg, "reference", preview = preview) } copy_figures <- function(pkg) { # copy everything from man/figures to docs/reference/figures dir_copy_to( src_dir = path(pkg$src_path, "man", "figures"), src_root = pkg$src_path, dst_dir = path(pkg$dst_path, "reference", "figures"), dst_root = pkg$dst_path ) } examples_env <- function( pkg, seed = 1014L, devel = TRUE, envir = parent.frame() ) { # Re-loading pkgdown while it's running causes weird behaviour with # the context cache if (isTRUE(devel) && !(pkg$package %in% c("pkgdown", "rprojroot"))) { check_installed("pkgload", "to use `build_reference(devel = TRUE)`") pkgload::load_all( pkg$src_path, export_all = FALSE, helpers = FALSE, quiet = TRUE ) } else { library(pkg$package, character.only = TRUE) } # Need to compute before changing working directory pre_path <- path_abs(path(pkg$src_path, "pkgdown", "pre-reference.R")) post_path <- path_abs(path(pkg$src_path, "pkgdown", "post-reference.R")) withr::local_dir(path(pkg$dst_path, "reference"), .local_envir = envir) width <- config_pluck_number_whole(pkg, "code.width", default = 80) withr::local_options(width = width, .local_envir = envir) withr::local_seed(seed, .local_envir = envir) if (requireNamespace("htmlwidgets", quietly = TRUE)) { htmlwidgets::setWidgetIdSeed(seed) } examples_env <- child_env(globalenv()) if (file_exists(pre_path)) { sys.source(pre_path, envir = examples_env) } if (file_exists(post_path)) { withr::defer(sys.source(post_path, envir = examples_env), envir = envir) } examples_env } #' @export #' @rdname build_reference build_reference_index <- function(pkg = ".", override = list()) { pkg <- section_init(pkg, "reference", override = override) # Copy icons, if needed dir_copy_to( src_dir = path(pkg$src_path, "icons"), src_root = pkg$src_path, dst_dir = path(pkg$dst_path, "reference", "icons"), dst_root = pkg$dst_path ) render_page( pkg, "reference-index", data = data_reference_index(pkg), path = "reference/index.html" ) invisible() } build_reference_topic <- function( topic, pkg, lazy = TRUE, examples_env = globalenv(), run_dont_run = FALSE ) { in_path <- path(pkg$src_path, "man", topic$file_in) out_path <- path(pkg$dst_path, "reference", topic$file_out) if (lazy && !out_of_date(in_path, out_path)) { return(invisible()) } cli::cli_inform("Reading {src_path(path('man', topic$file_in))}") data <- withCallingHandlers( data_reference_topic( topic, pkg, examples_env = examples_env, run_dont_run = run_dont_run ), error = function(err) { cli::cli_abort( "Failed to parse Rd in {.file {topic$file_in}}", parent = err, call = quote(build_reference()) ) } ) deps <- data$dependencies data$has_deps <- !is.null(deps) if (data$has_deps) { deps <- bs_theme_deps_suppress(deps) deps <- htmltools::resolveDependencies(deps) deps <- purrr::map( deps, htmltools::copyDependencyToDir, outputDir = path(pkg$dst_path, "reference", "libs"), mustWork = FALSE ) deps <- purrr::map( deps, htmltools::makeDependencyRelative, basepath = path(pkg$dst_path, "reference"), mustWork = FALSE ) data$dependencies <- htmltools::renderDependencies(deps, c("file", "href")) } render_page( pkg, "reference-topic", data = data, path = path("reference", topic$file_out) ) invisible() } # Convert Rd to list ------------------------------------------------------ data_reference_topic <- function( topic, pkg, examples_env = globalenv(), run_dont_run = FALSE ) { local_context_eval(pkg$figures, pkg$src_path) withr::local_options(list(downlit.rdname = get_rdname(topic))) tag_names <- purrr::map_chr(topic$rd, ~ class(.)[[1]]) tags <- split(topic$rd, tag_names) out <- list() # Single top-level converted to string out$name <- flatten_text(tags$tag_name[[1]][[1]]) out$title <- extract_title(tags$tag_title) out$pagetitle <- paste0(strip_html_tags(out$title), " \u2014 ", out$name) # File source out$source <- repo_source(pkg, topic$source) out$filename <- topic$file_in # Multiple top-level converted to string out$author <- purrr::map_chr(tags$tag_author %||% list(), flatten_para) out$aliases <- purrr::map_chr(tags$tag_alias %||% list(), flatten_text) out$keywords <- purrr::map_chr(tags$tag_keyword %||% list(), flatten_text) # Sections that contain arbitrary text and need cross-referencing out$description <- as_data(tags$tag_description[[1]]) out$opengraph <- list(description = strip_html_tags(out$description$contents)) if (length(tags$tag_usage[[1]])) { out$usage <- list( title = tr_("Usage"), contents = as_data(tags$tag_usage[[1]]) ) } if (!is.null(tags$tag_examples)) { out$examples <- run_examples( tags$tag_examples[[1]], env = if (is.null(examples_env)) NULL else new.env(parent = examples_env), topic = tools::file_path_sans_ext(topic$file_in), run_dont_run = run_dont_run ) deps <- attr(out$examples, "dependencies") if (!is.null(deps)) { attr(out$examples, "dependencies") <- NULL out$dependencies <- deps } } # Everything else stays in original order, and becomes a list of sections. section_tags <- paste0( "tag_", c( "arguments", "value", "details", "references", "source", "format", "note", "seealso", "section", "author" ) ) sections <- topic$rd[tag_names %in% section_tags] out$sections <- purrr::map(sections, function(section) { data <- as_data(section) data$slug <- make_slug(data$title) data }) out } make_slug <- function(x) { x <- strip_html_tags(x) x <- tolower(x) x <- gsub("[^a-z]+", "-", x) x } get_rdname <- function(topics) { gsub("\\.[Rr]d$", "", topics$file_in) } pkgdown/R/rd-html.R0000644000176200001440000003670615074163153013637 0ustar liggesusersas_html <- function(x, ...) { UseMethod("as_html") } # Various types of text ------------------------------------------------------ flatten_para <- function(x, ...) { if (length(x) == 0) { return(character()) } # Look for "\n" TEXT blocks after a TEXT block, and not at end of file is_nl <- purrr::map_lgl(x, is_newline, trim = TRUE) is_text <- purrr::map_lgl(x, inherits, "TEXT") is_text_prev <- c(FALSE, is_text[-length(x)]) has_next <- c(rep(TRUE, length(x) - 1), FALSE) is_para_break <- is_nl & is_text_prev & has_next # Or tags that are converted to HTML blocks block_tags <- c( "tag_preformatted", "tag_itemize", "tag_enumerate", "tag_tabular", "tag_describe", "tag_subsection" ) is_block <- purrr::map_lgl(x, inherits, block_tags) # Break before and after each status change before_break <- is_para_break | is_block after_break <- c(FALSE, before_break[-length(x)]) groups <- cumsum(before_break | after_break) unwrap_purrr_error(html <- purrr::map(x, as_html, ...)) # split at line breaks for everything except blocks empty <- purrr::map_lgl(x, purrr::is_empty) needs_split <- !is_block & !empty html[needs_split] <- purrr::map(html[needs_split], split_at_linebreaks) blocks <- purrr::map_chr(split(html, groups), function(x) { paste(unlist(x), collapse = "") }) # There are three types of blocks: # 1. Combined text and inline tags # 2. Paragraph breaks (text containing only "\n") # 3. Block-level tags # # Need to wrap 1 in

    needs_p <- purrr::map_lgl(split(!(is_nl | is_block), groups), any) blocks[needs_p] <- paste0("

    ", str_trim(blocks[needs_p]), "

    ") paste0(blocks, collapse = "") } split_at_linebreaks <- function(text) { if (length(text) == 0) { character() } else { strsplit(text, "\\n\\s*\\n")[[1]] } } flatten_text <- function(x, ...) { if (length(x) == 0) { return("") } unwrap_purrr_error(html <- purrr::map_chr(x, as_html, ...)) paste(html, collapse = "") } #' @export as_html.Rd <- function(x, ...) flatten_text(x, ...) #' @export as_html.LIST <- flatten_text # Leaves ----------------------------------------------------------------- #' @export as_html.character <- function(x, ..., escape = TRUE) { # src_highlight (used by usage, examples, and out) also does escaping # so we need some way to turn it off when needed. if (escape) { escape_html(x) } else { as.character(x) } } #' @export as_html.TEXT <- function(x, ..., escape = TRUE) { # tools:::htmlify x <- gsub("---", "\u2014", x) x <- gsub("--", "\u2013", x) x <- gsub("``", "\u201c", x) x <- gsub("''", "\u201d", x) x <- as_html.character(x, ..., escape = escape) x } #' @export as_html.RCODE <- as_html.character #' @export as_html.VERB <- as_html.character #' @export as_html.COMMENT <- function(x, ...) { paste0("") } # USERMACRO appears first, followed by the rendered macro #' @export as_html.USERMACRO <- function(x, ...) "" #' @export as_html.tag_subsection <- function(x, ..., subsection_level = 3L) { h <- paste0("h", subsection_level) title <- flatten_text(x[[1]], ...) id <- make_slug(title) text <- flatten_para(x[[2]], ..., subsection_level = subsection_level + 1L) # fmt: skip paste0( "
    \n", "<", h, ">", title, "\n", text, "\n", "
    " ) } # Equations ------------------------------------------------------------------ #' @export as_html.tag_eqn <- function(x, ...) { latex_rep <- x[[1]] paste0("\\(", flatten_text(latex_rep, ...), "\\)") } #' @export as_html.tag_deqn <- function(x, ...) { latex_rep <- x[[1]] paste0("$$", flatten_text(latex_rep, ...), "$$") } # Links ---------------------------------------------------------------------- #' @export as_html.tag_url <- function(x, ...) { if (length(x) != 1) { if (length(x) == 0) { msg <- "Check for empty \\url{{}} tags." } else { msg <- "This may be caused by a \\url tag that spans a line break." } stop_bad_tag("url", msg) } text <- flatten_text(x[[1]]) a(text, href = text) } #' @export as_html.tag_href <- function(x, ...) { a(flatten_text(x[[2]]), href = flatten_text(x[[1]])) } #' @export as_html.tag_email <- function(x, ...) { if (length(x) != 1) { stop_bad_tag("email", "empty {}") } paste0("", x[[1]], "") } # If single, need to look up alias to find file name and package #' @export as_html.tag_link <- function(x, ...) { opt <- attr(x, "Rd_option") in_braces <- flatten_text(x) if (is.null(opt)) { # \link{topic} href <- downlit::href_topic(in_braces) } else if (substr(opt, 1, 1) == "=") { # \link[=dest]{name} href <- downlit::href_topic(substr(opt, 2, nchar(opt))) } else { match <- regexec('^([^:]+)(?:|:(.*))$', opt) parts <- regmatches(opt, match)[[1]][-1] if (parts[[2]] == "") { # \link[pkg]{foo} href <- downlit::href_topic(in_braces, opt) } else { # \link[pkg:bar]{foo} href <- downlit::href_topic(parts[[2]], parts[[1]]) } } a(in_braces, href = href) } #' @export as_html.tag_linkS4class <- function(x, ...) { if (length(x) != 1) { stop_bad_tag("linkS4class") } text <- flatten_text(x[[1]]) href <- downlit::href_topic(paste0(text, "-class")) a(text, href = href) } # Conditionals and Sexprs ---------------------------------------------------- #' @export as_html.tag_Sexpr <- function(x, ...) { code <- flatten_text(x, escape = FALSE) options <- parse_opts(attr(x, "Rd_option")) # Needs to be package root old_wd <- setwd(context_get("src_path")) on.exit(setwd(old_wd), add = TRUE) # Environment shared across a file env <- context_get("sexpr_env") results <- options$results %||% "rd" if (results == "verbatim") { outlines <- utils::capture.output({ out <- withVisible(eval(parse(text = code), env)) res <- out$value if (out$visible) print(res) }) paste0( "
    \n",
          paste0(escape_html(outlines), collapse = "\n"),
          "\n
    \n" ) } else { res <- eval(parse(text = code), env) switch( results, text = as.character(res), rd = flatten_text(rd_text(as.character(res))), hide = "", cli::cli_abort( "unknown \\Sexpr option: results={results}", call = NULL ) ) } } #' @export as_html.tag_if <- function(x, ...) { if (x[[1]] == "html") { as_html(x[[2]], ...) } else { "" } } #' @export as_html.tag_ifelse <- function(x, ...) { if (x[[1]] == "html") as_html(x[[2]], ...) else as_html(x[[3]], ...) } # Used inside a \usage{} Rd tag to prevent the code from being treated as # regular R syntax, either because it is not valid R, or because its usage # intentionally deviates from regular R usage. An example of the former is the # command line documentation, e.g. `R CMD SHLIB` # (https://github.com/wch/r-source/blob/trunk/src/library/utils/man/SHLIB.Rd): # # \special{R CMD SHLIB [options] [-o dllname] files} # # An example of the latter is the documentation shortcut `?` # (https://github.com/wch/r-source/blob/trunk/src/library/utils/man/Question.Rd): # # \special{?topic} # #' @export as_html.tag_special <- function(x, ...) { flatten_text(x, ...) } #' @export `as_html.#ifdef` <- function(x, ...) { os <- trimws(flatten_text(x[[1]])) if (os == "unix") { flatten_text(x[[2]]) } else { "" } } #' @export `as_html.#ifndef` <- function(x, ...) { os <- trimws(flatten_text(x[[1]])) if (os == "windows") { flatten_text(x[[2]]) } else { "" } } # Tables --------------------------------------------------------------------- #' @export as_html.tag_tabular <- function(x, ...) { align_abbr <- strsplit(as_html(x[[1]], ...), "")[[1]] align_abbr <- align_abbr[!(align_abbr %in% c("|", ""))] align <- unname(c("r" = "right", "l" = "left", "c" = "center")[align_abbr]) contents <- x[[2]] class <- purrr::map_chr(contents, ~ class(.x)[[1]]) cell_contents <- purrr::map_chr(contents, flatten_text, ...) row_sep <- class == "tag_cr" contents[row_sep] <- list("") col_sep <- class == "tag_tab" sep <- col_sep | row_sep # Identify groups in reverse order (preserve empty cells) # Negative maintains correct ordering once reversed cell_grp <- rev(cumsum(-rev(sep))) cells <- unname(split(contents, cell_grp)) # Remove trailing content (that does not match the dimensions of the table) cells <- cells[seq_len(length(cells) - length(cells) %% length(align))] cell_contents <- purrr::map_chr(cells, flatten_text, ...) cell_contents <- paste0("", str_trim(cell_contents), "") cell_contents <- matrix(cell_contents, ncol = length(align), byrow = TRUE) rows <- apply(cell_contents, 1, paste0, collapse = "") paste0( "\n", paste0("", rows, "\n", collapse = ""), "
    \n" ) } # Figures ----------------------------------------------------------------- #' @export as_html.tag_figure <- function(x, ...) { n <- length(x) path <- as.character(x[[1]]) if (n == 1) { paste0("") } else if (n == 2) { opt <- paste(trimws(as.character(x[[2]])), collapse = " ") if (substr(opt, 1, 9) == "options: ") { extra <- substr(opt, 9, nchar(opt)) paste0("") } else { paste0("", opt, "") } } } # List ----------------------------------------------------------------------- #' @export as_html.tag_itemize <- function(x, ...) { paste0("
      \n", parse_items(x[-1], ...), "
    ") } #' @export as_html.tag_enumerate <- function(x, ...) { paste0("
      \n", parse_items(x[-1], ...), "
    ") } #' @export as_html.tag_describe <- function(x, ...) { paste0("
    \n", parse_descriptions(x[-1], ...), "\n
    ") } # Effectively does nothing: only used by parse_items() to split up # sequence of tags. #' @export as_html.tag_item <- function(x, ...) { "" } parse_items <- function(rd, ...) { separator <- purrr::map_lgl(rd, inherits, "tag_item") group <- cumsum(separator) # Drop anything before first tag_item if (!all(group == 0) && any(group == 0)) { rd <- rd[group != 0] group <- group[group != 0] } parse_item <- function(x) { x <- trim_ws_nodes(x) paste0("
  • ", flatten_para(x, ...), "
  • \n") } paste(purrr::map_chr(split(rd, group), parse_item), collapse = "") } parse_descriptions <- function(rd, ..., id_prefix = NULL) { if (length(rd) == 0) { return(character()) } parse_item <- function(x) { if (inherits(x, "tag_item")) { term <- flatten_text(x[[1]], ...) def <- flatten_para(x[[2]], ...) if (!is.null(id_prefix)) { id <- paste0(id_prefix, make_slug(term)) id_attr <- paste0(" id='", id, "'") anchor <- anchor_html(id) } else { id_attr <- "" anchor <- "" } paste0( "", term, anchor, "\n", "
    ", def, "
    \n" ) } else { flatten_text(x, ...) } } paste(purrr::map_chr(rd, parse_item), collapse = "") } # Marking text ------------------------------------------------------------ # https://cran.rstudio.com/doc/manuals/r-devel/R-exts.html#Marking-text tag_wrapper <- function(prefix, suffix = NULL) { function(x, ...) { html <- flatten_text(x, ...) paste0(prefix, html, suffix) } } #' @export as_html.tag_emph <- tag_wrapper("", "") #' @export as_html.tag_strong <- tag_wrapper("", "") #' @export as_html.tag_bold <- tag_wrapper("", "") #' @export as_html.tag_dQuote <- tag_wrapper("“", "”") #' @export as_html.tag_sQuote <- tag_wrapper("‘", "’") #' @export as_html.tag_code <- function(x, ..., auto_link = TRUE) { text <- flatten_text(x, ...) if (auto_link) { href <- downlit::autolink_url(text) text <- a(text, href = href) } paste0("", text, "") } #' @export as_html.tag_preformatted <- function(x, ...) { # the language is stored in a prior \if{}{\out{}} block, so we delay # highlighting until we have the complete html page pre(flatten_text(x, ...)) } #' @export as_html.tag_kbd <- tag_wrapper("", "") #' @export as_html.tag_samp <- tag_wrapper('', "") #' @export as_html.tag_verb <- tag_wrapper("", "") #' @export as_html.tag_pkg <- tag_wrapper('', "") #' @export as_html.tag_file <- tag_wrapper('', '') #' @export as_html.tag_var <- tag_wrapper("", "") #' @export as_html.tag_env <- tag_wrapper('', '') #' @export as_html.tag_option <- tag_wrapper('', "") #' @export as_html.tag_command <- tag_wrapper("", "") #' @export as_html.tag_dfn <- tag_wrapper("", "") #' @export as_html.tag_cite <- tag_wrapper("", "") #' @export as_html.tag_acronym <- tag_wrapper('', '') #' @export as_html.tag_out <- function(x, ...) flatten_text(x, ..., escape = FALSE) # Insertions -------------------------------------------------------------- #' @export as_html.tag_R <- function(x, ...) 'R' #' @export as_html.tag_dots <- function(x, ...) "..." #' @export as_html.tag_ldots <- function(x, ...) "..." #' @export as_html.tag_cr <- function(x, ...) "
    " # First element of enc is the encoded version (second is the ascii version) #' @export as_html.tag_enc <- function(x, ...) { if (length(x) == 2) { as_html(x[[1]], ...) } else { stop_bad_tag("enc") } } # Elements that don't return anything ---------------------------------------- #' @export as_html.tag_tab <- function(x, ...) "" #' @export as_html.tag_newcommand <- function(x, ...) "" #' @export as_html.tag_renewcommand <- function(x, ...) "" #' @export as_html.tag <- function(x, ...) { if (identical(class(x), "tag")) { flatten_text(x, ...) } else { cli::cli_inform("Unknown tag: {.cls {class(x)}}") "" } } # Whitespace helper ------------------------------------------------------- trim_ws_nodes <- function(x, side = c("both", "left", "right")) { is_ws <- purrr::map_lgl(x, ~ inherits(., "TEXT") && grepl("^\\s*$", .[[1]])) if (!any(is_ws)) { return(x) } if (all(is_ws)) { return(x[0]) } which_not <- which(!is_ws) side <- match.arg(side) if (side %in% c("left", "both")) { start <- which_not[1] } else { start <- 1 } if (side %in% c("right", "both")) { end <- which_not[length(which_not)] } else { end <- length(x) } x[start:end] } # Helpers ----------------------------------------------------------------- parse_opts <- function(string) { if (is.null(string)) { return(list()) } args <- list("text", "verbatim", "rd", "hide", "build", "install", "render") names(args) <- args arg_env <- child_env(baseenv(), !!!args) args <- strsplit(string, ",")[[1]] exprs <- purrr::map(args, parse_expr) env <- child_env(arg_env) purrr::walk(exprs, eval_bare, env = env) as.list(env) } stop_bad_tag <- function(tag, msg = NULL) { bad_tag <- paste0("\\", tag, "{}") msg_abort <- 'Failed to parse tag {.val {bad_tag}}.' cli::cli_abort(c(msg_abort, i = msg), call = NULL) } is_newline <- function(x, trim = FALSE) { if (!inherits(x, "TEXT") && !inherits(x, "RCODE") && !inherits(x, "VERB")) { return(FALSE) } text <- x[[1]] if (trim) { text <- gsub("^[ \t]+|[ \t]+$", "", text) } identical(text, "\n") } pkgdown/R/build-home-md.R0000644000176200001440000000273714770274305014714 0ustar liggesusersbuild_home_md <- function(pkg) { mds <- package_mds(pkg$src_path, in_dev = pkg$development$in_dev) lapply(mds, render_md, pkg = pkg) invisible() } package_mds <- function(path, in_dev = FALSE) { mds <- dir_ls(path, glob = "*.md") # Also looks in .github, if it exists github_path <- path(path, ".github") if (dir_exists(github_path)) { mds <- c(mds, dir_ls(github_path, glob = "*.md")) } # Remove files handled elsewhere handled <- c("README.md", "LICENSE.md", "LICENCE.md", "NEWS.md") mds <- mds[!path_file(mds) %in% handled] # Do not build 404 page if in-dev if (in_dev) { mds <- mds[path_file(mds) != "404.md"] } # Remove files that don't need to be rendered no_render <- c( "issue_template.md", "pull_request_template.md", "cran-comments.md" ) mds <- mds[!path_file(mds) %in% no_render] unname(mds) } render_md <- function(pkg, filename) { cli::cli_inform("Reading {src_path(path_rel(filename, pkg$src_path))}") body <- markdown_body(pkg, filename, strip_header = TRUE) path <- path_ext_set(path_file(filename), "html") render_page( pkg, "title-body", data = list( pagetitle = attr(body, "title"), body = body, filename = filename, source = repo_source(pkg, path_rel(filename, pkg$src_path)) ), path = path ) if (path == "404.html") { update_html(path(pkg$dst_path, path), tweak_link_absolute, pkg = pkg) } check_missing_images(pkg, filename, path) invisible() } pkgdown/R/build-home-license.R0000644000176200001440000000406414770274305015731 0ustar liggesusers# Renders LICENSE text file into html build_home_license <- function(pkg) { license_md <- path_first_existing(pkg$src_path, c("LICENSE.md", "LICENCE.md")) if (!is.null(license_md)) { render_md(pkg, license_md) } license_raw <- path_first_existing(pkg$src_path, c("LICENSE", "LICENCE")) if (!is.null(license_raw)) { render_page( pkg, "title-body", data = list( pagetitle = tr_("License"), body = paste0("
    ", escape_html(read_file(license_raw)), "
    ") ), path = "LICENSE-text.html" ) return() } } data_home_sidebar_license <- function(pkg = ".") { pkg <- as_pkgdown(pkg) link <- autolink_license(pkg$desc$get_field("License", "")) license_md <- path_first_existing(pkg$src_path, c("LICENSE.md", "LICENCE.md")) if (!is.null(license_md)) { link <- c( a(tr_("Full license"), "LICENSE.html"), paste0("", link, "") ) } sidebar_section(tr_("License"), link) } # helpers ----------------------------------------------------------------- autolink_license <- function(x) { db <- licenses_db() for (i in seq_len(nrow(db))) { match <- paste0("\\b\\Q", db$abbr[[i]], "\\E\\b") x <- gsub(match, db$a[[i]], x, perl = TRUE) } x } licenses_db <- function() { path <- path(R.home("share"), "licenses", "license.db") db <- tibble::as_tibble(read.dcf(path)) db <- add_missing_sss(db) abbr <- ifelse(is.na(db$SSS), db$Abbrev, db$SSS) url <- db$URL # Add entry for LICENSE file abbr <- c(abbr, "LICENSE", "LICENCE") url <- c(url, "LICENSE-text.html", "LICENSE-text.html") out <- tibble::tibble(abbr, url) out$a <- paste0("", abbr, "") out[!is.na(out$abbr), ] } # Add missing standard short specification (SSS) for some licenses # (e.g., Mozilla Public Licences) # see src/library/tools/R/license.R in R source for details add_missing_sss <- function(db) { needs_sss <- !is.na(db$Abbrev) & !is.na(db$Version) & is.na(db$SSS) x <- db[needs_sss, ] db[needs_sss, "SSS"] <- paste0(x$Abbrev, "-", x$Version) db } pkgdown/R/build-favicons.R0000644000176200001440000000725214770274305015173 0ustar liggesusers#' Initialise favicons from package logo #' #' @description #' This function auto-detects the location of your package logo (with the name #' `logo.svg` (recommended format) or `logo.png`, created with `usethis::use_logo()`) #' and runs it through the API to build a #' complete set of favicons with different sizes, as needed for modern web usage. #' #' You only need to run the function once. The favicon set will be stored in #' `pkgdown/favicon` and copied by [init_site()] to the relevant location when #' the website is rebuilt. #' #' Once complete, you should add `pkgdown/` to `.Rbuildignore ` to avoid a NOTE #' during package checking. (`usethis::use_logo()` does this for you!) #' #' @inheritParams as_pkgdown #' @param overwrite If `TRUE`, re-create favicons from package logo. #' @export build_favicons <- function(pkg = ".", overwrite = FALSE) { rlang::check_installed("openssl") pkg <- as_pkgdown(pkg) cli::cli_rule("Building favicons") logo_path <- find_logo(pkg$src_path) if (is.null(logo_path)) { cli::cli_abort(c( "Can't find package logo PNG or SVG to build favicons.", "i" = "See {.fun usethis::use_logo} for more information." )) } if (has_favicons(pkg) && !overwrite) { cli::cli_inform(c( "Favicons already exist in {.path pkgdown}", "i" = "Set {.code overwrite = TRUE} to re-create." )) return(invisible()) } cli::cli_inform(c( i = "Building favicons with {.url https://realfavicongenerator.net}..." )) logo <- readBin(logo_path, what = "raw", n = file_info(logo_path)$size) json_request <- list( "favicon_generation" = list( "api_key" = "87d5cd739b05c00416c4a19cd14a8bb5632ea563", "master_picture" = list( "type" = "inline", "content" = openssl::base64_encode(logo) ), "favicon_design" = list( "desktop_browser" = list(), "ios" = list( "picture_aspect" = "no_change", "assets" = list( "ios6_and_prior_icons" = FALSE, "ios7_and_later_icons" = TRUE, "precomposed_icons" = FALSE, "declare_only_default_icon" = TRUE ) ) ) ) ) req <- httr2::request("https://realfavicongenerator.net/api/favicon") req <- httr2::req_body_json(req, json_request) withCallingHandlers( resp <- httr2::req_perform(req), error = function(e) { cli::cli_abort("API request failed.", parent = e) } ) content <- httr2::resp_body_json(resp) result <- content$favicon_generation_result if (!identical(result$result$status, "success")) { cli::cli_abort("API request failed.", .internal = TRUE) } tmp <- withr::local_tempfile() req <- httr2::request(result$favicon$package_url) resp <- httr2::req_perform(req, tmp) withCallingHandlers( paths <- utils::unzip( tmp, exdir = path(pkg$src_path, "pkgdown", "favicon") ), warning = function(e) { cli::cli_abort( "Your logo file couldn't be processed and may be corrupt.", parent = e ) }, error = function(e) { cli::cli_abort( "Your logo file couldn't be processed and may be corrupt.", parent = e ) } ) cli::cli_inform(c("v" = "Added {.path {sort(path_file(paths))}}.")) invisible() } copy_favicons <- function(pkg = ".") { pkg <- as_pkgdown(pkg) dir_copy_to( src_dir = path(pkg$src_path, "pkgdown", "favicon"), src_root = pkg$src_path, dst_dir = pkg$dst_path, dst_root = pkg$dst_path ) } has_favicons <- function(pkg = ".") { pkg <- as_pkgdown(pkg) unname(file_exists(path_favicons(pkg))) } path_favicons <- function(pkg) { path(pkg$src_path, "pkgdown", "favicon") } pkgdown/R/tweak.R0000644000176200001440000000056414134254444013374 0ustar liggesusershas_class <- function(html, class) { classes <- strsplit(xml2::xml_attr(html, "class"), " ") purrr::map_lgl(classes, ~ any(class %in% .x)) } tweak_class_prepend <- function(x, class) { if (length(x) == 0) { return(invisible()) } cur <- xml2::xml_attr(x, "class") xml2::xml_attr(x, "class") <- ifelse(is.na(cur), class, paste(class, cur)) invisible() } pkgdown/R/test.R0000644000176200001440000001413515074513430013234 0ustar liggesusers#' Test case: lists #' #' @noMd #' @description #' #' \subsection{Bulleted list}{ #' \itemize{ #' \item a #' \item This is an item... #' #' That spans multiple paragraphs. #' } #' } #' #' \subsection{Bulleted list (single item)}{ #' \itemize{\item a} #' } #' #' \subsection{Numbered list}{ #' \enumerate{ #' \item a #' \item b #' } #' } #' #' \subsection{Definition list}{ #' \describe{ #' \item{short}{short} #' \item{short}{Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do #' eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad #' minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip #' ex ea commodo consequat. Duis aute irure dolor in reprehenderit in #' voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur #' sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt #' mollit anim id est laborum.} #' \item{Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do #' eiusmod tempor incididunt ut labore et dolore magna aliqua.}{short} #' \item{Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do #' eiusmod tempor incididunt ut labore et dolore magna aliqua.}{Lorem ipsum #' adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore ad #' minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip #' ex ea commodo consequat. Duis aute irure dolor in reprehenderit in #' voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur #' sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt #' mollit anim id est laborum.} #' } #' } #' @keywords internal #' @family tests #' @name test-lists NULL #' Test case: links #' #' ```{r} #' jsonlite::minify("{}") #' ``` #' #' @name test-links #' @keywords internal #' @family tests #' @examples #' jsonlite::minify("{}") #' #' library(jsonlite, warn.conflicts = FALSE) #' minify("{}") NULL #' Test case: figures #' #' \figure{bacon.jpg} #' #' @name test-figures #' @keywords internal #' @family tests #' @examples #' x <- seq(0, 2 * pi, length.out = 25) #' plot(x, sin(x)) #' #' plot(1:10) #' lines(1:10) #' text(2, 5, "Hello", srt = 30, cex = 2) #' #' plot(1:3, col = c("red", "green", "blue"), pch = 16, cex = 10) NULL #' Test case: tables #' #' @name test-tables #' @keywords internal #' @family tests #' @examples #' gt::gt(head(mtcars)) NULL #' Test case: don't #' #' @name test-dont #' @keywords internal #' @family tests #' @examples #' # \dontrun{} -------------------------------------------------------- #' # always shown; never run #' #' x <- 1 #' \dontrun{x <- 2} #' \dontrun{ #' x <- 3 #' x <- 4 #' } #' x # should be 1 #' #' # \donttest{} ------------------------------------------------------- #' # only multiline are shown; always run #' #' x <- 1 #' \donttest{x <- 2} #' \donttest{ #' x <- 3 #' x <- 4 #' } #' x # should be 4 #' #' # \testonly{} ----------------------------------------------------- #' # never shown, never run #' #' x <- 1 #' \testonly{x <- 2} #' \testonly{ #' x <- 3 #' x <- 4 #' } #' x # should be 1 #' #' # \dontshow{} ------------------------------------------------------- #' # never shown, always run #' #' x <- 1 #' \dontshow{x <- 2} #' \dontshow{ #' x <- 3 #' x <- 4 #' } #' x # should be 4 #' #' # @examplesIf ------------------------------------------------------ #' # If FALSE, wrapped in if; if TRUE, not seen #' #' x <- 1 #' #' @examplesIf FALSE #' x <- 2 #' @examplesIf TRUE #' x <- 3 #' @examples #' x # should be 3 NULL #' Test case: params #' #' @name test-params #' @param ... ellipsis #' @keywords internal #' @family tests NULL #' Test case: output styles #' #' @name test-output-styles #' @keywords internal #' @family tests #' #' @examples #' # This example illustrates some important output types #' # The following output should be wrapped over multiple lines #' a <- 1:100 #' a #' #' cat("This some text!\n") #' message("This is a message!") #' warning("This is a warning!") #' #' # This is a multi-line block #' { #' 1 + 2 #' 2 + 2 #' } NULL #' Test case: long-lines #' #' The example results should have the copy button correctly placed when #' scrollings #' #' @name test-long-lines #' @keywords internal #' @family tests #' @examples #' pkgdown:::ruler() #' #' cat(rep("x ", 100), sep = "") #' cat(rep("xy", 100), sep = "") #' cat(rep("x ", 100), sep = "") #' cat(rep("xy", 100), sep = "") NULL #' Test case: crayon #' #' @name test-crayon #' @keywords internal #' @family tests #' #' @examples #' cat(cli::col_red("This is red"), "\n") #' cat(cli::col_blue("This is blue"), "\n") #' #' message(cli::col_green("This is green")) #' #' warning(cli::style_bold("This is bold")) NULL #' Test case: preformatted blocks & syntax highlighting #' #' Manual test cases for various ways of embedding code in sections. #' All code blocks should have copy and paste button. #' #' # Should be highlighted #' #' Valid R code in `\preformatted{}`: #' #' ``` #' mean(a + 1) #' ``` #' #' R code in `R` block: #' #' ```R #' mean(a + 1) #' ``` #' #' R code in `r` block: #' #' ```r #' mean(a + 1) #' ``` #' #' Yaml #' #' ```yaml #' yaml: [a, 1] #' ``` #' #' # Shouldn't be highlighted #' #' Non-R code in `\preformatted{}` #' #' ``` #' yaml: [a, b, c] #' ``` #' #' @name test-verbatim #' @keywords internal #' @family tests NULL #' Index #' #' @aliases test-index #' @name index #' @keywords internal #' @family tests NULL #' Test case: \Sexpr[stage=render,results=rd]{"sexpr"} #' #' @name test-sexpr-title #' @keywords internal #' @family tests NULL #' Test case: math rendering in examples #' #' @param x \eqn{f(x) > 0}: inline equation #' #' @details #' Display equation: #' #' \deqn{y = \alpha + \beta X + \varepsilon} #' #' Multi-line equation (correctly rendered by katex only): #' #' \deqn{\text{Minimize } l \\ #' \text{ subject to } \\ #' \sum_{i = 1}^{I} x_i r_{ij} + y_j \geq t_j \forall j \in J \\ #' l \geq \frac{y_j}{t_j} \forall j \in J \\ #' \sum_{i = 1}^{I} x_i c_i \leq B}{ #' Minimize l subject to #' sum_i^I (xi * rij) + yj >= tj for all j in J & #' l >= (yj / tj) for all j in J & #' sum_i^I (xi * ci) <= B} #' #' @name test-math-examples #' @keywords internal #' @family tests NULL pkgdown/R/build-news.R0000644000176200001440000002314415074163153014331 0ustar liggesusers#' Build news section #' #' @description #' A `NEWS.md` will be broken up into versions using level one (`#`) or #' level two headings (`##`) that (partially) match one of the following forms #' (ignoring case): #' #' * `{package name} 1.3.0` #' * `{package name} v1.3.0` #' * `Version 1.3.0` #' * `Changes in 1.3.0` #' * `Changes in v1.3.0` #' #' @details #' A [common structure](https://style.tidyverse.org/news.html) for news files #' is to use a top level heading for each release, and use a second level #' heading to break up individual bullets into sections. #' #' ```yaml #' # foofy 1.0.0 #' #' ## Major changes #' #' * Can now work with all grooveable grobbles! #' #' ## Minor improvements and bug fixes #' #' * Printing scrobbles no longer errors (@githubusername, #100) #' #' * Wibbles are now 55% less jibbly (#200) #' ``` #' #' Issues and contributors will be automatically linked to the corresponding #' pages on GitHub if the GitHub repo can be discovered from the `DESCRIPTION` #' (typically from a `URL` entry containing `github.com`) #' #' If a version is available on CRAN, the release date will automatically #' be added to the heading (see below for how to suppress); if not #' available on CRAN, "Unreleased" will be added. #' #' # YAML config #' #' To automatically link to release announcements, include a `releases` #' section. #' #' ```yaml #' news: #' releases: #' - text: "usethis 1.3.0" #' href: https://www.tidyverse.org/articles/2018/02/usethis-1-3-0/ #' - text: "usethis 1.0.0 (and 1.1.0)" #' href: https://www.tidyverse.org/articles/2017/11/usethis-1.0.0/ #' ``` #' #' Control whether news is present on one page or multiple pages with the #' `one_page` field. The default is `true`. #' #' ```yaml #' news: #' one_page: false #' ``` #' #' Suppress the default addition of CRAN release dates with: #' #' ```yaml #' news: #' cran_dates: false #' ``` #' @family site components #' #' @seealso [Tidyverse style for News](https://style.tidyverse.org/news.html) #' #' @inheritParams build_articles #' @export build_news <- function(pkg = ".", override = list(), preview = FALSE) { pkg <- section_init(pkg, "news", override = override) if (!has_news(pkg$src_path)) { return(invisible()) } cli::cli_rule("Building news") one_page <- config_pluck_bool(pkg, "news.one_page", default = TRUE) if (one_page) { build_news_single(pkg) } else { build_news_multi(pkg) } preview_site(pkg, "news", preview = preview) } build_news_single <- function(pkg = ".") { pkg <- as_pkgdown(pkg) news <- data_news(pkg) render_page( pkg, "news", list( contents = purrr::transpose(news), pagetitle = tr_("Changelog"), source = repo_source(pkg, "NEWS.md") ), path("news", "index.html") ) } build_news_multi <- function(pkg = ".") { pkg <- as_pkgdown(pkg) news <- data_news(pkg) page <- factor(news$page, levels = unique(news$page)) news_paged <- tibble::tibble( version = levels(page), file_out = paste0("news-", version, ".html"), contents = split(news[c("html", "version", "anchor")], page) ) render_news <- function(version, file_out, contents) { # Older, major, versions first on each page # https://github.com/r-lib/pkgdown/issues/2285#issuecomment-2070966518 render_page( pkg, "news", list( version = version, contents = rev(purrr::transpose(contents)), pagetitle = sprintf(tr_("Version %s"), version) ), path("news", file_out), ) } purrr::pwalk(news_paged, render_news) render_page( pkg, "news-index", list( versions = purrr::transpose(news_paged), pagetitle = tr_("News") ), path("news", "index.html") ) } data_news <- function(pkg, call = caller_env()) { html <- markdown_body(pkg, path(pkg$src_path, "NEWS.md")) xml <- xml2::read_html(html) sections <- xml2::xml_find_all(xml, "./body/div") footnotes <- has_class(sections, "footnotes") if (any(footnotes)) { cli::cli_warn("Footnotes in NEWS.md are not currently supported") } sections <- sections[!footnotes] headings <- xml2::xml_find_first(sections, ".//h1|.//h2|.//h3|.//h4|.//h5") levels <- xml2::xml_name(headings) ulevels <- unique(levels) if (!identical(ulevels, "h1") && !identical(ulevels, "h2")) { msg <- c( "inconsistent use of section headings.", i = "Top-level headings must be either all

    or all

    .", i = "See {.help pkgdown::build_news} for more details." ) config_abort(pkg, msg, path = "NEWS.md", call = call) } if (ulevels == "h1") { # Bump every heading down a level so to get a single

    for the page title tweak_section_levels(xml) } titles <- xml2::xml_text(xml2::xml_find_first(sections, ".//h2"), trim = TRUE) versions <- news_version(titles, pkg$package) sections <- sections[!is.na(versions)] if (length(sections) == 0) { msg <- c( "no version headings found", i = "See {.help pkgdown::build_news} for expected structure." ) config_warn(pkg, msg, path = "NEWS.md", call = call) } versions <- versions[!is.na(versions)] show_dates <- config_pluck_bool( pkg, "news.cran_dates", default = !is_testing() ) if (show_dates) { timeline <- pkg_timeline(pkg$package) } else { timeline <- NULL } purrr::walk2( sections, versions, tweak_news_heading, timeline = timeline, bs_version = pkg$bs_version ) html <- purrr::map_chr(sections, as.character, options = character()) html <- purrr::map_chr(html, repo_auto_link, pkg = pkg) anchors <- xml2::xml_attr(sections, "id") news <- tibble::tibble( version = versions, page = purrr::map_chr(versions, version_page), anchor = anchors, html = html ) news } news_version <- function(x, pkgname) { pattern <- paste0( "(?x) (?:", pkgname, "|version|changes\\ in) \\s+ # whitespace v? # optional v followed by (? (?:\\d+[.-]\\d+)(?:[.-]\\d+)* # digits, dots, and dashes | # OR \\(development\\ version\\) # literal used by usethis ) " ) pieces <- re_match(x, pattern, ignore.case = TRUE) gsub("^[(]|[)]$", "", pieces$version) } version_page <- function(x) { if (x == "development version") { return("dev") } ver <- unclass(package_version(x))[[1]] if (length(ver) == 4 && ver[[4]] > 0) { "dev" } else { paste0(ver[[1]], ".", ver[[2]]) } } navbar_news <- function(pkg) { releases_meta <- config_pluck_list(pkg, "news.releases") if (!is.null(releases_meta)) { menu_submenu( tr_("News"), list2( menu_heading(tr_("Releases")), !!!releases_meta, menu_separator(), menu_link(tr_("Changelog"), "news/index.html") ) ) } else if (has_news(pkg$src_path)) { menu_link(tr_("Changelog"), "news/index.html") } } has_news <- function(path = ".") { file_exists(path(path, "NEWS.md")) } pkg_timeline <- function(package) { url <- paste0("https://crandb.r-pkg.org/", package, "/all") req <- httr2::request(url) req <- httr2::req_retry(req, max_tries = 3) req <- httr2::req_error(req, function(resp) FALSE) resp <- httr2::req_perform(req) if (httr2::resp_is_error(resp)) { return(NULL) } content <- httr2::resp_body_json(resp) timeline <- unlist(content$timeline) data.frame( version = names(timeline), date = as.Date(timeline), row.names = NULL ) } tweak_news_heading <- function(html, version, timeline, bs_version) { class <- if (bs_version == 3) "page-header" else "pkg-version" h2 <- xml2::xml_find_all(html, ".//h2") xml2::xml_set_attr(h2, "class", class) xml2::xml_set_attr(h2, "data-toc-text", version) # Add release date, if known if (!is.null(timeline)) { date <- timeline$date[match(version, timeline$version)] if (!is.na(date)) { if (bs_version == 3) { release_str <- paste0(" ", date, "") release_html <- xml2::xml_find_first( xml2::read_html(release_str), ".//small" ) xml2::xml_add_child(h2, release_html, .where = 1) } else { release_date <- sprintf(tr_("CRAN release: %s"), date) release_str <- paste0("

    ", release_date, "

    ") release_html <- xml2::xml_find_first( xml2::read_html(release_str), ".//p" ) xml2::xml_add_sibling(h2, release_html, .where = "after") } } } tweak_news_anchor(html, version) invisible() } # Manually de-duplicate repeated section anchors using version tweak_news_anchor <- function(html, version) { div <- xml2::xml_find_all(html, ".//div") div <- div[has_class(div, "section")] id <- xml2::xml_attr(div, "id") id <- gsub("-[0-9]+", "", id) # remove pandoc de-duplication suffixes id <- paste0(id, "-", gsub("[^a-z0-9]+", "-", version)) # . breaks scrollspy xml2::xml_attr(div, "id") <- id invisible() } tweak_section_levels <- function(html) { sections <- xml2::xml_find_all( html, ".//div[contains(@class, 'section level')]|//main/section" ) # Update headings xml2::xml_set_name(xml2::xml_find_all(sections, ".//h5"), "h6") xml2::xml_set_name(xml2::xml_find_all(sections, ".//h4"), "h5") xml2::xml_set_name(xml2::xml_find_all(sections, ".//h3"), "h4") xml2::xml_set_name(xml2::xml_find_all(sections, ".//h2"), "h3") xml2::xml_set_name(xml2::xml_find_all(sections, ".//h1"), "h2") # Update section xml2::xml_attr(sections, "class") <- paste0( "section level", get_section_level(sections) + 1 ) invisible() } news_style <- function(pkg) { one_page <- config_pluck_bool(pkg, "new.one_page") if (one_page) "single" else "multi" } pkgdown/R/check.R0000644000176200001440000000576214770274305013347 0ustar liggesusers#' Check `_pkgdown.yml` #' #' @description #' This pair of functions checks that your `_pkgdown.yml` is valid without #' building the whole site. `check_pkgdown()` errors at the first problem; #' `pkgdown_sitrep()` reports the status of all checks. #' #' Currently they check that: #' #' * There's a `url` in the pkgdown configuration, which is also recorded #' in the `URL` field of the `DESCRIPTION`. #' #' * All opengraph metadata is valid. #' #' * All reference topics are included in the index. #' #' * All articles/vignettes are included in the index. # #' @export #' @inheritParams as_pkgdown check_pkgdown <- function(pkg = ".") { pkg <- as_pkgdown(pkg) check_urls(pkg) data_open_graph(pkg) data_articles_index(pkg) data_reference_index(pkg) cli::cli_inform(c("v" = "No problems found.")) } #' @export #' @rdname check_pkgdown pkgdown_sitrep <- function(pkg = ".") { cli::cli_rule("Sitrep") pkg <- as_pkgdown(pkg) if (pkg$bs_version == 3) { cli::cli_inform(c( x = "Bootstrap 3 is deprecated; please switch to Bootstrap 5.", i = "Learn more at {.url https://www.tidyverse.org/blog/2021/12/pkgdown-2-0-0/#bootstrap-5}." )) } error_to_sitrep("URLs", check_urls(pkg)) error_to_sitrep("Favicons", check_favicons(pkg)) error_to_sitrep("Open graph metadata", data_open_graph(pkg)) error_to_sitrep("Articles metadata", data_articles_index(pkg)) error_to_sitrep("Reference metadata", data_reference_index(pkg)) } error_to_sitrep <- function(title, code) { tryCatch( { code cli::cli_inform(c("v" = "{title} ok.")) }, rlang_error = function(e) { bullets <- c(cnd_header(e), cnd_body(e)) cli::cli_inform(c(x = "{title} not ok.", set_names(bullets, " "))) } ) invisible() } check_urls <- function(pkg = ".", call = caller_env()) { pkg <- as_pkgdown(pkg) details <- c(i = "See details in {.vignette pkgdown::metadata}.") if (identical(pkg$meta, list())) { cli::cli_abort( c("No {.path _pkgdown.yml} found.", details), call = call ) } url <- pkg$meta[["url"]] if (is.null(url)) { config_abort(pkg, c("{.field url} is missing.", details), call = call) } else { desc_urls <- pkg$desc$get_urls() desc_urls <- sub("/$", "", desc_urls) if (!pkg$meta[["url"]] %in% desc_urls) { msg <- "{.field URL} is missing package url ({url})." config_abort(pkg, c(msg, details), path = "DESCRIPTION", call = call) } } } check_favicons <- function(pkg) { if (!has_logo(pkg)) { return() } if (has_favicons(pkg)) { logo <- find_logo(pkg$src_path) favicon <- path(path_favicons(pkg), "favicon.ico") if (out_of_date(logo, favicon)) { cli::cli_abort(c( "Package logo is newer than favicons.", i = "Do you need to rerun {.run [build_favicons()](pkgdown::build_favicons())}?" )) } } else { cli::cli_abort(c( "Found package logo but not favicons.", i = "Do you need to run {.run [build_favicons()](pkgdown::build_favicons())}?" )) } } pkgdown/R/navbar-menu.R0000644000176200001440000001531315011715040014457 0ustar liggesusers# Menu constructors ----------------------------------------------------------- # Helpers for use within pkgdown itself - these must stay the same as the # yaml structure defined in vignette("customise") menu_submenu <- function(text, menu, icon = NULL, label = NULL, id = NULL) { if (length(menu) == 0) { return() } else { purrr::compact(list( text = text, icon = icon, "aria-label" = label, id = id, menu = menu )) } } menu_link <- function( text, href, target = NULL, class = NULL, id = NULL, title = NULL ) { purrr::compact(list( text = text, href = href, target = target, class = class, id = id, title = title )) } menu_links <- function(text, href) { purrr::map2(text, href, menu_link) } menu_theme <- function(text, icon, theme) { purrr::compact(list(text = text, theme = theme, icon = icon)) } menu_heading <- function(text, ...) list(text = text, ...) menu_separator <- function() list(text = "---------") menu_search <- function() list(search = list()) menu_icon <- function(icon, href, label) { list(icon = icon, href = href, "aria-label" = label) } menu_type <- function(x, menu_depth = 0L) { if (!is.list(x) || !is_named(x)) { not <- obj_type_friendly(x) cli::cli_abort("Navbar components must be named lists, not {not}.") } else if (!is.null(x$menu)) { # https://github.com/twbs/bootstrap/pull/6342 if (menu_depth > 0) { cli::cli_abort("Nested menus are not supported.") } "menu" } else if (!is.null(x$text) && grepl("^\\s*-{3,}\\s*$", x$text)) { "separator" } else if (!is.null(x$theme)) { "theme" } else if (!is.null(x$text) && is.null(x$href)) { "heading" } else if ((!is.null(x$text) || !is.null(x$icon)) && !is.null(x$href)) { "link" } else if (!is.null(x$search)) { "search" } else if (!is_named(x)) { "list" } else { cli::cli_abort("Unknown navbar component with names {names(x)}.") } } # Menu renderers -------------------------------------------------------------- navbar_html <- function( x, path_depth = 0L, menu_depth = 0L, side = c("left", "right") ) { if (is.null(x)) { return("") } side <- arg_match(side) type <- menu_type(x, menu_depth = menu_depth) text <- switch( type, menu = navbar_html_menu( x, menu_depth = menu_depth, path_depth = path_depth, side = side ), heading = navbar_html_heading(x), link = navbar_html_link(x, menu_depth = menu_depth), separator = navbar_html_separator(), search = navbar_html_search(x, path_depth = path_depth), theme = navbar_html_theme(x) ) class <- c( if (menu_depth == 0L) "nav-item", if (type == "menu") "dropdown" ) html_tag("li", class = class, text) } navbar_html_list <- function( x, path_depth = 0L, menu_depth = 0L, side = "left" ) { tags <- unwrap_purrr_error(purrr::map_chr( x, navbar_html, path_depth = path_depth, menu_depth = menu_depth, side = side )) paste0(tags, collapse = "\n") } navbar_html_menu <- function( x, path_depth = 0L, menu_depth = 0L, side = "left" ) { id <- paste0("dropdown-", x$id %||% make_slug(x$text)) button <- html_tag( "button", type = "button", class = c(if (menu_depth == 0L) "nav-link", "dropdown-toggle"), id = id, `data-bs-toggle` = "dropdown", "aria-expanded" = "false", "aria-haspopup" = "true", "aria-label" = x$`aria-label`, navbar_html_text(x), ) li <- navbar_html_list( x$menu, path_depth = path_depth, menu_depth = menu_depth + 1, side = side ) ul <- html_tag( "ul", class = c("dropdown-menu", if (side == "right") "dropdown-menu-end"), "aria-labelledby" = id, paste0("\n", indent(li, " "), "\n") ) paste0("\n", indent(paste0(button, "\n", ul), " "), "\n") } navbar_html_link <- function(x, menu_depth = 0) { base_class <- if (menu_depth == 0) "nav-link" else "dropdown-item" html_tag( "a", class = paste0(c(base_class, x$class), collapse = " "), id = x$id, href = x$href, target = x$target, title = x$title, "aria-label" = x$`aria-label`, navbar_html_text(x) ) } navbar_html_theme <- function(x) { html_tag( "button", class = "dropdown-item", "aria-label" = x$`aria-label`, "data-bs-theme-value" = x$theme, navbar_html_text(x) ) } navbar_html_heading <- function(x) { html_tag( "h6", class = "dropdown-header", "data-toc-skip" = NA, navbar_html_text(x) ) } navbar_html_separator <- function() { '' } navbar_html_search <- function(x, path_depth = 0) { input <- html_tag( "input", type = "search", class = "form-control", name = "search-input", id = "search-input", autocomplete = "off", "aria-label" = tr_("Search site"), placeholder = tr_("Search for"), "data-search-index" = paste0(up_path(path_depth), "search.json") ) html_tag("form", class = "form-inline", role = "search", "\n", input, "\n") } # Reused HTML components ----------------------------------------------------- html_tag <- function(tag, ..., class = NULL) { dots <- list2(...) dots_attr <- dots[have_name(dots)] dots_child <- dots[!have_name(dots)] if (!is.null(class)) { class <- paste0(class, collapse = " ") } attr <- purrr::compact(c(list(class = class), dots_attr)) if (length(attr) > 0) { html_attr <- ifelse( is.na(attr), names(attr), paste0(names(attr), '="', attr, '"') ) html_attr <- paste0(" ", paste0(html_attr, collapse = " ")) } else { html_attr <- "" } html_child <- paste0(purrr::compact(dots_child), collapse = " ") needs_close <- !tag %in% "input" paste0( "<", tag, html_attr, ">", html_child, if (needs_close) paste0("") ) } navbar_html_text <- function(x) { if (is.null(x$icon)) { icon <- "" } else { # Extract icon set from class name classes <- strsplit(x$icon, " ")[[1]] icon_classes <- classes[grepl("-", classes)] iconset <- purrr::map_chr(strsplit(icon_classes, "-"), 1) icon <- html_tag("span", class = unique(c(iconset, classes))) if (is.null(x$`aria-label`) && is.null(x$text)) { cli::cli_inform( c( x = "Icon {.str {x$icon}} lacks an {.var aria-label}.", i = "Specify {.var aria-label} to make the icon accessible to screen readers.", i = "Learn more in {.vignette pkgdown::accessibility}." ), .frequency = "regularly", .frequency_id = "icon-aria-label" ) } } paste0( icon, if (!is.null(x$icon) && !is.null(x$text)) " ", escape_html(x$text) ) } indent <- function(x, indent) { paste0(indent, gsub("\n", paste0("\n", indent), x)) } pkgdown/R/package.R0000644000176200001440000002755514770274305013671 0ustar liggesusers#' Generate pkgdown data structure #' #' You will generally not need to use this unless you need a custom site #' design and you're writing your own equivalent of [build_site()]. #' #' @param pkg Path to package. #' @param override An optional named list used to temporarily override #' values in `_pkgdown.yml` #' @export as_pkgdown <- function(pkg = ".", override = list()) { if (!is.list(override)) { cli::cli_abort( "{.arg override} must be a list, not {obj_type_friendly(override)}." ) } if (is_pkgdown(pkg)) { pkg$meta <- modify_list(pkg$meta, override) return(pkg) } check_string(pkg) if (!dir_exists(pkg)) { if (dir.exists(pkg)) { #nolint # path expansion with fs and base R is different on Windows. # By default "~/", is typically C:/Users/username/Documents, while fs see "~/" as C:/Users/username, to be more platform portable. # Read more in ?fs::path_expand cli::cli_abort( "pkgdown accepts {.href [fs paths](https://fs.r-lib.org/reference/path_expand.html#details)}." ) } cli::cli_abort("{.file {pkg}} is not an existing directory") } if (!dir.exists(pkg)) { #nolint # Use complete path if fs path doesn't exist according to base R #2639 pkg <- path_expand(pkg) } src_path <- pkg desc <- read_desc(src_path) meta <- read_meta(src_path) meta <- modify_list(meta, override) # Create a partial pkgdown object so we can use config_pluck_* functions pkg <- list( package = desc$get_field("Package"), version = desc$get_field("Version"), src_path = path_abs(src_path), meta = meta, desc = desc ) class(pkg) <- "pkgdown" # If boostrap version set locally, it drives the template choice # But if it's not set locally, the template may have a default template <- config_pluck_list(pkg, "template") template_package <- config_pluck_string(pkg, "template.package") bs_version_local <- get_bootstrap_version(pkg, pkg$meta$template) template_meta <- find_template_config(template_package, bs_version_local) if (is.null(bs_version_local)) { bs_version_remote <- get_bootstrap_version( pkg, template_meta$template, template_package ) } else { bs_version_remote <- NULL } bs_version <- bs_version_local %||% bs_version_remote %||% 3 check_bootstrap_version(bs_version, error_pkg = pkg) pkg$bs_version <- bs_version pkg$meta <- modify_list(template_meta, pkg$meta) # Ensure the URL has no trailing slash if (!is.null(pkg$meta$url)) { pkg$meta$url <- sub("/$", "", pkg$meta$url) } pkg$development <- meta_development(pkg) pkg$prefix <- pkg$development$prefix dest <- config_pluck_string(pkg, "destination") pkg$dst_path <- path_abs(dest %||% "docs", start = src_path) if (pkg$development$in_dev) { pkg$dst_path <- path(pkg$dst_path, pkg$development$destination) } pkg$lang <- get_pkg_lang(pkg) pkg$install_metadata <- config_pluck_bool( pkg, "deploy.install_metadata", FALSE ) pkg$figures <- meta_figures(pkg) pkg$repo <- package_repo(pkg) pkg$topics <- package_topics(src_path) pkg$tutorials <- package_tutorials(src_path, meta) pkg$vignettes <- package_vignettes(src_path) pkg } is_pkgdown <- function(x) inherits(x, "pkgdown") read_desc <- function(path = ".") { path <- path(path, "DESCRIPTION") if (!file_exists(path)) { cli::cli_abort("Can't find {.file DESCRIPTION}", call = caller_env()) } desc::description$new(path) } get_pkg_lang <- function(pkg) { if (!is.null(pkg$meta$lang)) { return(pkg$meta$lang) } if (pkg$desc$has_fields("Language")) { field <- pkg$desc$get_field("Language") if (length(field) && nchar(field) > 0) { return(regmatches(field, regexpr("[^,]+", field))) } } return("en") } get_bootstrap_version <- function( pkg, template, template_package = NULL, call = caller_env() ) { if (is.null(template)) { return(NULL) } template_bootstrap <- template[["bootstrap"]] template_bslib <- template[["bslib"]][["version"]] if (!is.null(template_bootstrap) && !is.null(template_bslib)) { if (!is.null(template_package)) { hint <- "Specified locally and in template package {.pkg {template_package}}." } else { hint <- NULL } msg <- "must set only one of {.field template.bootstrap} and {.field template.bslib.version}." config_abort(pkg, c(msg, i = hint), call = call) } template_bootstrap %||% template_bslib } check_bootstrap_version <- function( version, error_pkg, error_call = caller_env() ) { if (version %in% c(3, 5)) { version } else if (version == 4) { msg <- c( "{.var template.bootstrap: 4} no longer supported", i = "Using {.var template.bootstrap: 5} instead" ) config_warn(error_pkg, msg, call = error_call) 5 } else { msg <- "{.field template.bootstrap} must be 3 or 5, not {.val {version}}." config_abort(error_pkg, msg, error_call = caller_env()) } } # Metadata ---------------------------------------------------------------- pkgdown_config_path <- function(path) { if (is_pkgdown(path)) { path <- path$src_path } path_first_existing( path, c( "_pkgdown.yml", "_pkgdown.yaml", "pkgdown/_pkgdown.yml", "pkgdown/_pkgdown.yaml", "inst/_pkgdown.yml", "inst/_pkgdown.yaml" ) ) } read_meta <- function(path, call = caller_env()) { path <- pkgdown_config_path(path) if (is.null(path)) { yaml <- list() } else { yaml <- withCallingHandlers( yaml::yaml.load_file(path, error.label = NULL) %||% list(), error = function(e) { cli::cli_abort( "Could not parse config file at {.path {path}}.", call = call, parent = e ) } ) } yaml } # Topics ------------------------------------------------------------------ package_topics <- function(path = ".") { # Needed if title contains sexpr local_context_eval() rd <- package_rd(path) aliases <- purrr::map(rd, extract_tag, "tag_alias") names <- purrr::map_chr(rd, extract_tag, "tag_name") titles <- purrr::map_chr(rd, extract_title) concepts <- unname(purrr::map(rd, extract_tag, "tag_concept")) keywords <- unname(purrr::map(rd, extract_tag, "tag_keyword")) internal <- purrr::map_lgl(keywords, ~ "internal" %in% .) source <- purrr::map(rd, extract_source) lifecycle <- unname(purrr::map(rd, extract_lifecycle)) file_in <- names(rd) file_out <- rd_output_path(file_in) funs <- purrr::map(rd, topic_funs) tibble::tibble( name = names, file_in = file_in, file_out = file_out, alias = aliases, funs = funs, title = titles, rd = rd, source = source, keywords = keywords, concepts = concepts, internal = internal, lifecycle = lifecycle ) } rd_output_path <- function(x) { x <- gsub("\\.Rd$", ".html", x) x[x == "index.html"] <- "index-topic.html" x } package_rd <- function(path = ".") { man_path <- path(path, "man") if (!dir_exists(man_path)) { return(set_names(list(), character())) } rd <- dir_ls(man_path, regexp = "\\.[Rr]d$", type = "file") names(rd) <- path_file(rd) lapply(rd, rd_file, pkg_path = path) } extract_tag <- function(x, tag) { purrr::map_chr(purrr::keep(x, inherits, tag), c(1, 1)) } extract_title <- function(x) { title <- purrr::detect(x, inherits, "tag_title") str_squish(flatten_text(title, auto_link = FALSE)) } extract_source <- function(x) { nl <- purrr::map_lgl(x, inherits, "TEXT") & x == "\n" comment <- purrr::map_lgl(x, inherits, "COMMENT") first_comment <- cumsum(!(nl | comment)) == 0 lines <- as.character(x[first_comment]) text <- paste0(lines, collapse = "") if (!grepl("roxygen2", text)) { return(character()) } m <- gregexpr("R/[^ ]+\\.[rR]", text) regmatches(text, m)[[1]] } extract_lifecycle <- function(x) { desc <- purrr::keep(x, inherits, "tag_description") fig <- extract_figure(desc) if (!is.null(fig) && length(fig) > 0 && length(fig[[1]]) > 0) { path <- as.character(fig[[1]][[1]]) if (grepl("lifecycle", path)) { name <- gsub("lifecycle-", "", path) name <- path_ext_remove(name) # Translate the most common lifecylce names name <- switch( name, deprecated = tr_("deprecated"), superseded = tr_("superseded"), experimental = tr_("experimental"), stable = tr_("stable"), name ) return(name) } } NULL } extract_figure <- function(elements) { for (element in elements) { if (inherits(element, "tag_figure")) { return(element) } else if (inherits(element, "tag")) { child <- extract_figure(element) if (!is.null(child)) { return(child) } } } NULL } # Vignettes --------------------------------------------------------------- package_vignettes <- function(path = ".") { base <- path(path, "vignettes") if (!dir_exists(base)) { vig_path <- character() } else { vig_path <- dir_ls( base, regexp = "\\.[Rrq]md$", type = "file", recurse = TRUE ) } vig_path <- path_rel(vig_path, base) vig_path <- vig_path[!grepl("^_", path_file(vig_path))] vig_path <- vig_path[!grepl("^tutorials", path_dir(vig_path))] type <- tolower(path_ext(vig_path)) meta <- purrr::map(path(base, vig_path), article_metadata) title <- purrr::map_chr(meta, "title") desc <- purrr::map_chr(meta, "desc") ext <- purrr::map_chr(meta, "ext") # Vignettes will be written to /articles/ with path relative to vignettes/ # *except* for vignettes in vignettes/articles, which are moved up a level file_in <- path("vignettes", vig_path) file_out <- path_ext_set(vig_path, ext) file_out[!path_has_parent(file_out, "articles")] <- path( "articles", file_out[!path_has_parent(file_out, "articles")] ) check_unique_article_paths(file_in, file_out) out <- tibble::tibble( name = as.character(path_ext_remove(vig_path)), type = type, file_in = as.character(file_in), file_out = as.character(file_out), title = title, description = desc, depth = dir_depth(file_out) ) out[order(path_file(out$file_out)), ] } article_metadata <- function(path) { if (path_ext(path) == "qmd") { inspect <- quarto::quarto_inspect(path) meta <- inspect$formats[[1]]$metadata out <- list( title = meta$title %||% "UNKNOWN TITLE", desc = meta$description %||% NA_character_, ext = path_ext(inspect$formats[[1]]$pandoc$`output-file`) %||% "html" ) } else { yaml <- rmarkdown::yaml_front_matter(path) out <- list( title = yaml$title[[1]] %||% "UNKNOWN TITLE", desc = yaml$description[[1]] %||% NA_character_, ext = yaml$pkgdown$extension %||% "html" ) } if (out$ext == "pdf") { out$title <- paste0(out$title, " (PDF)") } out } find_template_config <- function( package, bs_version = NULL, error_call = caller_env() ) { if (is.null(package)) { return(list()) } config <- path_package_pkgdown( "_pkgdown.yml", package, bs_version, error_call = error_call ) if (!file_exists(config)) { return(list()) } yaml::yaml.load_file(config) %||% list() } check_unique_article_paths <- function(file_in, file_out) { if (!any(duplicated(file_out))) { return() } # Since we move vignettes/articles/* up one level, we may end up with two # vignettes destined for the same final location. We also know that if there # are conflicting final paths, they are the result of exactly two source files file_out_dup <- file_out[duplicated(file_out)] same_out_bullets <- purrr::map_chr(file_out_dup, function(f_out) { src_files <- src_path(file_in[which(file_out == f_out)]) src_files <- paste(src_files, collapse = " and ") }) names(same_out_bullets) <- rep_len("x", length(same_out_bullets)) cli::cli_abort( c( "Rendered articles must have unique names. Rename or relocate:", same_out_bullets ), call = caller_env() ) } pkgdown/R/deploy-site.R0000644000176200001440000001675014770274305014527 0ustar liggesusers#' Deploy a pkgdown site on Travis-CI to Github Pages #' #' @description #' `r lifecycle::badge('superseded')` #' #' `deploy_site_github()` was designed to deploy your site from Travis CI, #' which we no longer recommend, so this function is deprecated. There are #' two replacements: #' #' * [usethis::use_pkgdown_github_pages()] will setup a GitHub action to #' automatically build and deploy your package website to GitHub pages. #' #' * [deploy_to_branch()] can be called locally to build and deploy your #' website to any desired branch. #' #' @inheritParams build_site #' @param install Optionally, opt-out of automatic installation. This is #' necessary if the package you're documenting is a dependency of pkgdown #' @param tarball The location of the built package tarball. The default Travis #' configuration for R packages sets `PKG_TARBALL` to this path. #' @param ssh_id The private id to use, a base64 encoded content of the private #' pem file. This should _not_ be your personal private key. Instead create a #' new keypair specifically for deploying the site. The easiest way is to use #' `travis::use_travis_deploy()`. #' @param commit_message The commit message to be used for the commit. #' @param clean Clean all files from old site. #' @param verbose Print verbose output #' @param ... Additional arguments passed to [build_site()]. #' @param host The GitHub host url. #' @param repo_slug The `user/repo` slug for the repository. #' @export #' @keywords internal deploy_site_github <- function( pkg = ".", install = TRUE, tarball = Sys.getenv("PKG_TARBALL", ""), ssh_id = Sys.getenv("id_rsa", ""), commit_message = construct_commit_message(pkg), clean = FALSE, verbose = FALSE, host = "github.com", ..., repo_slug = Sys.getenv("TRAVIS_REPO_SLUG", "") ) { rlang::check_installed("openssl") if (!nzchar(tarball)) { cli::cli_abort( "No built tarball detected, please provide the location of one with {.var tarball}", call = caller_env() ) } if (!nzchar(ssh_id)) { cli::cli_abort( "No deploy key found, please setup with {.fn travis::use_travis_deploy}", call = caller_env() ) } if (!nzchar(repo_slug)) { cli::cli_abort( "No repo detected, please supply one with {.var repo_slug}", call = caller_env() ) } cli::cli_alert("Deploying site to GitHub") if (install) { cli::cli_inform("Installing package") callr::rcmd("INSTALL", tarball, show = verbose, fail_on_status = TRUE) } ssh_id_file <- "~/.ssh/id_rsa" cli::cli_inform("Setting up SSH id") cli::cli_inform("Copying private key to {.file ssh_id_file}") write_lines(rawToChar(openssl::base64_decode(ssh_id)), ssh_id_file) cli::cli_inform("Setting private key permissions to 0600") file_chmod(ssh_id_file, "0600") cli::cli_inform("Setting remote to use the ssh url") git("remote", "set-url", "origin", sprintf("git@%s:%s.git", host, repo_slug)) deploy_to_branch( pkg, commit_message = commit_message, clean = clean, branch = "gh-pages", ... ) cli::cli_inform(c(v = "Deploy completed")) } #' Build and deploy a site locally #' #' Assumes that you're in a git clone of the project, and the package is #' already installed. Use [usethis::use_pkgdown_github_pages()] to automate #' this process using GitHub actions. #' #' @param branch The git branch to deploy to #' @param remote The git remote to deploy to #' @param github_pages Is this a GitHub pages deploy. If `TRUE`, adds a `CNAME` #' file for custom domain name support, and a `.nojekyll` file to suppress #' jekyll rendering. #' @param ... Additional arguments passed to [build_site()]. #' @param subdir The sub-directory where the site should be built on the branch. #' This argument can be used to support a number of site configurations. #' For example, you could build version-specific documentation by setting #' `subdir = "v1.2.3"`; `deploy_to_branch()` will build and deploy the #' package documentation in the `v.1.2.3/` directory of your site. #' @inheritParams build_site #' @inheritParams deploy_site_github #' @export deploy_to_branch <- function( pkg = ".", commit_message = construct_commit_message(pkg), clean = TRUE, branch = "gh-pages", remote = "origin", github_pages = (branch == "gh-pages"), ..., subdir = NULL ) { dest_dir <- dir_create(file_temp()) on.exit(dir_delete(dest_dir)) if (!git_has_remote_branch(remote, branch)) { old_branch <- git_current_branch() # If no remote branch, we need to create it git("checkout", "--orphan", branch) git("rm", "-rf", "--quiet", ".") git( "commit", "--allow-empty", "-m", sprintf("Initializing %s branch", branch) ) git("push", remote, paste0("HEAD:", branch)) # checkout the previous branch git("checkout", old_branch) } # Explicitly set the branches tracked by the origin remote. # Needed if we are using a shallow clone, such as on travis-CI git("remote", "set-branches", "--add", remote, branch) git("fetch", remote, branch) github_worktree_add(dest_dir, remote, branch) on.exit(github_worktree_remove(dest_dir), add = TRUE) site_dest_dir <- if (!is.null(subdir)) { dir_create(path(dest_dir, subdir)) } else { dest_dir } pkg <- as_pkgdown(pkg, override = list(destination = site_dest_dir)) if (!is.null(subdir) && !is.null(pkg$meta$url)) { pkg$meta$url <- path(pkg$meta$url, subdir) } build_site_github_pages(pkg, ..., clean = clean) github_push(dest_dir, commit_message, remote, branch) invisible() } git_has_remote_branch <- function(remote, branch) { has_remote_branch <- git( "ls-remote", "--quiet", "--exit-code", remote, branch, echo = FALSE, echo_cmd = FALSE, error_on_status = FALSE )$status == 0 } git_current_branch <- function() { branch <- git( "rev-parse", "--abbrev-ref", "HEAD", echo = FALSE, echo_cmd = FALSE )$stdout sub("\n$", "", branch) } github_worktree_add <- function(dir, remote, branch) { cli::cli_inform("Adding worktree") git( "worktree", "add", "--track", "-B", branch, dir, paste0(remote, "/", branch) ) } github_worktree_remove <- function(dir) { cli::cli_inform("Removing worktree") git("worktree", "remove", dir) } github_push <- function(dir, commit_message, remote, branch) { # force execution before changing working directory force(commit_message) cli::cli_inform("Commiting updated site") withr::with_dir(dir, { git("add", "-A", ".") git("commit", "--allow-empty", "-m", commit_message) cli::cli_alert("Deploying to GitHub Pages") git("remote", "-v") git("push", "--force", remote, paste0("HEAD:", branch)) }) } git <- function(..., echo_cmd = TRUE, echo = TRUE, error_on_status = TRUE) { callr::run( "git", c(...), echo_cmd = echo_cmd, echo = echo, error_on_status = error_on_status ) } construct_commit_message <- function(pkg = ".", commit = ci_commit_sha()) { pkg <- as_pkgdown(pkg) cli::format_inline( "Built site for {pkg$package}@{pkg$version}: {substr(commit, 1, 7)}" ) } ci_commit_sha <- function() { env_vars <- c( # https://docs.travis-ci.com/user/environment-variables/#default-environment-variables "TRAVIS_COMMIT", # https://help.github.com/en/actions/configuring-and-managing-workflows/using-environment-variables#default-environment-variables "GITHUB_SHA" ) for (var in env_vars) { commit_sha <- Sys.getenv(var, "") if (commit_sha != "") return(commit_sha) } "" } pkgdown/R/init.R0000644000176200001440000001064414770274305013230 0ustar liggesusers#' Initialise site infrastructure #' #' @description #' `init_site()`: #' #' * creates the output directory (`docs/`), #' * generates a machine readable description of the site, used for autolinking, #' * copies CSS/JS assets and extra files, and #' * runs `build_favicons()`, if needed. #' #' Typically, you will not need to call this function directly, as all `build_*()` #' functions will run `init_site()` if needed. #' #' The only good reasons to call `init_site()` directly are the following: #' * If you add or modify a package logo. #' * If you add or modify `pkgdown/extra.scss`. #' * If you modify `template.bslib` variables in `_pkgdown.yml`. #' #' See `vignette("customise")` for the various ways you can customise the #' display of your site. #' #' # Build-ignored files #' We recommend using [usethis::use_pkgdown_github_pages()] to build-ignore `docs/` and #' `_pkgdown.yml`. If use another directory, or create the site manually, #' you'll need to add them to `.Rbuildignore` yourself. A `NOTE` about #' an unexpected file during `R CMD CHECK` is an indication you have not #' correctly ignored these files. #' #' @inheritParams build_articles #' @export init_site <- function(pkg = ".", override = list()) { # This is the only user facing function that doesn't call section_init() # because section_init() can conditionally call init_site() rstudio_save_all() cache_cli_colours() pkg <- as_pkgdown(pkg, override = override) cli::cli_rule("Initialising site") dir_create(pkg$dst_path) copy_assets(pkg) if (pkg$bs_version > 3) { build_bslib(pkg) } # Building favicons is expensive, so we hopefully only do it once, locally if (has_logo(pkg) && !has_favicons(pkg) && !on_ci()) { build_favicons(pkg) } copy_favicons(pkg) copy_logo(pkg) build_site_meta(pkg) invisible() } copy_assets <- function(pkg = ".") { pkg <- as_pkgdown(pkg) template <- config_pluck(pkg, "template") # pkgdown assets if (!identical(template$default_assets, FALSE)) { copy_asset_dir( pkg, path_pkgdown(paste0("BS", pkg$bs_version, "/", "assets")), src_root = path_pkgdown(), src_label = "/" ) } # package assets if (!is.null(template$package)) { copy_asset_dir( pkg, path_package_pkgdown("assets", template$package, pkg$bs_version), src_root = system_file(package = template$package), src_label = paste0("<", template$package, ">/") ) } # extras copy_asset_dir(pkg, "pkgdown", file_regexp = "^extra") # site assets copy_asset_dir(pkg, "pkgdown/assets") invisible() } copy_asset_dir <- function( pkg, dir, src_root = pkg$src_path, src_label = "", file_regexp = NULL ) { src_dir <- path_abs(dir, pkg$src_path) if (!file_exists(src_dir)) { return(character()) } src_paths <- dir_ls(src_dir, recurse = TRUE) src_paths <- src_paths[!is_dir(src_paths)] if (!is.null(file_regexp)) { src_paths <- src_paths[grepl(file_regexp, path_file(src_paths))] } src_paths <- src_paths[path_ext(src_paths) != "scss"] # Handled in bs_theme() dst_paths <- path(pkg$dst_path, path_rel(src_paths, src_dir)) file_copy_to( src_paths = src_paths, src_root = src_root, src_label = src_label, dst_paths = dst_paths, dst_root = pkg$dst_path ) } timestamp <- function(time = Sys.time()) { attr(time, "tzone") <- "UTC" strftime(time, "%Y-%m-%dT%H:%MZ", tz = "UTC") } # Generate site meta data file (available to website viewers) build_site_meta <- function(pkg = ".") { meta <- site_meta(pkg) # Install pkgdown.yml to ./inst if requested, install_metadata <- pkg$install_metadata %||% FALSE if (install_metadata) { path_meta <- path(pkg$src_path, "inst", "pkgdown.yml") dir_create(path_dir(path_meta)) write_yaml(meta, path_meta) } path_meta <- path(pkg$dst_path, "pkgdown.yml") write_yaml(meta, path_meta) invisible() } site_meta <- function(pkg) { article_index <- article_index(pkg) yaml <- list( pandoc = as.character(rmarkdown::pandoc_version()), pkgdown = as.character(utils::packageDescription( "pkgdown", fields = "Version" )), pkgdown_sha = utils::packageDescription("pkgdown")$GithubSHA1, articles = as.list(article_index), last_built = timestamp() ) url <- config_pluck_string(pkg, "url") if (!is.null(url)) { yaml$urls <- list( reference = paste0(url, "/reference"), article = paste0(url, "/articles") ) } print_yaml(yaml) } pkgdown/R/html-build.R0000644000176200001440000000204114770274305014316 0ustar liggesusersa <- function(text, href) { ifelse(is.na(href), text, paste0("", text, "")) } link_url <- function(text, href) { if (!is.null(href)) { paste0("", text, "") } } linkify <- function(text) { text <- escape_html(text) text <- gsub( "<doi:([^&]+)>", # DOIs with < > & are not supported "<doi:\\1>", text, ignore.case = TRUE ) text <- gsub( "<arXiv:([^&]+)>", "<arXiv:\\1>", text, ignore.case = TRUE ) text <- gsub( "<((http|ftp)[^&]+)>", # URIs with & are not supported "<\\1>", text ) text } dont_index <- function(x) { paste0("
    ", x, "
    ") } escape_html <- function(x) { x <- gsub("&", "&", x) x <- gsub("<", "<", x) x <- gsub(">", ">", x) # x <- gsub("'", "'", x) # x <- gsub("\"", """, x) x } strip_html_tags <- function(x) gsub("<.*?>", "", x) pkgdown/R/utils.R0000644000176200001440000001252015102647422013412 0ustar liggesusersup_path <- function(depth) { paste(rep.int("../", depth), collapse = "") } dir_depth <- function(x) { # length(strsplit(path, "/")[[1]]) - 1L purrr::map_int(strsplit(x, ""), function(x) sum(x == "/")) } invert_index <- function(x) { stopifnot(is.list(x)) if (length(x) == 0) { return(list()) } key <- rep(names(x), purrr::map_int(x, length)) val <- unlist(x, use.names = FALSE) split(key, val) } rstudio_save_all <- function() { if (is_installed("rstudioapi") && rstudioapi::hasFun("documentSaveAll")) { rstudioapi::documentSaveAll() } } is_syntactic <- function(x) x == make.names(x) auto_quote <- function(x) { ifelse(is_syntactic(x), x, paste0("`", x, "`")) } str_trim <- function(x) gsub("^\\s+|\\s+$", "", x) str_squish <- function(x) str_trim(gsub("\\s+", " ", x)) unwrap_purrr_error <- function(code) { withCallingHandlers( code, purrr_error_indexed = function(err) { cnd_signal(err$parent) } ) } tr_ <- function(...) { enc2utf8(gettext(..., domain = "R-pkgdown")) } # devtools metadata ------------------------------------------------------- system_file <- function(..., package) { if (is.null(devtools_meta(package))) { path(system.file(package = package), ...) } else { path(getNamespaceInfo(package, "path"), "inst", ...) } } devtools_meta <- function(x) { ns <- .getNamespace(x) ns[[".__DEVTOOLS__"]] } # CLI --------------------------------------------------------------------- dst_path <- cli::combine_ansi_styles( cli::style_bold, cli::col_cyan ) src_path <- cli::combine_ansi_styles( cli::style_bold, cli::col_green ) writing_file <- function(path, show) { path <- as.character(path) text <- dst_path(as.character(show)) cli::cli_inform( "Writing {.run [{text}](pkgdown::preview_site(path='{path}'))}" ) } modify_list <- function(x, y) { if (is.null(x)) { return(y) } else if (is.null(y)) { return(x) } utils::modifyList(x, y) } # from https://github.com/r-lib/rematch2/blob/8098bd06f251bfe0f20c0598d90fc20b741d13f8/R/package.R#L47 re_match <- function(text, pattern, perl = TRUE, ...) { stopifnot(is.character(pattern), length(pattern) == 1, !is.na(pattern)) text <- as.character(text) match <- regexpr(pattern, text, perl = perl, ...) start <- as.vector(match) length <- attr(match, "match.length") end <- start + length - 1L matchstr <- substring(text, start, end) matchstr[start == -1] <- NA_character_ res <- data.frame( .text = text, .match = matchstr ) if (!is.null(attr(match, "capture.start"))) { gstart <- attr(match, "capture.start") glength <- attr(match, "capture.length") gend <- gstart + glength - 1L groupstr <- substring(text, gstart, gend) groupstr[gstart == -1] <- NA_character_ dim(groupstr) <- dim(gstart) res <- cbind(groupstr, res) } names(res) <- c(attr(match, "capture.names"), ".text", ".match") class(res) <- c("tbl_df", "tbl", class(res)) res } # external links can't be an active item # external links start with http(s) # but are NOT an absolute URL to the pkgdown site at hand is_internal_link <- function(links, pkg) { if (is.null(pkg$meta$url)) { !grepl("https?://", links) } else { !grepl("https?://", links) | grepl(pkg$meta$url, links) } } ruler <- function(width = getOption("width")) { x <- seq_len(width) y <- rep("-", length(x)) y[x %% 5 == 0] <- "+" y[x %% 10 == 0] <- (x[x %% 10 == 0] %/% 10) %% 10 cat(y, "\n", sep = "") cat(x %% 10, "\n", sep = "") } get_section_level <- function(section) { class <- xml2::xml_attr(section, "class") level <- as.numeric(re_match(class, "level(\\d+)")[[1]]) level[is.na(level)] <- 0 level } section_id <- function(section) { h <- xml2::xml_find_first(section, ".//h1|.//h2|.//h3|.//h4|.//h5|.//h6") xml2::xml_attr(h, "id") } on_ci <- function() { isTRUE(as.logical(Sys.getenv("CI", "false"))) } # yaml ------------------------------------------------------------ print_yaml <- function(x) { structure(x, class = "print_yaml") } #' @export print.print_yaml <- function(x, ...) { cat(yaml::as.yaml(x), "\n", sep = "") } write_yaml <- function(x, path) { yaml::write_yaml( x, path, handlers = list(logical = yaml::verbatim_logical) ) } # Helpers for testing ----------------------------------------------------- xpath_xml <- function(x, xpath = NULL) { if (!is.null(xpath)) { x <- xml2::xml_find_all(x, xpath) } structure(x, class = c("pkgdown_xml", class(x))) } xpath_contents <- function(x, xpath) { x <- xml2::xml_find_all(x, xpath) contents <- xml2::xml_contents(x) if (length(contents) == 0) { NULL } else { xml2str(contents) } } xml2str <- function(x) { strings <- as.character(x, options = c("format", "no_declaration")) paste0(strings, collapse = "") } xpath_attr <- function(x, xpath, attr) { gsub( "\r", "", xml2::xml_attr(xml2::xml_find_all(x, xpath), attr), fixed = TRUE ) } xpath_text <- function(x, xpath, trim = FALSE) { xml2::xml_text(xml2::xml_find_all(x, xpath), trim = trim) } xpath_length <- function(x, xpath) { length(xml2::xml_find_all(x, xpath)) } #' @export print.pkgdown_xml <- function(x, ...) { cat(as.character(x, options = c("format", "no_declaration")), sep = "\n") invisible(x) } cli_escape <- function(x) { x <- gsub("{", "{{", x, fixed = TRUE) x <- gsub("}", "}}", x, fixed = TRUE) x } pkgdown/R/rd-data.R0000644000176200001440000000577114633374223013604 0ustar liggesusersas_data <- function(x, ...) { UseMethod("as_data") } #' @export as_data.NULL <- function(x, ...) { NULL } # Sections ---------------------------------------------------------------- parse_section <- function(x, title, ...) { text <- flatten_para(x, ...) list( title = title, contents = text ) } #' @export as_data.tag_details <- function(x, ...) { parse_section(x, tr_("Details"), ...) } #' @export as_data.tag_description <- function(x, ...) { parse_section(x, tr_("Description"), ...) } #' @export as_data.tag_references <- function(x, ...) { parse_section(x, tr_("References"), ...) } #' @export as_data.tag_source <- function(x, ...) { parse_section(x, tr_("Source"), ...) } #' @export as_data.tag_format <- function(x, ...) { parse_section(x, tr_("Format"), ...) } #' @export as_data.tag_note <- function(x, ...) { parse_section(x, tr_("Note"), ...) } #' @export as_data.tag_author <- function(x, ...) { parse_section(x, tr_("Author"), ...) } #' @export as_data.tag_seealso <- function(x, ...) { section <- parse_section(x, tr_("See also"), ...) section$contents <- dont_index(section$contents) section } #' @export as_data.tag_section <- function(x, ...) { parse_section(x[[2]], as_html(x[[1]], ...), ...) } # \arguments{} & \details{} ----------------------------------------------- # Both are like the contents of \description{} but can contain arbitrary # text outside of \item{} #' @export as_data.tag_arguments <- function(x, ...) { list( title = tr_("Arguments"), contents = describe_contents(x, ..., id_prefix = "arg-") ) } #' @export as_data.tag_value <- function(x, ...) { list( title = tr_("Value"), contents = describe_contents(x, ...) ) } describe_contents <- function(x, ..., id_prefix = NULL) { if (length(x) == 0) { return("") } # Group contiguous \items{}/whitespace into a
    ; everything else # is handled as is block_id <- integer(length(x)) block_id[[1]] <- 1 cur_block_is_dl <- inherits(x[[1]], "tag_item") for (i in seq2(2, length(x))) { is_item <- inherits(x[[i]], "tag_item") if (cur_block_is_dl) { same_type <- is_item || is_whitespace(x[[i]]) } else { same_type <- !is_item } if (same_type) { block_id[[i]] <- block_id[[i - 1]] } else { block_id[[i]] <- block_id[[i - 1]] + 1 cur_block_is_dl <- !cur_block_is_dl } } parse_block <- function(x) { is_dl <- any(purrr::map_lgl(x, inherits, "tag_item")) if (is_dl) { paste0( "
    \n", parse_descriptions(x, ..., id_prefix = id_prefix), "
    " ) } else { flatten_para(x, ...) } } blocks <- split(x, block_id) out <- purrr::map(blocks, parse_block) paste(unlist(out), collapse = "\n") } is_whitespace <- function(x) { inherits(x, "TEXT") && all(grepl("^\\s*$", x)) } # For testing value2html <- function(x) { rd <- rd_text(paste0("\\value{", x, "}"), fragment = FALSE)[[1]] html <- as_data(rd)$contents str_trim(strsplit(str_trim(html), "\n")[[1]]) } pkgdown/R/build-github.R0000644000176200001440000000315615074163153014640 0ustar liggesusers#' Build site for GitHub pages #' #' @description #' Designed to be run as part of automated workflows for deploying #' to GitHub pages. It cleans out the old site, builds the site into `dest_dir` #' adds a `.nojekyll` file to suppress rendering by Jekyll, and adds a `CNAME` #' file if needed. #' #' It is designed to be run in CI, so by default it: #' #' * Cleans out the old site. #' * Does not install the package. #' * Runs [build_site()] in process. #' #' @inheritParams build_site #' @inheritParams deploy_to_branch #' @param dest_dir Directory to build site in. #' @export build_site_github_pages <- function( pkg = ".", ..., dest_dir = "docs", clean = TRUE, install = FALSE, new_process = FALSE ) { pkg <- as_pkgdown(pkg, override = list(destination = dest_dir)) if (clean) { cli::cli_rule("Cleaning files from old site") clean_site(pkg) } build_site( pkg, preview = FALSE, install = install, new_process = new_process, ... ) build_github_pages(pkg) invisible() } build_github_pages <- function(pkg = ".") { cli::cli_rule("Extra files for GitHub pages") pkg <- as_pkgdown(pkg) # Add .nojekyll since site is static HTML write_if_different(pkg, "", ".nojekyll", check = FALSE) # Add CNAME if url present cname <- cname_url(config_pluck_string(pkg, "url")) if (is.null(cname)) { return(invisible()) } write_if_different(pkg, cname, "CNAME", check = FALSE) invisible() } cname_url <- function(url) { if (is.null(url)) { return(NULL) } pieces <- xml2::url_parse(url) if (!pieces$path %in% c("", "/")) { return(NULL) } pieces$server } pkgdown/R/tweak-homepage.R0000644000176200001440000000657415074163153015166 0ustar liggesuserstweak_homepage_html <- function( html, strip_header = FALSE, sidebar = TRUE, show_badges = TRUE, bs_version = 3, logo = NULL ) { html <- tweak_sidebar_html(html, sidebar = sidebar, show_badges = show_badges) # Always remove dummy page header header <- xml2::xml_find_all(html, ".//div[contains(@class, 'page-header')]") if (length(header) > 0) { xml2::xml_remove(header, free = TRUE) } header <- xml2::xml_find_first(html, ".//h1") if (strip_header) { page_header <- xml2::xml_remove(header, free = TRUE) } else { page_header <- xml2::xml_add_parent(header, "div", class = "page-header") } if (!is.null(logo) && bs_version > 3) { # Remove logo if added to h1 # Bare image xml2::xml_remove(xml2::xml_find_all( html, ".//h1/img[contains(@src, 'logo')]" )) # Image in link xml2::xml_remove( xml2::xml_parent( xml2::xml_find_all(html, ".//h1/a/img[contains(@src, 'logo')]") ) ) # Add back to header xml2::xml_add_sibling( page_header, "img", src = logo, class = "logo", alt = "", .where = "before" ) } invisible() } tweak_sidebar_html <- function(html, sidebar = TRUE, show_badges = TRUE) { if (!sidebar) { return(html) } # this extracts *and removes* badges from HTML badges <- badges_extract(html) dev_status_html <- xml2::xml_find_first(html, ".//div[@class='dev-status']") if (inherits(dev_status_html, "xml_missing")) { return(html) } if (!show_badges || length(badges) == 0) { xml2::xml_remove(dev_status_html) } else { list <- sidebar_section(tr_("Dev status"), badges) list_html <- xml2::xml_find_first( xml2::read_html(list, encoding = "UTF-8"), ".//div" ) xml2::xml_replace(dev_status_html, list_html) } html } # Mutates `html`, removing the badge container badges_extract <- function(html) { # First try specially named element; x <- xml2::xml_find_first(html, "//div[@id='badges']") strict <- FALSE # then try usethis-readme-like more complex structure; if (length(x) == 0) { # Find start comment, then all elements after # which are followed by the end comment. x <- xml2::xml_find_all( html, " //comment()[contains(., 'badges: start')][1] /following-sibling::*[following-sibling::comment()[contains(., 'badges: end')]] " ) } # then try usethis-readme-like paragraph; # where the badges: end comment is inside the paragraph after badges: start if (length(x) == 0) { x <- xml2::xml_find_all( html, ".//*/comment()[contains(., 'badges: start')]/following-sibling::p[1]" ) } # finally try first paragraph if (length(x) == 0) { # BS5 (main) and BS3 (div) x <- xml2::xml_find_first( html, "//main/p|//div[@class='contents col-md-9']/p" ) strict <- TRUE } # No paragraph if (length(x) == 0) { return(character()) } # If we guessed the element, # we only proceed if there is no text if (strict && any(xml2::xml_text(x, trim = TRUE) != "")) { return(character()) } # Proceed if we find image-containing links badges <- xml2::xml_find_all(x, ".//a[img]") if (length(badges) == 0) { return(character()) } xml2::xml_remove(x) as.character(badges) } badges_extract_text <- function(x) { html <- xml2::read_html(x, encoding = "UTF-8") badges_extract(html) } pkgdown/R/build-logo.R0000644000176200001440000000142114633374223014311 0ustar liggesuserscopy_logo <- function(pkg = ".") { pkg <- as_pkgdown(pkg) logo_path <- find_logo(pkg$src_path) if (!is.null(logo_path)) { file_copy_to( src_paths = logo_path, src_root = pkg$src_path, dst_paths = path(pkg$dst_path, path_file(logo_path)), dst_root = pkg$dst_path ) } } find_logo <- function(path) { path_first_existing( c( path(path, "logo.svg"), path(path, "man", "figures", "logo.svg"), path(path, "logo.png"), path(path, "man", "figures", "logo.png") ) ) } has_logo <- function(pkg) { logo_path <- find_logo(pkg$src_path) !is.null(logo_path) } logo_path <- function(pkg, depth) { path <- find_logo(pkg$src_path) if (is.null(path)) { return() } paste0(up_path(depth), path_file(path)) } pkgdown/R/config.R0000644000176200001440000001271714770274305013535 0ustar liggesusersconfig_pluck <- function(pkg, path, default = NULL) { check_string(path, allow_empty = FALSE, .internal = TRUE) where <- strsplit(path, ".", fixed = TRUE)[[1]] purrr::pluck(pkg$meta, !!!where, .default = default) } config_pluck_list <- function( pkg, path, has_names = NULL, default = NULL, call = caller_env() ) { check_string(path, allow_empty = FALSE, .internal = TRUE) x <- config_pluck(pkg, path, default) config_check_list( x, has_names = has_names, error_path = path, error_pkg = pkg, error_call = call ) } config_pluck_character <- function( pkg, path, default = character(), call = caller_env() ) { x <- config_pluck(pkg, path, default) config_check_character( x, error_path = path, error_pkg = pkg, error_call = call ) } config_pluck_string <- function( pkg, path, default = NULL, call = caller_env() ) { x <- config_pluck(pkg, path, default) config_check_string( x, error_path = path, error_pkg = pkg, error_call = call ) } config_pluck_markdown_inline <- function( pkg, path, default = NULL, call = caller_env() ) { text <- config_pluck_string(pkg, path, default, call = call) markdown_text_inline(pkg, text, error_path = path, error_call = call) } config_pluck_markdown_block <- function( pkg, path, default = NULL, call = caller_env() ) { text <- config_pluck_string(pkg, path, default, call = call) markdown_text_block(pkg, text) } config_pluck_bool <- function(pkg, path, default = NULL, call = caller_env()) { x <- config_pluck(pkg, path, default) config_check_bool( x, error_path = path, error_pkg = pkg, error_call = call ) } config_pluck_number_whole <- function( pkg, path, default = NULL, call = caller_env() ) { x <- config_pluck(pkg, path, default) config_check_number_whole( x, error_path = path, error_pkg = pkg, error_call = call ) } # checks --------------------------------------------------------------------- config_check_character <- function( x, error_pkg, error_path, error_call = caller_env() ) { if (is.character(x) || is.null(x)) { x } else if (identical(x, list())) { character() } else { config_abort_type( must_be = "a character vector", not = x, error_pkg = error_pkg, error_path = error_path, error_call = error_call ) } } config_check_string <- function( x, error_pkg, error_path, error_call = caller_env() ) { if (is_string(x) || is.null(x)) { x } else { config_abort_type( must_be = "a string", not = x, error_pkg = error_pkg, error_path = error_path, error_call = error_call ) } } config_check_bool <- function( x, error_pkg, error_path, error_call = caller_env() ) { if (is_bool(x) || is.null(x)) { x } else { config_abort_type( must_be = "true or false", not = x, error_pkg = error_pkg, error_path = error_path, error_call = error_call ) } } config_check_number_whole <- function( x, error_pkg, error_path, error_call = caller_env() ) { is_whole <- (0 == (exit_code <- .standalone_types_check_dot_call( ffi_standalone_check_number_1.0.7, x, allow_decimal = FALSE, min = NULL, max = NULL, allow_infinite = FALSE, allow_na = FALSE, allow_null = TRUE ))) if (is_whole) { x } else { config_abort_type( must_be = "a whole number", not = x, error_pkg = error_pkg, error_path = error_path, error_call = error_call ) } } config_check_list <- function( x, has_names = NULL, error_pkg, error_path, error_call = caller_env() ) { if (is_list(x) || is.null(x)) { if (!is.null(has_names) && !all(has_name(x, has_names))) { missing <- setdiff(has_names, names(x)) config_abort( error_pkg, c( "{.field {error_path}} must have {cli::qty(has_names)} component{?s} {.str {has_names}}.", "{length(missing)} missing component{?s}: {.str {missing}}." ), call = error_call ) } else { x } } else { not <- obj_type_friendly(x) config_abort( error_pkg, "{.field {error_path}} must be a list, not {not}.", call = error_call ) } } config_abort_type <- function(must_be, not, error_pkg, error_path, error_call) { not_str <- obj_type_friendly(not) config_abort( error_pkg, "{.field {error_path}} must be {must_be}, not {not_str}.", call = error_call ) } # generic error --------------------------------------------------------------- config_abort <- function( pkg, message, path = NULL, ..., call = caller_env(), .envir = caller_env() ) { message <- config_message(pkg, message, path) cli::cli_abort(message, ..., call = call, .envir = .envir) } config_warn <- function( pkg, message, path = NULL, ..., call = caller_env(), .envir = caller_env() ) { message <- config_message(pkg, message, path) cli::cli_warn(message, ..., call = call, .envir = .envir) } config_message <- function(pkg, message, path = NULL) { # Not all projects necessary have a _pkgdown.yml (#2542) path <- path %||% pkgdown_config_path(pkg) %||% "_pkgdown.yml" if (is_absolute_path(path)) { path_label <- path_rel(path, pkg$src_path) } else { path_label <- path } link <- cli::style_hyperlink(path_label, paste0("file://", path)) message[[1]] <- paste0("In ", link, ", ", message[[1]]) message } pkgdown/R/pkgdown-package.R0000644000176200001440000000116615075503625015325 0ustar liggesusers#' @keywords internal "_PACKAGE" ## usethis namespace: start #' @importFrom utils installed.packages #' @import rlang #' @import fs #' @importFrom lifecycle deprecated ## usethis namespace: end NULL release_bullets <- function() { c( "Check that [test/widget.html](https://pkgdown.r-lib.org/dev/articles/) responds to mouse clicks on 5/10/50", "Update translations with `potools::po_extract()` + `potools::po_update()`", "Use an LLM to proofread / fill in missing translations (see #2926)", "Compile po files with `potools::po_compile()`", "Update `vignette/translations.Rmd` with any new languages" ) } pkgdown/R/build-search-docs.R0000644000176200001440000002454614770274305015563 0ustar liggesusersbuild_docsearch_json <- function(pkg = ".") { pkg <- as_pkgdown(pkg) index_name <- config_pluck_string(pkg, "template.params.docsearch.index_name") if (is.null(index_name)) { return() } data <- list( index = index_name, package = pkg$package, url = config_pluck_string(pkg, "url") ) template <- find_template("config", "docsearch", ext = ".json", pkg = pkg) json <- render_template(template, data) json_path <- path(pkg$dst_path, "docsearch.json") write_if_different(pkg, json, json_path, check = FALSE) } build_sitemap <- function(pkg = ".") { pkg <- as_pkgdown(pkg) url <- paste0(config_pluck_string(pkg, "url"), "/") if (is.null(url)) { return() } cli::cli_rule("Building sitemap") if (pkg$development$in_dev && pkg$bs_version > 3) { url <- paste0(url, pkg$prefix) } urls <- paste0(url, get_site_paths(pkg)) doc <- paste0( "\n", paste0("", escape_html(urls), "\n", collapse = ""), "\n" ) write_if_different(pkg, doc, "sitemap.xml", check = FALSE) invisible() } #' Build search index #' #' @description #' Generate a JSON search index from the built site. This is used by #' [fuse.js](https://www.fusejs.io/) to provide a javascript powered search for #' BS5 powered pkgdown sites. #' #' NB: `build_search()` is called automatically by [build_site()]; you don't #' need call it yourself. This page documents how it works and its customisation #' options. #' #' # YAML config #' You can exclude some paths from the search index using `search.exclude`. #' Below we exclude the changelog from the search index: #' #' ```yaml #' search: #' exclude: ['news/index.html'] #' ``` #' # Debugging and local testing #' #' Locally (as opposed to on GitHub Pages or Netlify for instance), #' search won't work if you simply use pkgdown preview of the static files. #' You can use `servr::httw("docs")` instead. #' #' If search is not working, run `pkgdown::pkgdown_sitrep()` to eliminate #' common issues such as the absence of URL in the pkgdown configuration file #' of your package. #' #' @inheritParams build_articles #' @export #' build_search <- function(pkg = ".", override = list()) { pkg <- section_init(pkg, override = override) cli::cli_rule("Building search index") search_index <- build_search_index(pkg) jsonlite::write_json( search_index, path(pkg$dst_path, "search.json"), auto_unbox = TRUE ) } build_search_index <- function(pkg) { paths <- get_site_paths(pkg) paths <- paths[ !paths %in% c("404.html", "articles/index.html", "reference/index.html") ] # user-defined exclusions paths <- paths[!paths %in% config_pluck_character(pkg, "search.exclude")] if ("news/index.html" %in% paths) { index <- lapply( paths[paths != "news/index.html"], file_search_index, pkg = pkg ) index <- unlist(index, recursive = FALSE) index <- c(index, news_search_index("news/index.html", pkg = pkg)) } else { index <- lapply(paths, file_search_index, pkg = pkg) index <- unlist(index, recursive = FALSE) } # Make URLs absolute if possible url <- config_pluck_string(pkg, "url", default = "") fix_path <- function(x) { x$path <- sprintf("%s%s", url, x$path) x } purrr::map(index, fix_path) } news_search_index <- function(path, pkg) { html <- xml2::read_html(path(pkg$dst_path, path), encoding = "UTF-8") # Get contents minus logo node <- xml2::xml_find_all(html, ".//main") xml2::xml_remove(xml2::xml_find_first( node, ".//img[contains(@class, 'pkg-logo')]" )) sections <- xml2::xml_find_all(node, ".//*[contains(@class, 'section')]") purrr::pmap( list( sections, purrr::map_chr(sections, get_headings, depth = 4), title = purrr::map_chr(sections, get_version) ), bs4_index_data, dir = "Changelog", path = paste0("/", pkg$prefix, path) ) } file_search_index <- function(path, pkg) { html <- xml2::read_html(path(pkg$dst_path, path), encoding = "UTF-8") # Get page title title_element <- xml2::xml_find_first(html, ".//meta[@property='og:title']") title <- xml2::xml_attr(title_element, "content") # Get contents minus logo node <- xml2::xml_find_all(html, ".//main") xml2::xml_remove(xml2::xml_find_first( node, ".//img[contains(@class, 'pkg-logo')]" )) sections <- xml2::xml_find_all( node, ".//div[contains(@class, 'section')]|.//section" ) purrr::pmap( list( sections, purrr::map_chr(sections, get_headings, depth = 3), title = title ), bs4_index_data, dir = get_dir(path), path = paste0("/", pkg$prefix, path) ) } # Directory parts (where in the site) get_dir <- function(path) { dir <- path_dir(path) if (dir == ".") { return("") } paste(capitalise(unlist(path_split(dir))), collapse = " > ") } # Headings (where in the page) get_headings <- function(section, depth) { level <- get_section_level(section) if (level < depth) { return("") } headings <- purrr::map_chr( seq(depth - 1, level - 1), get_h, section = section ) paste0(headings[headings != ""], collapse = " > ") } # Function for extracting all headers get_h <- function(level, section) { parents <- xml2::xml_parents(section) if (length(parents) == 0) { return("") } parents <- parents[!is.na(xml2::xml_attr(parents, "class"))] h_section <- parents[grepl( paste0("section level", level), xml2::xml_attr(parents, "class") )] h <- xml2::xml_contents(h_section)[is_heading(xml2::xml_contents(h_section))] sub("^\\n", "", xml_text1(h)) } get_version <- function(section) { parents <- xml2::xml_parents(section) parents <- parents[!is.na(xml2::xml_attr(parents, "class"))] h_section <- parents[grepl( "section level2", xml2::xml_attr(parents, "class") )] if (length(h_section) == 0) { h <- xml2::xml_contents(section)[is_heading(xml2::xml_contents(section))] } else { h <- xml2::xml_contents(h_section)[is_heading(xml2::xml_contents( h_section ))] } sub("^\\n", "", xml_text1(h)) } # edited from https://github.com/rstudio/bookdown/blob/abd461593033294d82427139040a0a03cfa0390a/R/bs4_book.R#L518 # index ------------------------------------------------------------------- bs4_index_data <- function(node, previous_headings, title, dir, path) { # Make a copy of the node because we will remove contents from it for getting the data node_copy <- node # remove sections nested inside the current section to prevent duplicating content xml2::xml_remove(xml2::xml_find_all( node_copy, ".//*[contains(@class, 'section')]" )) # remove dont-index sections xml2::xml_remove(xml2::xml_find_all( node_copy, ".//*[contains(@class, 'dont-index')]" )) # Helpers for XPath queries # We want to find all nodes corresponding to ... but whose descendants # do not correspond to any ... otherwise we would treat some text/code twice, # e.g. the text of p nested within li. all <- function(...) { not <- sprintf( "[not(%s)]", paste0(paste0("descendant::", c(...)), collapse = "|") ) paste0(".//", c(...), not, collapse = "|") } text_xpath <- all( "p", "li", "caption", "figcaption", "dt", "dd", "blockquote", "div[contains(@class, 'line-block')]" ) code_xpath <- all("pre") code <- xml2::xml_find_all(node_copy, code_xpath) # Special case for definitions (mostly encountered in Rd files) if (xml2::xml_name(node_copy) == "dt") { # both argument name and definition text <- paste( xml_text1(node_copy), xml_text1(xml2::xml_find_first(node_copy, "following-sibling::*")), collapse = " " ) heading <- paste(xml_text1(node_copy), "(argument)") } else { # Other cases text <- xml_text1(xml2::xml_find_all(node_copy, text_xpath)) children <- xml2::xml_children(node_copy) heading_node <- children[purrr::map_lgl(children, is_heading)][1] heading <- xml_text1(heading_node) # Add heading for Usage section of Rd if (xml2::xml_attr(node_copy, "id", default = "") == "ref-usage") { heading <- "Usage" } } # If no specific heading, use the title if (nchar(heading) == 0) { heading <- title previous_headings <- "" } index_data <- list( path = path, id = section_id(node_copy), dir = dir, previous_headings = previous_headings, what = heading, title = title, text = strip_stop_words(text), code = xml_text1(code) ) if (index_data$text == "" && index_data$code == "") { return(NULL) } index_data } xml_text1 <- function(x) { trimws( gsub("(\r\n|\r|\n)", " ", paste0(trimws(xml2::xml_text(x)), collapse = " ")) ) } strip_stop_words <- function(x) { # paste(tidytext::get_stopwords()$word, collapse = "|") pattern <- "\\b(i|me|my|myself|we|our|ours|ourselves|you|your|yours|yourself|yourselves|he|him|his|himself|she|her|hers|herself|it|its|itself|they|them|their|theirs|themselves|what|which|who|whom|this|that|these|those|am|is|are|was|were|be|been|being|have|has|had|having|do|does|did|doing|would|should|could|ought|i'm|you're|he's|she's|it's|we're|they're|i've|you've|we've|they've|i'd|you'd|he'd|she'd|we'd|they'd|i'll|you'll|he'll|she'll|we'll|they'll|isn't|aren't|wasn't|weren't|hasn't|haven't|hadn't|doesn't|don't|didn't|won't|wouldn't|shan't|shouldn't|can't|cannot|couldn't|mustn't|let's|that's|who's|what's|here's|there's|when's|where's|why's|how's|a|an|the|and|but|if|or|because|as|until|while|of|at|by|for|with|about|against|between|into|through|during|before|after|above|below|to|from|up|down|in|out|on|off|over|under|again|further|then|once|here|there|when|where|why|how|all|any|both|each|few|more|most|other|some|such|no|nor|not|only|own|same|so|than|too|very|will)\\b ?" gsub(pattern, "", x, ignore.case = TRUE) } is_heading <- function(node) { xml2::xml_name(node) %in% c("h1", "h2", "h3", "h4", "h5") } capitalise <- function(string) { paste0(toupper(substring(string, 1, 1)), substring(string, 2)) } get_site_paths <- function(pkg) { paths <- dir_ls(pkg$dst_path, glob = "*.html", recurse = TRUE) paths_rel <- path_rel(paths, pkg$dst_path) # do not include dev package website in search index / sitemap paths_rel <- paths_rel[ !path_has_parent(paths_rel, pkg$development$destination) ] # do not include redirects redirects <- purrr::map_chr(data_redirects(pkg, has_url = TRUE), 1) setdiff(paths_rel, redirects) } pkgdown/R/build-article.R0000644000176200001440000002105215102647422014772 0ustar liggesusers#' @order 2 #' @export #' @rdname build_articles #' @param name Name of article to render. This should be either a path #' relative to `vignettes/` *without extension*, or `index` or `README`. #' @param new_process Build the article in a clean R process? The default, #' `TRUE`, ensures that every article is build in a fresh environment, but #' you may want to set it to `FALSE` to make debugging easier. #' @param pandoc_args Pass additional arguments to pandoc. Used for testing. build_article <- function( name, pkg = ".", lazy = FALSE, seed = 1014L, new_process = TRUE, pandoc_args = character(), override = list(), quiet = TRUE ) { pkg <- section_init(pkg, "articles", override = override) # Look up in pkg vignette data - this allows convenient automatic # specification of depth, output destination, and other parameters that # allow code sharing with building of the index. vig <- match(name, pkg$vignettes$name) if (is.na(vig)) { cli::cli_abort("Can't find article {.file {name}}") } input <- pkg$vignettes$file_in[vig] output_file <- pkg$vignettes$file_out[vig] depth <- pkg$vignettes$depth[vig] type <- pkg$vignettes$type[vig] input_path <- path_abs(input, pkg$src_path) output_path <- path_abs(output_file, pkg$dst_path) if (lazy && !out_of_date(input_path, output_path)) { return(invisible()) } if (type == "rmd") { build_rmarkdown_article( pkg = pkg, input_file = input, input_path = input_path, output_file = output_file, output_path = output_path, depth = depth, seed = seed, new_process = new_process, pandoc_args = pandoc_args, quiet = quiet ) } else { build_quarto_articles(pkg = pkg, article = name, quiet = quiet) } } build_rmarkdown_article <- function( pkg, input_file, input_path, output_file, output_path, depth, seed = NULL, new_process = TRUE, pandoc_args = character(), quiet = TRUE, call = caller_env() ) { cli::cli_inform("Reading {src_path(input_file)}") digest <- file_digest(output_path) data <- data_article(pkg, input_file, call = call) if (data$as_is) { if (identical(data$ext, "html")) { setup <- rmarkdown_setup_custom( pkg, input_path, depth = depth, data = data ) } else { setup <- list(format = NULL, options = NULL) } } else { setup <- rmarkdown_setup_pkgdown( pkg, depth = depth, data = data, pandoc_args = pandoc_args ) } local_envvar_pkgdown(pkg) local_texi2dvi_envvars(input_path) withr::local_envvar(R_CLI_NUM_COLORS = 256) args <- list( input = input_path, output_file = path_file(output_path), output_dir = path_dir(output_path), intermediates_dir = tempdir(), encoding = "UTF-8", seed = seed, output_format = setup$format, output_options = setup$options, quiet = quiet ) if (new_process) { path <- withCallingHandlers( callr::r_safe(rmarkdown_render_with_seed, args = args, show = !quiet), error = function(cnd) wrap_rmarkdown_error(cnd, input_file, call) ) } else { path <- inject(rmarkdown_render_with_seed(!!!args)) } is_html <- identical(path_ext(path)[[1]], "html") if (is_html) { local_options_link(pkg, depth = depth) update_html( path, tweak_rmarkdown_html, input_path = path_dir(input_path), pkg = pkg ) # Need re-active navbar now that we now the target path update_html(path, function(html) { activate_navbar(html, path_rel(path, pkg$dst_path), pkg) }) } if (digest != file_digest(output_path)) { writing_file(path_rel(output_path, pkg$dst_path), output_file) } if (is_html) { copy_article_images(path, input_path, output_path) check_missing_images(pkg, input_path, output_file) } invisible(path) } data_article <- function(pkg, input, call = caller_env()) { yaml <- rmarkdown::yaml_front_matter(path_abs(input, pkg$src_path)) opengraph <- check_open_graph(pkg, yaml$opengraph, input, call = call) opengraph$description <- opengraph$description %||% yaml$description list( opengraph = opengraph, pagetitle = escape_html(yaml$title), toc = yaml$toc %||% TRUE, source = repo_source(pkg, input), filename = path_file(input), as_is = isTRUE(purrr::pluck(yaml, "pkgdown", "as_is")), ext = purrr::pluck(yaml, "pkgdown", "extension", .default = "html") ) } rmarkdown_setup_custom <- function( pkg, input_path, depth = 1L, data = list(), env = caller_env() ) { template <- rmarkdown_template(pkg, depth = depth, data = data, env = env) # Override defaults & values supplied in metadata options <- list( template = template, self_contained = FALSE ) output <- rmarkdown::default_output_format(input_path) if (output$name != "rmarkdown::html_vignette") { # Force to NULL unless overridden by user options$theme <- output$options$theme } list(format = NULL, options = options) } rmarkdown_setup_pkgdown <- function( pkg, depth = 1L, data = list(), pandoc_args = character(), env = caller_env() ) { template <- rmarkdown_template(pkg, depth = depth, data = data, env = env) format <- rmarkdown::html_document( self_contained = FALSE, theme = NULL, template = template, anchor_sections = FALSE, math_method = config_math_rendering(pkg), extra_dependencies = bs_theme_deps_suppress(), pandoc_args = pandoc_args ) format$knitr$opts_chunk <- fig_opts_chunk( pkg$figures, format$knitr$opts_chunk ) # Add knitr hook to inject CSS class into plot img tags format$knitr$knit_hooks <- format$knitr$knit_hooks %||% list() format$knitr$knit_hooks$plot <- function(x, options) { # Get the default plot hook output hook_output <- knitr::hook_plot_md(x, options) # Add the fig.class to img tags if specified if (!is.null(options$fig.class)) { # Match img tags and add class attribute hook_output <- gsub( ' 0] # Feeding random text back into cli, so have to escape lines <- gsub("{", "{{", lines, fixed = TRUE) lines <- gsub("}", "}}", lines, fixed = TRUE) cli::cli_abort( c( "!" = "Failed to render {.path {input}}.", set_names(cli_escape(lines), "x") ), parent = cnd$parent %||% cnd, trace = cnd$parent$trace, call = call ) } rmarkdown_render_with_seed <- function(..., seed = NULL) { if (!is.null(seed)) { set.seed(seed) if (requireNamespace("htmlwidgets", quietly = TRUE)) { htmlwidgets::setWidgetIdSeed(seed) } } # Ensure paths from output are not made relative to input # https://github.com/yihui/knitr/issues/2171 options(knitr.graphics.rel_path = FALSE) rmarkdown::render(envir = globalenv(), ...) } pkgdown/R/build.R0000644000176200001440000003644515100735002013353 0ustar liggesusers#' Build a complete pkgdown website #' #' @description #' `build_site()` is a convenient wrapper around six functions: #' #' * [init_site()] #' * [build_home()] #' * [build_reference()] #' * [build_articles()] #' * [build_tutorials()] #' * [build_news()] #' * [build_redirects()] #' * [build_llm_docs()] #' #' See the documentation for the each function to learn how to control #' that aspect of the site. This page documents options that affect the #' whole site. #' #' # General config #' * `destination` controls where the site will be generated, defaulting to #' `docs/`. Paths are relative to the package root. #' #' * `url` is optional, but strongly recommended. #' #' ```yaml #' url: https://pkgdown.r-lib.org #' ``` #' #' It specifies where the site will be published and is used to allow other #' pkgdown sites to link to your site when needed (`vignette("linking")`), #' generate a `sitemap.xml`, automatically generate a `CNAME` when #' [deploying to github][build_site_github_pages()], generate the metadata needed #' rich social "media cards" (`vignette("metadata")`), and more. #' #' * `title` overrides the default site title, which is the package name. #' It's used in the page title and default navbar. #' #' # Navbar and footer #' #' The `navbar` and `footer` fields control the appearance of the navbar #' footer which appear on every page. Learn more about these fields in #' `vignette("customise")`. #' #' # Development mode #' The `development` field allows you to generate different sites for the #' development and released versions of your package. To use it, you first #' need to set the development `mode`: #' #' ```yaml #' development: #' mode: auto #' ``` #' #' ### Setting development mode #' #' The development `mode` of a site controls where the built site is placed #' and how it is styled (i.e. the colour of the package version in the #' navbar, the version tooltip), and whether or not the site is indexed by #' search engines. There are four possible modes: #' #' * **automatic** (`mode: auto`): determines the mode based on the version: #' #' * `0.0.0.9000` (`0.0.0.*`): unreleased. #' * four version components: development. #' * everything else -> release. #' #' * **release** (`mode: release`), the default. Site is written to `docs/` #' and styled like a released package, even if the content is for an #' unreleased or development version. Version in navbar gets the default #' colouring. Development badges are not shown in the sidebar #' (see `?build_home`). #' #' * **development** (`mode: devel`). Site is written to `docs/dev/`. #' The navbar version gets a "danger" class and a tooltip stating these are #' docs for an in-development version of the package. The `noindex` meta tag #' is used to ensure that these packages are not indexed by search engines. #' Development badges are shown in the sidebar (see `?build_home`). #' #' * **unreleased** (`mode: unreleased`). Site is written to `docs/`. #' Version in navbar gets the "danger" class, and a message indicating the #' package is not yet on CRAN. #' Development badges are shown in the sidebar (see `?build_home`). #' #' Use `mode: auto` if you want both a released and a dev site, and #' `mode: release` if you just want a single site. It is very rare that you #' will need either devel or unreleased modes. #' #' You can override the mode specified in the `_pkgdown.yml` by setting #' by setting `PKGDOWN_DEV_MODE` to `devel` or `release`. #' #' ### Selective HTML #' #' You can selectively show HTML only on the devel or release site by adding #' class `pkgdown-devel` or `pkgdown-release`. This is most easily accessed #' from `.Rmd` files where you can use pandoc's `
    ` syntax to control #' where a block of markdown will display. For example, you can use the #' following markdown in your README to only show GitHub install instructions #' on the development version of your site: #' #' ```md #' ::: {.pkgdown-devel} #' You can install the development version of pkgdown from GitHub with: #' `remotes::install_github("r-lib/pkgdown")` #' ::: #' ``` #' #' You can use a similar technique to control where badges are displayed. #' This markdown show the CRAN status badge on the site for the released #' package and the GitHub check status for the development package: #' #' ```md #' [![CRAN Status](https://www.r-pkg.org/badges/version/pkgdown)] #' (https://cran.r-project.org/package=pkgdown){.pkgdown-release} #' [![R-CMD-check](https://github.com/r-lib/pkgdown/workflows/R-CMD-check/badge.svg)] #' (https://github.com/r-lib/pkgdown/actions){.pkgdown-devel} #' ``` #' #' ### Other options #' #' There are three other options that you can control: #' #' ```yaml #' development: #' destination: dev #' version_label: danger #' version_tooltip: "Custom message here" #' ``` #' #' `destination` allows you to override the default subdirectory used for the #' development site; it defaults to `dev/`. `version_label` allows you to #' override the style used for development (and unreleased) versions of the #' package. It defaults to "danger", but you can set to "default", "info", or #' "warning" instead. (The precise colours are determined by your bootstrap #' theme, but become progressively more eye catching as you go from default #' to danger). Finally, you can choose to override the default tooltip with #' `version_tooltip`. #' #' # Template #' The `template` field is mostly used to control the appearance of the site. #' See `vignette("customise")` for details. But it's also used to control #' #' ## Other aspects #' #' There are a few other `template` fields that control other aspects of the #' site: #' #' * `noindex: true` will suppress indexing of your pages by search engines: #' #' ```yaml #' template: #' params: #' noindex: true #' ``` #' #' * `google_site_verification` allows you to verify your site with google: #' #' ```yaml #' template: #' params: #' google_site_verification: _nn6ile-a6x6lctOW #' ``` #' #' * `trailing_slash_redirect: true` will automatically redirect #' `your-package-url.com` to `your-package-url.com/`, using a JS script #' added to the `` of the home page. This is useful in certain #' redirect scenarios. #' #' ```yaml #' template: #' trailing_slash_redirect: true #' ``` #' #' ## Analytics #' #' To capture usage of your site with a web analytics tool, you can make #' use of the `includes` field to add the special HTML they need. This HTML #' is typically placed `in_header` (actually in the ``), `before_body`, #' or `after_body`. #' You can learn more about how includes work in pkgdown at #' . #' #' I include a few examples of popular analytics platforms below, but we #' recommend getting the HTML directly from the tool: #' #' * [plausible.io](https://plausible.io): #' #' ```yaml #' template: #' includes: #' in_header: | #' #' ``` #' #' * [Google analytics](https://analytics.google.com/analytics/web/): #' #' ```yaml #' template: #' includes: #' in_header: | #' #' #' #' #' ``` #' * [GoatCounter](https://www.goatcounter.com): #' #' ```yaml #' template: #' includes: #' after_body: > #' #' ``` #' #' # Source repository #' #' Use the `repo` field to override pkgdown's automatically discovery #' of your source repository. This is used in the navbar, on the homepage, #' in articles and reference topics, and in the changelog (to link to issue #' numbers and user names). pkgdown can automatically figure out the necessary #' URLs if you link to a GitHub, GitLab or Codeberg repo in your `BugReports` #' or `URL` field. #' #' Otherwise, you can supply your own in the `repo` field: #' #' ```yaml #' repo: #' url: #' home: https://github.com/r-lib/pkgdown/ #' source: https://github.com/r-lib/pkgdown/blob/HEAD/ #' issue: https://github.com/r-lib/pkgdown/issues/ #' user: https://github.com/ #' ``` #' #' * `home`: path to package home on source code repository. #' * `source`: path to source of individual file in default branch #' (more on that below). #' * `issue`: path to individual issue. #' * `user`: path to user. #' #' The varying components (e.g. path, issue number, user name) are pasted on #' the end of these URLs so they should have trailing `/`s. #' #' When creating the link to a package source, we have to link to a specific #' branch. The default behaviour is to use current branch when in GitHub #' actions and `HEAD` otherwise. You can overide this default with #' `repo.branch`: #' #' ```yaml #' repo: #' branch: devel #' ``` #' #' pkgdown can automatically link to Jira issues as well if specify both a #' custom `issue` URL as well Jira project names to auto-link in #' `jira_projects`. You can specify as many projects as you would like: #' #' ```yaml #' repo: #' jira_projects: [this_project, another_project] #' url: #' issue: https://jira.organisation.com/jira/browse/ #' ``` #' #' # Deployment (`deploy`) #' There is a single `deploy` field #' #' * `install_metadata` allows you to install package index metadata into #' the package itself. Normally this metadata is made available on the #' published site; installing it into your package means that it's #' available for autolinking even if your website is not reachable at build #' time (e.g. because behind a firewall or requires auth). #' #' ```yaml #' deploy: #' install_metadata: true #' ``` #' @inheritParams build_articles #' @inheritParams build_reference #' @param lazy If `TRUE`, will only rebuild articles and reference pages #' if the source is newer than the destination. #' @param devel Use development or deployment process? #' #' If `TRUE`, uses lighter-weight process suitable for rapid #' iteration; it will run examples and vignettes in the current process, #' and will load code with `pkgload::load_all()`. #' #' If `FALSE`, will first install the package to a temporary library, #' and will run all examples and vignettes in a new process. #' #' `build_site()` defaults to `devel = FALSE` so that you get high fidelity #' outputs when you building the complete site; `build_reference()`, #' `build_home()` and friends default to `devel = TRUE` so that you can #' rapidly iterate during development. #' @param new_process If `TRUE`, will run `build_site()` in a separate process. #' This enhances reproducibility by ensuring nothing that you have loaded #' in the current process affects the build process. #' @param install If `TRUE`, will install the package in a temporary library #' so it is available for vignettes. #' @param quiet If `FALSE`, generate build messages for build functions that #' take `quiet` arguments. #' @export #' @examples #' \dontrun{ #' build_site() #' #' build_site(override = list(destination = tempdir())) #' } build_site <- function( pkg = ".", examples = TRUE, run_dont_run = FALSE, seed = 1014L, lazy = FALSE, override = list(), preview = NA, devel = FALSE, new_process = !devel, install = !devel, quiet = TRUE ) { pkg <- as_pkgdown(pkg, override = override) check_bool(devel) check_bool(new_process) check_bool(install) if (install) { withr::local_temp_libpaths() cli::cli_rule( "Installing package {.pkg {pkg$package}} into temporary library" ) # Keep source, so that e.g. pillar can show the source code # of its functions in its articles withr::with_options( list(keep.source.pkgs = TRUE, keep.parse.data.pkgs = TRUE), utils::install.packages( pkg$src_path, repos = NULL, type = "source", quiet = TRUE ) ) } if (new_process) { build_site_external( pkg = pkg, examples = examples, run_dont_run = run_dont_run, seed = seed, lazy = lazy, override = override, preview = preview, devel = devel, quiet = quiet ) } else { build_site_local( pkg = pkg, examples = examples, run_dont_run = run_dont_run, seed = seed, lazy = lazy, override = override, preview = preview, devel = devel, quiet = quiet ) } } build_site_external <- function( pkg = ".", examples = TRUE, run_dont_run = FALSE, seed = 1014L, lazy = FALSE, override = list(), preview = NA, devel = TRUE, quiet = TRUE ) { pkg <- as_pkgdown(pkg, override = override) args <- list( pkg = pkg, examples = examples, run_dont_run = run_dont_run, seed = seed, lazy = lazy, override = override, install = FALSE, preview = FALSE, new_process = FALSE, devel = devel, quiet = quiet, cli_colors = cli::num_ansi_colors(), hyperlinks = cli::ansi_has_hyperlink_support() ) callr::r( function(..., cli_colors, hyperlinks) { options( cli.num_colors = cli_colors, cli.hyperlink = hyperlinks, cli.hyperlink_run = hyperlinks ) pkgdown::build_site(...) }, args = args, show = TRUE ) cli::cli_rule( "Finished building pkgdown site for package {.pkg {pkg$package}}" ) preview_site(pkg, preview = preview) invisible() } build_site_local <- function( pkg = ".", examples = TRUE, run_dont_run = FALSE, seed = 1014L, lazy = FALSE, override = list(), preview = NA, devel = TRUE, quiet = TRUE ) { pkg <- section_init(pkg, override = override) cli::cli_rule("Building pkgdown site for package {.pkg {pkg$package}}") cli::cli_inform("Reading from: {src_path(path_abs(pkg$src_path))}") cli::cli_inform("Writing to: {dst_path(path_abs(pkg$dst_path))}") pkgdown_sitrep(pkg) if (!lazy) { # Only force init_site() if `!lazy` # if site is not initialized, it will be in build_home() init_site(pkg, override) } build_home(pkg, override = override, quiet = quiet, preview = FALSE) build_reference( pkg, lazy = lazy, examples = examples, run_dont_run = run_dont_run, seed = seed, override = override, preview = FALSE, devel = devel ) build_articles( pkg, lazy = lazy, override = override, quiet = quiet, preview = FALSE ) build_tutorials(pkg, override = override, preview = FALSE) build_news(pkg, override = override, preview = FALSE) build_sitemap(pkg) if (pkg$bs_version > 3) { build_llm_docs(pkg) } build_redirects(pkg, override = override) if (pkg$bs_version == 3) { build_docsearch_json(pkg) } else { build_search(pkg, override = override) } check_built_site(pkg) cli::cli_rule( "Finished building pkgdown site for package {.pkg {pkg$package}}" ) preview_site(pkg, preview = preview) } pkgdown/R/build-home-authors.R0000644000176200001440000002015615074163153015770 0ustar liggesusersbuild_citation_authors <- function(pkg = ".") { pkg <- as_pkgdown(pkg) source <- if (has_citation(pkg$src_path)) { repo_source(pkg, "inst/CITATION") } else { repo_source(pkg, "DESCRIPTION") } authors <- data_authors(pkg) data <- list( pagetitle = tr_("Authors and Citation"), citations = data_citations(pkg), authors = unname(authors$all), inst = authors$inst, before = authors$before, after = authors$after, source = source ) render_page(pkg, "citation-authors", data, "authors.html") } data_authors <- function( pkg = ".", roles = default_roles(), call = caller_env() ) { pkg <- as_pkgdown(pkg) author_info <- config_pluck_list( pkg, "authors", default = list(), call = call ) inst_path <- path(pkg$src_path, "inst", "AUTHORS") if (file_exists(inst_path)) { inst <- paste(read_lines(inst_path), collapse = "\n") } else { inst <- NULL } authors_all <- pkg_authors(pkg) authors_main <- pkg_authors(pkg, roles) all <- purrr::map(authors_all, author_list, author_info, pkg = pkg) main <- purrr::map(authors_main, author_list, author_info, pkg = pkg) more_authors <- length(main) != length(all) comments <- purrr::compact(purrr::map(all, "comment")) print_yaml(list( all = all, main = main, inst = inst, needs_page = more_authors || length(comments) > 0 || !is.null(inst), before = config_pluck_markdown_block(pkg, "authors.before", call = call), after = config_pluck_markdown_block(pkg, "authors.after", call = call) )) } default_roles <- function() { c("aut", "cre", "fnd") } pkg_authors <- function(pkg, role = NULL) { if (pkg$desc$has_fields("Authors@R")) { authors <- unclass(pkg$desc$get_authors()) } else { # Just show maintainer authors <- unclass(utils::as.person(pkg$desc$get_maintainer())) authors[[1]]$role <- "cre" } if (is.null(role)) { authors } else { purrr::keep(authors, ~ any(.$role %in% role)) } } data_home_sidebar_authors <- function(pkg = ".", call = caller_env()) { pkg <- as_pkgdown(pkg) config_pluck_list(pkg, "authors.sidebar") roles <- config_pluck_character( pkg, "authors.sidebar.roles", default = default_roles(), call = call ) data <- data_authors(pkg, roles) authors <- purrr::map_chr(data$main, author_desc, comment = FALSE) before <- config_pluck_markdown_inline( pkg, "authors.sidebar.before", call = call ) after <- config_pluck_markdown_inline( pkg, "authors.sidebar.after", call = call ) bullets <- c(before, authors, after) if (data$needs_page) { bullets <- c(bullets, a(tr_("More about authors..."), "authors.html")) } sidebar_section(tr_("Developers"), bullets) } author_name <- function(x, authors, pkg) { name <- format_author_name(x$given, x$family) if (!(name %in% names(authors))) { return(name) } author <- authors[[name]] if (!is.null(author$html)) { error_path <- paste0("authors.", name, ".html") name <- markdown_text_inline(pkg, author$html, error_path = error_path) } if (is.null(author$href)) { name } else { a(name, author$href) } } format_author_name <- function(given, family) { given <- paste(given, collapse = " ") if (is.null(family)) { given } else { paste0(given, " ", family) } } author_list <- function(x, authors_info = NULL, comment = FALSE, pkg = ".") { name <- author_name(x, authors_info, pkg = pkg) roles <- paste0(role_lookup(x$role), collapse = ", ") substr(roles, 1, 1) <- toupper(substr(roles, 1, 1)) orcid <- purrr::pluck(x$comment, "ORCID") x$comment <- remove_orcid(x$comment) ror <- purrr::pluck(x$comment, "ROR") x$comment <- remove_ror(x$comment) list( name = name, roles = roles, comment = linkify(x$comment), orcid = orcid_link(orcid), ror = ror_link(ror) ) } author_desc <- function(x, comment = TRUE) { paste( x$name, "
    \n", x$roles, "", if (!is.null(x$orcid)) { x$orcid }, if (!is.null(x$ror)) { x$ror }, if (comment && !is.null(x$comment) && length(x$comment) != 0) { paste0("
    \n(", linkify(x$comment), ")") } ) } orcid_link <- function(orcid) { if (is.null(orcid)) { return(NULL) } paste0( "", "" ) } ror_link <- function(ror) { if (is.null(ror)) { return(NULL) } paste0( "", "ROR" ) } # Derived from: # db <- utils:::MARC_relator_db # db <- db[db$usage != "",] # dput(setNames(tolower(db$term), db$code)) # # and replace creater with maintainer role_lookup <- function(abbr) { # CRAN roles are translated roles <- c( aut = tr_("author"), com = tr_("compiler"), ctr = tr_("contractor"), ctb = tr_("contributor"), cph = tr_("copyright holder"), cre = tr_("maintainer"), dtc = tr_("data contributor"), fnd = tr_("funder"), rev = tr_("reviewer"), ths = tr_("thesis advisor"), trl = tr_("translator") ) # Other roles are left as is marc_db <- getNamespace("utils")$MARC_relator_db extra <- setdiff(marc_db$code, names(roles)) roles[extra] <- tolower(marc_db$term[match(extra, marc_db$code)]) out <- unname(roles[abbr]) if (any(is.na(out))) { missing <- abbr[is.na(out)] cli::cli_warn("Unknown MARC role abbreviation{?s}: {.field {missing}}") out[is.na(out)] <- abbr[is.na(out)] } out } # citation --------------------------------------------------------------------- has_citation <- function(path = ".") { file_exists(path(path, 'inst/CITATION')) } create_citation_meta <- function(path) { path <- path(path, "DESCRIPTION") dcf <- read.dcf(path) desc <- as.list(dcf[1, ]) if (!is.null(desc$Encoding)) { desc <- lapply(desc, iconv, from = desc$Encoding, to = "UTF-8") } else { desc$Encoding <- "UTF-8" } if (!is.null(desc$Title)) { desc$Title <- str_squish(desc$Title) } desc } read_citation <- function(path = ".") { if (!has_citation(path)) { return(character()) } meta <- create_citation_meta(path) cit_path <- path(path, 'inst/CITATION') utils::readCitationFile(cit_path, meta = meta) } data_home_sidebar_citation <- function(pkg = ".") { pkg <- as_pkgdown(pkg) sidebar_section( heading = tr_("Citation"), bullets = a(sprintf(tr_("Citing %s"), pkg$package), "authors.html#citation") ) } data_citations <- function(pkg = ".") { pkg <- as_pkgdown(pkg) if (has_citation(pkg$src_path)) { return(citation_provided(pkg$src_path)) } citation_auto(pkg) } citation_provided <- function(src_path) { provided_citation <- read_citation(src_path) text_version <- format(provided_citation, style = "textVersion") cit <- list( html = ifelse( text_version == "", format(provided_citation, style = "html"), paste0("

    ", escape_html(text_version), "

    ") ), bibtex = format(provided_citation, style = "bibtex") ) purrr::transpose(cit) } citation_auto <- function(pkg) { desc <- read_desc(pkg$src_path) cit_info <- as.list(desc$get(desc$fields())) # utils::packageDescription( # pkg$package, # lib.loc = path_dir(pkg$src_path) # ) # browser() # C cit_info$`Date/Publication` <- cit_info$`Date/Publication` %||% Sys.time() if (!is.null(cit_info$Title)) { cit_info$Title <- str_squish(cit_info$Title) } cit <- utils::citation(auto = cit_info) list( html = format(cit, style = "html"), bibtex = format(cit, style = "bibtex") ) } # helpers ------------------------------------------------------------------------- # Not strictly necessary, but produces a simpler data structure testing remove_orcid <- function(x) { out <- x[names2(x) != "ORCID"] if (all(names(out) == "")) { names(out) <- NULL } out } remove_ror <- function(x) { out <- x[names2(x) != "ROR"] if (all(names(out) == "")) { names(out) <- NULL } out } pkgdown/R/template.R0000644000176200001440000000170514633374223014074 0ustar liggesusers#' Generate YAML templates #' #' Use these function to generate the default YAML that pkgdown uses for #' the different parts of `_pkgdown.yml`. This are useful starting #' points if you want to customise your site. #' #' @param path Path to package root #' @rdname templates #' @examples #' \dontrun{ #' pkgdown::template_navbar() #' } #' #' @export template_navbar <- function(path = ".") { pkg <- as_pkgdown(path) print_yaml(list( navbar = list( structure = navbar_structure(), components = navbar_components(pkg) ) )) } #' @rdname templates #' @examples #' \dontrun{ #' pkgdown::template_reference() #' } #' #' @export template_reference <- function(path = ".") { print_yaml(list(reference = default_reference_index(path))) } #' @rdname templates #' @examples #' \dontrun{ #' pkgdown::template_articles() #' } #' #' @export template_articles <- function(path = ".") { print_yaml(list(articles = default_articles_index(path))) } pkgdown/R/figure.R0000644000176200001440000001025415075503625013542 0ustar liggesusersfig_save <- function( plot, name, dev = "ragg::agg_png", dpi = 96L, dev.args = list(), fig.ext = "png", fig.width = 700 / 96, fig.height = NULL, fig.retina = 2L, fig.asp = 1 / 1.618, # golden ratio bg = NULL, other.parameters = list() ) { path <- paste0(name, ".", fig.ext) dev <- match_fun(dev) if (is.null(fig.height)) { fig.height <- fig.width * fig.asp } else if (is.null(fig.width)) { fig.width <- fig.height / fig.asp } width <- round(dpi * fig.width) height <- round(dpi * fig.height) has_res <- "res" %in% names(formals(dev)) if (has_res) { # raster device; units in pixels, need to rescale for retina args <- list( path, # some devices use file and some use filename width = width * fig.retina, height = height * fig.retina, res = dpi * fig.retina ) } else { # vector device; units in inches; no need to rescale args <- list( path, width = fig.width, height = fig.height ) } # NB: bg is always set to transparent here; it takes effect during # recording in highlight_examples() dev.args$bg <- NA with_device(dev, c(args, dev.args), plot) list(path = path, width = width, height = height) } fig_save_args <- function() { # Avoid having multiple copies of the default settings default <- formals(fig_save) default$plot <- NULL default$name <- NULL default <- lapply(default, eval, baseenv()) default } meta_figures <- function(pkg) { default <- fig_save_args() figures <- config_pluck_list(pkg, "figures") print_yaml(modify_list(default, figures)) } #' Get current settings for figures #' #' @description #' You will generally not need to use this function unless you are handling #' custom plot output. #' #' Packages needing custom parameters should ask users to place them within #' the `other.parameters` entry under the package name, e.g. #' ``` #' figures: #' other.parameters: #' rgl: #' fig.asp: 1 #' ``` #' #' @return #' A list containing the entries from the `figures` field in `_pkgdown.yml` #' (see [build_reference()]), with default values added. Computed `width` and #' `height` values (in pixels) are also included. #' @export #' @keywords internal fig_settings <- function() { result <- fig_save_args() # The context might not be initialized. settings <- tryCatch(context_get("figures"), error = function(e) NULL) result[names(settings)] <- settings if (is.null(result$fig.height)) { result$fig.height <- result$fig.width * result$fig.asp } else if (is.null(result$fig.width)) { result$fig.width <- result$fig.height / result$fig.asp } result } with_device <- function(dev, dev.args, plot) { do.call(dev, dev.args) on.exit(grDevices::dev.off()) print(plot) } fig_opts_chunk <- function(figures, default) { figures$dev <- fun_name(figures$dev) # fig.asp beats fig.height in knitr, so if it's provided only use # it to override the default height if (!is.null(figures$fig.asp) && is.null(figures$fig.height)) { figures$fig.height <- figures$fig.width * figures$fig.asp figures$fig.asp <- NULL } # Copy background into dev.args figures$dev.args <- figures$dev.args %||% list() figures$dev.args$bg <- figures$bg %||% NA # Default figure class for rendered images # Same class as added by downlit figures$fig.class <- figures$fig.class %||% "r-plt" modify_list(default, figures) } # Find graphics device ---------------------------------------------------- match_fun <- function(x) { if (is.function(x)) { x } else if (is.character(x) && length(x) == 1) { e <- parse_expr(x) f <- eval(e, globalenv()) if (!is.function(f)) { cli::cli_abort( "{.var x} must evaluate to a function", call = caller_env() ) } f } else { cli::cli_abort("{.var x} must be a function or string", call = caller_env()) } } # knitr only takes a function name - user will need to load package fun_name <- function(x) { if (x == "ragg::agg_png") { return("ragg_png") } expr <- parse_expr(x) if (is_symbol(expr)) { x } else if (is_call(expr, "::")) { as.character(expr[[3]]) } else { cli::cli_abort("Unknown input", call = caller_env()) } } pkgdown/R/utils-io.R0000644000176200001440000000136215074163153014023 0ustar liggesusers# Reading ----------------------------------------------------------------- read_file <- function(path) { lines <- read_lines(path) paste0(lines, "\n", collapse = "") } # Inspired by roxygen2 utils-io.R (https://github.com/klutometis/roxygen/) -------- read_lines <- function(path, n = -1L) { base::readLines(path, n = n, encoding = "UTF-8", warn = FALSE) # nolint } write_lines <- function(text, path) { base::writeLines(enc2utf8(text), path, useBytes = TRUE) # nolint } # Other ------------------------------------------------------------------- file_equal <- function(src, dst) { if (!file_exists(dst)) { return(FALSE) } src_hash <- rlang::hash_file(src) dst_hash <- rlang::hash_file(dst) identical(src_hash, dst_hash) } pkgdown/R/topics-external.R0000644000176200001440000000266414770274305015411 0ustar liggesusersext_topics <- function(match_strings) { pieces <- strsplit(match_strings, "::", fixed = TRUE) pkg <- purrr::map_chr(pieces, 1) fun <- sub("\\(\\)$", "", purrr::map_chr(pieces, 2)) unwrap_purrr_error( ext_rd <- purrr::map2(pkg, fun, get_rd_from_help) ) ext_title <- purrr::map_chr(ext_rd, extract_title) ext_href <- purrr::map2_chr(fun, pkg, downlit::href_topic) ext_funs <- purrr::map(ext_rd, topic_funs) tibble::tibble( name = match_strings, file_in = NA_character_, file_out = ext_href, alias = list(character()), # used to find icons, funs = ext_funs, # used list alternative names title = sprintf("%s (from %s)", ext_title, pkg), rd = list(character()), source = NA_character_, keywords = list(character()), # used for has_keyword() concepts = list(character()), # used for has_concept() internal = FALSE, lifecycle = list(NULL) # used for has_lifecycle ) } # Adapted from roxygen2::get_rd_from_help get_rd_from_help <- function(package, alias) { call <- quote(build_reference_index()) check_installed(package, "as it's used in the reference index.", call = call) help <- utils::help((alias), (package)) if (length(help) == 0) { fun <- paste0(package, "::", alias) cli::cli_abort( "Could not find documentation for {.fn {fun}}.", call = call ) return() } out <- get(".getHelpFile", envir = asNamespace("utils"))(help) set_classes(out) } pkgdown/R/clean.R0000644000176200001440000000336515074163153013345 0ustar liggesusers#' Clean site #' #' Delete all files in `docs/` (except for `CNAME`). #' #' @param quiet If `TRUE`, suppresses a message. #' @param force If `TRUE`, delete contents of `docs` even if it is not a pkgdown site. #' @inheritParams build_site #' @rdname clean #' @export clean_site <- function(pkg = ".", quiet = FALSE, force = FALSE) { pkg <- as_pkgdown(pkg) if (!quiet) { cli::cli_inform( "Cleaning {.pkg {pkg$package}} pkgdown docs from {.path {pkg$dst_path}}" ) } if (!dir_exists(pkg$dst_path)) { return(invisible()) } top_level <- dest_files(pkg) if (length(top_level) > 0 && !force) { check_dest_is_pkgdown(pkg) } is_dir <- is_dir(top_level) dir_delete(top_level[is_dir]) file_delete(top_level[!is_dir]) invisible(TRUE) } #' Clean cache #' #' Delete all files in the pkgdown cache directory. #' #' @rdname clean #' @export clean_cache <- function(pkg = ".", quiet = FALSE) { pkg <- as_pkgdown(pkg) cache_path <- tools::R_user_dir("pkgdown", "cache") if (dir_exists(cache_path)) { if (!quiet) { cli::cli_inform( "Cleaning {.pkg {pkg$package}} cache files from {.path {cache_path}}" ) } dir_delete(cache_path) } invisible(TRUE) } check_dest_is_pkgdown <- function(pkg) { if (file_exists(path(pkg$dst_path, "pkgdown.yml"))) { return() } cli::cli_abort(c( "{.file {pkg$dst_path}} is non-empty and not built by pkgdown", "!" = "Make sure it contains no important information \\ and use {.run pkgdown::clean_site(force = TRUE)} to delete its contents." )) } dest_files <- function(pkg) { if (!dir_exists(pkg$dst_path)) { character() } else { top_level <- dir_ls(pkg$dst_path) top_level[!path_file(top_level) %in% c("CNAME", "dev")] } } pkgdown/R/build-tutorials.R0000644000176200001440000000742114770274305015407 0ustar liggesusers#' Build tutorials section #' #' learnr tutorials must be hosted elsewhere as they require an #' R execution engine. Currently, pkgdown will not build or publish tutorials #' for you, but makes it easy to embed (using `

    pkgdown/inst/BS3/templates/header.html0000644000176200001440000000000014134110164017364 0ustar liggesuserspkgdown/inst/BS3/templates/content-citation-authors.html0000644000176200001440000000143414633374223023131 0ustar liggesusers
    {{{before}}}
      {{#authors}}
    • {{{name}}}. {{{roles}}}. {{{orcid}}} {{#comment}}
      {{{.}}}{{/comment}}

    • {{/authors}}
    {{{after}}}

    {{#translate}}{{citation}}{{/translate}}

    {{#source}}{{{.}}}{{/source}}
    {{#citations}} {{{html}}}
    {{bibtex}}
    {{/citations}}
    pkgdown/inst/BS3/templates/layout.html0000644000176200001440000000074214137761366017511 0ustar liggesusers {{{ head }}} {{{ in-header }}} {{{ before-body }}}
    {{{ navbar }}} {{{ header }}}
    {{{ content }}}
    {{{ footer }}}
    {{{ docsearch }}} {{{ after-body }}} pkgdown/inst/BS3/templates/in-header.html0000644000176200001440000000005214136064064020010 0ustar liggesusers{{#includes}}{{{in_header}}}{{/includes}} pkgdown/inst/BS3/templates/content-reference-index.html0000644000176200001440000000276114633374223022703 0ustar liggesusers
    {{#has_icons}}{{/has_icons}} {{#rows}} {{#title}}{{/title}} {{#subtitle}}{{/subtitle}} {{#topics}} {{#has_icons}}{{/has_icons}} {{/topics}} {{/rows}}

    {{{title}}}

    {{{desc}}}

    {{{subtitle}}}

    {{{desc}}}

    {{#icon}}{{/icon}}

    {{#aliases}}{{{.}}} {{/aliases}}

    {{{title}}}

    pkgdown/inst/BS3/templates/footer.html0000644000176200001440000000023514134110164017444 0ustar liggesusers{{#footer}}

    {{#right}}{{{.}}}{{/right}}

    {{/footer}} pkgdown/inst/BS3/templates/navbar.html0000644000176200001440000000306114134110164017417 0ustar liggesusers{{#navbar}} {{/navbar}} pkgdown/inst/BS3/templates/layout-redirect.html0000644000176200001440000000026514633374223021301 0ustar liggesusers pkgdown/inst/BS3/templates/head.html0000644000176200001440000001365114740246027017070 0ustar liggesusers {{{pagetitle}}} • {{#site}}{{title}}{{/site}} {{#has_favicons}} {{/has_favicons}} {{#yaml}} {{#bootswatch}}{{/bootswatch}} {{^bootswatch}}{{/bootswatch}} {{/yaml}} {{#yaml}}{{#docsearch}} {{/docsearch}}{{/yaml}} {{#extra}} {{#css}}{{/css}} {{#js}}{{/js}} {{/extra}} {{#opengraph}} {{#description}} {{/description}} {{#image}} {{#alt}} {{/alt}} {{/image}} {{#twitter}} {{#card}} {{/card}} {{^card}} {{/card}} {{#creator}} {{/creator}} {{#site}} {{/site}} {{/twitter}} {{/opengraph}} {{#yaml}}{{#noindex}}{{/noindex}}{{/yaml}} {{#development}}{{#in_dev}}{{/in_dev}}{{/development}} {{#yaml}}{{#google_site_verification}} {{/google_site_verification}}{{/yaml}} {{#yaml}}{{#ganalytics}} {{/ganalytics}}{{/yaml}} {{#has_trailingslash}} {{/has_trailingslash}} {{#has_deps}} {{{dependencies}}} {{/has_deps}} pkgdown/inst/BS5/0000755000176200001440000000000015102677747013311 5ustar liggesuserspkgdown/inst/BS5/assets/0000755000176200001440000000000015075503625014603 5ustar liggesuserspkgdown/inst/BS5/assets/pkgdown.js0000644000176200001440000001154415074163153016614 0ustar liggesusers/* http://gregfranko.com/blog/jquery-best-practices/ */ (function ($) { $(function () { $('nav.navbar').headroom(); Toc.init({ $nav: $("#toc"), $scope: $("main h2, main h3, main h4, main h5, main h6") }); if ($('#toc').length) { $('body').scrollspy({ target: '#toc', offset: $("nav.navbar").outerHeight() + 1 }); } // Activate popovers $('[data-bs-toggle="popover"]').popover({ container: 'body', html: true, trigger: 'focus', placement: "top", sanitize: false, }); $('[data-bs-toggle="tooltip"]').tooltip(); /* Clipboard --------------------------*/ function changeTooltipMessage(element, msg) { var tooltipOriginalTitle = element.getAttribute('data-bs-original-title'); element.setAttribute('data-bs-original-title', msg); $(element).tooltip('show'); element.setAttribute('data-bs-original-title', tooltipOriginalTitle); } if (ClipboardJS.isSupported()) { $(document).ready(function () { var copyButton = ""; $("div.sourceCode").addClass("hasCopyButton"); // Insert copy buttons: $(copyButton).prependTo(".hasCopyButton"); // Initialize tooltips: $('.btn-copy-ex').tooltip({ container: 'body' }); // Initialize clipboard: var clipboard = new ClipboardJS('[data-clipboard-copy]', { text: function (trigger) { return trigger.parentNode.textContent.replace(/\n#>[^\n]*/g, ""); } }); clipboard.on('success', function (e) { changeTooltipMessage(e.trigger, 'Copied!'); e.clearSelection(); }); clipboard.on('error', function (e) { changeTooltipMessage(e.trigger, 'Press Ctrl+C or Command+C to copy'); }); }); } /* Search marking --------------------------*/ var url = new URL(window.location.href); var toMark = url.searchParams.get("q"); var mark = new Mark("main#main"); if (toMark) { mark.mark(toMark, { accuracy: { value: "complementary", limiters: [",", ".", ":", "/"], } }); } /* Search --------------------------*/ /* Adapted from https://github.com/rstudio/bookdown/blob/2d692ba4b61f1e466c92e78fd712b0ab08c11d31/inst/resources/bs4_book/bs4_book.js#L25 */ // Initialise search index on focus var fuse; $("#search-input").focus(async function (e) { if (fuse) { return; } $(e.target).addClass("loading"); var response = await fetch($("#search-input").data("search-index")); var data = await response.json(); var options = { keys: ["what", "text", "code"], ignoreLocation: true, threshold: 0.1, includeMatches: true, includeScore: true, }; fuse = new Fuse(data, options); $(e.target).removeClass("loading"); }); // Use algolia autocomplete var options = { autoselect: true, debug: true, hint: false, minLength: 2, }; var q; async function searchFuse(query, callback) { await fuse; var items; if (!fuse) { items = []; } else { q = query; var results = fuse.search(query, { limit: 20 }); items = results .filter((x) => x.score <= 0.75) .map((x) => x.item); if (items.length === 0) { items = [{ dir: "Sorry 😿", previous_headings: "", title: "No results found.", what: "No results found.", path: window.location.href }]; } } callback(items); } $("#search-input").autocomplete(options, [ { name: "content", source: searchFuse, templates: { suggestion: (s) => { if (s.title == s.what) { return `${s.dir} >
    ${s.title}
    `; } else if (s.previous_headings == "") { return `${s.dir} >
    ${s.title}
    > ${s.what}`; } else { return `${s.dir} >
    ${s.title}
    > ${s.previous_headings} > ${s.what}`; } }, }, }, ]).on('autocomplete:selected', function (event, s) { window.location.href = s.path + "?q=" + q + "#" + s.id; }); }); })(window.jQuery || window.$) document.addEventListener('keydown', function (event) { // Check if the pressed key is '/' if (event.key === '/') { event.preventDefault(); // Prevent any default action associated with the '/' key document.getElementById('search-input').focus(); // Set focus to the search input } }); pkgdown/inst/BS5/assets/link.svg0000644000176200001440000000145214134110164016246 0ustar liggesusers pkgdown/inst/BS5/assets/lightswitch.js0000644000176200001440000000470215074163153017472 0ustar liggesusers /*! * Color mode toggler for Bootstrap's docs (https://getbootstrap.com/) * Copyright 2011-2023 The Bootstrap Authors * Licensed under the Creative Commons Attribution 3.0 Unported License. * Updates for {pkgdown} by the {bslib} authors, also licensed under CC-BY-3.0. */ const getStoredTheme = () => localStorage.getItem('theme') const setStoredTheme = theme => localStorage.setItem('theme', theme) const getPreferredTheme = () => { const storedTheme = getStoredTheme() if (storedTheme) { return storedTheme } return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light' } const setTheme = theme => { if (theme === 'auto') { document.documentElement.setAttribute('data-bs-theme', (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light')) } else { document.documentElement.setAttribute('data-bs-theme', theme) } } function bsSetupThemeToggle() { 'use strict' const showActiveTheme = (theme, focus = false) => { var activeLabel, activeIcon; document.querySelectorAll('[data-bs-theme-value]').forEach(element => { const buttonTheme = element.getAttribute('data-bs-theme-value') const isActive = buttonTheme == theme element.classList.toggle('active', isActive) element.setAttribute('aria-pressed', isActive) if (isActive) { activeLabel = element.textContent; activeIcon = element.querySelector('span').classList.value; } }) const themeSwitcher = document.querySelector('#dropdown-lightswitch') if (!themeSwitcher) { return } themeSwitcher.setAttribute('aria-label', activeLabel) themeSwitcher.querySelector('span').classList.value = activeIcon; if (focus) { themeSwitcher.focus() } } window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => { const storedTheme = getStoredTheme() if (storedTheme !== 'light' && storedTheme !== 'dark') { setTheme(getPreferredTheme()) } }) window.addEventListener('DOMContentLoaded', () => { showActiveTheme(getPreferredTheme()) document .querySelectorAll('[data-bs-theme-value]') .forEach(toggle => { toggle.addEventListener('click', () => { const theme = toggle.getAttribute('data-bs-theme-value') setTheme(theme) setStoredTheme(theme) showActiveTheme(theme, true) }) }) }) } setTheme(getPreferredTheme()); bsSetupThemeToggle(); pkgdown/inst/BS5/assets/katex-auto.js0000644000176200001440000000115515074163153017222 0ustar liggesusers// https://github.com/jgm/pandoc/blob/29fa97ab96b8e2d62d48326e1b949a71dc41f47a/src/Text/Pandoc/Writers/HTML.hs#L332-L345 document.addEventListener("DOMContentLoaded", function () { var mathElements = document.getElementsByClassName("math"); var macros = []; for (var i = 0; i < mathElements.length; i++) { var texText = mathElements[i].firstChild; if (mathElements[i].tagName == "SPAN") { katex.render(texText.data, mathElements[i], { displayMode: mathElements[i].classList.contains("display"), throwOnError: false, macros: macros, fleqn: false }); } } }); pkgdown/inst/BS5/assets/pkgdown.scss0000644000176200001440000004352415075503625017161 0ustar liggesusers/* control page width ====================================================== */ .row>main { // Ensure contents never become unreadably wide max-width: 50rem; } // break and hypenate very long words on small screens @include media-breakpoint-down(md) { .row>main { overflow-wrap: break-word; hyphens: auto; } } // Put extra space between content and navbar @include media-breakpoint-only(xl) { .container .row { justify-content: space-evenly; } } // Boost font size and give big (but not infinite) margin on sidebar @include media-breakpoint-up(xxl) { body { font-size: 18px } .col-md-3 { margin-left: 5rem; } } /* navbar =================================================================== */ // pkgdown will follow bslib navbar variables by default $navbar-bg: null !default; $navbar-light-bg: if($navbar-bg, $navbar-bg, null) !default; $navbar-dark-bg: if($navbar-bg, $navbar-bg, null) !default; $pkgdown-navbar-bg: if($navbar-light-bg, $navbar-light-bg, null) !default; $pkgdown-navbar-bg-dark: if($navbar-dark-bg, $navbar-dark-bg, null) !default; // BS navbars appears to be designed with the idea that you have a coloured // navbar that looks the same in both light and dark mode. We prefer a mildly // coloured navbar that's just different enough from the body to stand out. // // Relies on CSS fallback rules .navbar { background: RGBA(var(--bs-body-color-rgb), 0.1); background: color-mix(in oklab, color-mix(in oklab, var(--bs-body-bg) 95%, var(--bs-primary)) 95%, var(--bs-body-color)); background: $pkgdown-navbar-bg; // Harmonize alignment of navbar elements (search field vs. rest) line-height: initial; } [data-bs-theme="dark"] .navbar { background: $pkgdown-navbar-bg-dark; } // make both the active nav and the hovered nav more clear by mixing the // background colour with the body and primary colours respectively .nav-item .nav-link { @include border-radius($border-radius); } .nav-item.active .nav-link { background: RGBA(var(--bs-body-color-rgb), 0.1); } .nav-item .nav-link:hover { background: RGBA(var(--bs-primary-rgb), 0.1); } // Align baselines of package name, version, and nav items .navbar>.container { align-items: baseline; -webkit-align-items: baseline; } // Make search a little narrower than the default input[type="search"] { width: 12rem; } [aria-labelledby=dropdown-lightswitch] span.fa { opacity: 0.5; } // When navbar is a dropdown: @include media-breakpoint-down(lg) { // Make search and sub-menus span full width .algolia-autocomplete, input[type="search"], #navbar .dropdown-menu { width: 100%; } // Allow text to wrap #navbar .dropdown-item { white-space: normal; } // Add a little margin input[type="search"] { margin: 0.25rem 0; } } // make long dropdown menus scrollable .dropdown-menu { max-height: 280px; overflow-y: auto; } /* headroom.js -------------------------------------------------------------- */ .headroom { will-change: transform; transition: transform 400ms ease; } .headroom--pinned { transform: translateY(0%); } .headroom--unpinned { transform: translateY(-100%); } // Need to adjust body components down by height of navbar so it // doesn't overlap them when visible $pkgdown-nav-height: 56px !default; .row>main, .row>aside { margin-top: $pkgdown-nav-height; } html, body { scroll-padding: $pkgdown-nav-height } // Make scrollable, sticky TOC @include media-breakpoint-up(sm) { #toc { position: sticky; top: $pkgdown-nav-height; max-height: calc(100vh - #{$pkgdown-nav-height} - 1rem); overflow-y: auto; } } /* sidebar ================================================================== */ aside { h2 { margin-top: 1.5rem; font-size: $font-size-lg; } .roles { color: RGBA(var(--bs-body-color-rgb), 0.8); } .list-unstyled li { margin-bottom: 0.5rem; } .dev-status .list-unstyled li { margin-bottom: 0.1rem; } } // Add some visual distinction between content and "sidebar" on mobile @include media-breakpoint-down(md) { // Additional specificity needed to override bootstrap width on .row > * .row>aside { margin: 0.5rem; width: calc(100vw - 1rem); background-color: RGBA(var(--bs-body-color-rgb), 0.1); border-color: var(--bs-border-color); @include border-radius($border-radius); h2:first-child { margin-top: 1rem; } } } /* table of contents -------------------------------------------------------- */ // needed for scrollspy body { position: relative; } #toc>.nav { margin-bottom: 1rem; a.nav-link { color: inherit; padding: 0.25rem 0.5rem; margin-bottom: 2px; @include border-radius($border-radius); &:hover, &:focus { background-color: RGBA(var(--bs-primary-rgb), 0.1); } &.active { background-color: RGBA(var(--bs-body-color-rgb), 0.1); } } // Nested headings are indented .nav a.nav-link { margin-left: 0.5rem; } // Only show second level if active. // Requires !important because that's how BS5 sets display: flex .nav { display: none !important; } a.active+.nav { display: flex !important; } } /* footer ================================================================== */ $pkgdown-footer-color: RGBA(var(--bs-body-color-rgb), 0.8) !default; $pkgdown-footer-bg: transparent !default; $pkgdown-footer-border-color: $border-color !default; $pkgdown-footer-border-width: $border-width !default; footer { margin: 1rem 0 1rem 0; padding-top: 1rem; font-size: .875em; border-top: $pkgdown-footer-border-width solid $pkgdown-footer-border-color; background: $pkgdown-footer-bg; color: $pkgdown-footer-color; display: flex; column-gap: 1rem; } @include media-breakpoint-down(sm) { footer { flex-direction: column; } } @include media-breakpoint-up(sm) { footer .pkgdown-footer-right { text-align: right; } } footer div { flex: 1 1 auto; } // "Sticky" footer - i.e. the footer always hugs the bottom of the viewport // even for short pages. // // Basic idea: https://philipwalton.github.io/solved-by-flexbox/demos/sticky-footer/ // Details: https://github.com/philipwalton/solved-by-flexbox/blob/master/assets/css/components/site.css // Need .container and __all parents__ have height set to 100% html, body { height: 100%; } body>.container { min-height: 100%; display: flex; flex-direction: column; } body>.container .row { flex: 1 0 auto; } /* General typography ======================================================= */ // Ensure in-page images don't run outside their container main img { max-width: 100%; height: auto; } main table { display: block; overflow: auto; } // avoid flash of invisible text + flash of unstyled text body { font-display: fallback; } // page header .page-header { border-bottom: 1px solid var(--bs-border-color); padding-bottom: 0.5rem; margin-bottom: 0.5rem; margin-top: 1.5rem; } // spacing tweaks // Use an indent for defintions rather than horitzonal space dl { margin-bottom: 0; } dd { padding-left: 1.5rem; margin-bottom: 0.25rem } // Use margins rather than size to distinguish headings h2, .h2 { font-size: 1.75rem; margin-top: 1.5rem; } h3, .h3 { font-size: 1.25rem; margin-top: 1rem; font-weight: bold; } h4, .h4 { font-size: 1.1rem; font-weight: bold; } h5, .h5 { font-size: 1rem; font-weight: bold; } summary { margin-bottom: 0.5rem; } details { margin-bottom: 1rem; } .html-widget { margin-bottom: 1rem; } // Section anchors a.anchor { display: none; // style like a footnote margin-left: 2px; vertical-align: top; width: Min(0.9em, 20px); height: Min(0.9em, 20px); background-image: url(../../link.svg); background-repeat: no-repeat; background-size: Min(0.9em, 20px) Min(0.9em, 20px); background-position: center center; } h2, h3, h4, h5, h6, dt { &:hover .anchor, &:target .anchor { display: inline-block; } } // Give targetted arguments some visual distinction dt:target, dt:target+dd { border-left: 0.25rem solid var(--bs-primary); margin-left: -0.75rem; } dt:target { padding-left: 0.5rem; } dt:target+dd { padding-left: 2rem; } // orcid badge .orcid { color: #A6CE39; margin-right: 4px; } // ror badge .ror { height: 16px; margin-right: 4px; } // activate font awesome .fab { font-family: "Font Awesome 5 Brands" !important; } // package logo img.logo { float: right; width: 100px; margin-left: 30px; } .template-home img.logo { width: 120px; } @include media-breakpoint-down(sm) { img.logo { width: 80px; } } // line up h1 border-bottom with corner of hexagon // values determined empirically @include media-breakpoint-up(sm) { .page-header { min-height: 88px } .template-home .page-header { min-height: 104px } } // line-block produced by pandoc needs margin-bottom since it doesn't // contain other tags .line-block { margin-bottom: 1rem; } // Override bootstrap defaults that make sense in page bodies, but not on // the reference index .template-reference-index { dt { font-weight: normal; } // Don't allow breaking within a function name code { word-wrap: normal; } } .icon { float: right; img { width: 40px; } } // Ensure skip link is visible if focussed a[href='#main'] { position: absolute; margin: 4px; padding: 0.75rem; background-color: var(--bs-body-bg); text-decoration: none; z-index: 2000; } .lifecycle { color: var(--bs-secondary-color); background-color: var(--bs-secondary-bg); // backup just in case we don't know the name border-radius: 5px; } .lifecycle-stable { background-color: rgb(16, 128, 1); color: var(--bs-white); } .lifecycle-superseded { background-color: rgb(7, 64, 128); color: var(--bs-white); } .lifecycle-experimental, .lifecycle-deprecated { background-color: rgb(253, 128, 8); color: var(--bs-black); } /* Footnotes ---------------------------------------------------------------- */ a.footnote-ref { cursor: pointer; } // use "Min" to trigger computation in css, not sass .popover { width: Min(100vw, 32rem); font-size: 0.9rem; box-shadow: 4px 4px 8px RGBA(var(--bs-body-color-rgb), 0.3); } .popover-body { padding: 0.75rem; } .popover-body p:last-child { margin-bottom: 0; } /* tabsets ------------------------------------------------------------------ */ .tab-content { padding: 1rem; } .tabset-pills .tab-content { border: solid 1px #e5e5e5; } // Make tab height consistent // https://observablehq.com/@rkaravia/css-trick-tabs-with-consistent-height .tab-content { display: flex; } .tab-content>.tab-pane { display: block; /* undo "display: none;" */ visibility: hidden; margin-right: -100%; width: 100%; } .tab-content>.active { visibility: visible; } /* bibliography styling ----------------------------------------------------- */ // Added in pandoc 2.11: https://github.com/jgm/pandoc-templates/commit/9904bf71 div.csl-bib-body {} div.csl-entry { clear: both; } .hanging-indent div.csl-entry { margin-left: 2em; text-indent: -2em; } div.csl-left-margin { min-width: 2em; float: left; } div.csl-right-inline { margin-left: 2em; padding-left: 1em; } div.csl-indent { margin-left: 2em; } /* code ===================================================================== */ pre, pre code { // override bootstrap deafult that causes problems in old safari + IE // https://github.com/rstudio/shiny/issues/2233 word-wrap: normal; } // Default dark mode styling does not look good for code [data-bs-theme="dark"] { pre, code { background-color: RGBA(var(--bs-body-color-rgb), 0.1); } // don't double apply transparency pre code { background: transparent; } } code { // break long functions into multiple lines overflow-wrap: break-word; } // copy button .hasCopyButton { position: relative; } .btn-copy-ex { position: absolute; right: 5px; top: 5px; visibility: hidden; } .hasCopyButton:hover button.btn-copy-ex { visibility: visible; } // Ensure there's enough space for the copy button pre { padding: 0.75rem; } // Spacing tweaks for gt table pre div.gt-table { white-space: normal; margin-top: 1rem; } // "Pop" code out of page margins on small screens to give a little more room @include media-breakpoint-down(sm) { // div.section div.sourceCode pre // prevents matching
     inside (e.g.) a 
  • div>div>pre { margin-left: calc(var(--bs-gutter-x) * -.5); margin-right: calc(var(--bs-gutter-x) * -.5); border-radius: 0; padding-left: 1rem; padding-right: 1rem; } .btn-copy-ex { right: calc(var(--bs-gutter-x) * -.5 + 5px); } } code a:any-link { color: inherit; text-decoration-color: RGBA(var(--bs-body-color-rgb), 0.6); } pre code { padding: 0; background: transparent; .error, .warning { font-weight: bolder; } } pre .img, pre .r-plt { img { margin: 5px 0; background-color: #fff; } } // low-tech plot softening in dark mode [data-bs-theme="dark"] pre img { opacity: 0.66; transition: opacity 250ms ease-in-out; &:hover, &:focus, &:active { opacity: 1; } } /* don't display links in code chunks when printing */ /* source: https://stackoverflow.com/a/10781533 */ @media print { code a:link:after, code a:visited:after { content: ""; } } a.sourceLine:hover { text-decoration: none; } /* search =================================================================== */ mark { background: linear-gradient(-100deg, RGBA(var(--bs-info-rgb), 0.2), RGBA(var(--bs-info-rgb), 0.7) 95%, RGBA(var(--bs-info-rgb), 0.1)) } // Mimic the style of the navbar dropdowns .algolia-autocomplete .aa-dropdown-menu { margin-top: 0.5rem; padding: 0.5rem 0.25rem; width: MAX(100%, 20rem); // force computation in css, not sass max-height: 50vh; overflow-y: auto; background-color: var(--bs-body-bg); border: var(--bs-border-width) solid var(--bs-border-color); @include border-radius($border-radius); .aa-suggestion { cursor: pointer; font-size: 1rem; padding: 0.5rem 0.25rem; line-height: 1.3; &:hover { background-color: var(--bs-tertiary-bg); color: var(--bs-body-color); } .search-details { text-decoration: underline; display: inline; // algolia makes it a div } } } /* Quarto specific =========================================================== */ // Selectively copied from https://github.com/quarto-dev/quarto-cli/blob/main/src/resources/formats/html/_quarto-rules.scss#L110 span.smallcaps { font-variant: small-caps; } // task-list -------------------------------------------------------------- ul.task-list { list-style: none; } ul.task-list li input[type="checkbox"] { width: 0.8em; margin: 0 0.8em 0.2em -1em; /* quarto-specific, see https://github.com/quarto-dev/quarto-cli/issues/4556 */ vertical-align: middle; } // Figure and layout -------------------------------------------------------- figure.figure { display: block; } .quarto-layout-panel { margin-bottom: 1em; } .quarto-layout-panel>figure { width: 100%; } .quarto-layout-panel>figure>figcaption, .quarto-layout-panel>.panel-caption { margin-top: 10pt; } .quarto-layout-panel>.table-caption { margin-top: 0px; } .table-caption p { margin-bottom: 0.5em; } .quarto-layout-row { display: flex; flex-direction: row; align-items: flex-start; } .quarto-layout-valign-top { align-items: flex-start; } .quarto-layout-valign-bottom { align-items: flex-end; } .quarto-layout-valign-center { align-items: center; } .quarto-layout-cell { position: relative; margin-right: 20px; } .quarto-layout-cell:last-child { margin-right: 0; } .quarto-layout-cell figure, .quarto-layout-cell>p { margin: 0.2em; } .quarto-layout-cell img { max-width: 100%; } .quarto-layout-cell .html-widget { width: 100% !important; } .quarto-layout-cell div figure p { margin: 0; } .quarto-layout-cell figure { display: block; margin-inline-start: 0; margin-inline-end: 0; } .quarto-layout-cell table { display: inline-table; } .quarto-layout-cell-subref figcaption, figure .quarto-layout-row figure figcaption { text-align: center; font-style: italic; } .quarto-figure { position: relative; margin-bottom: 1em; } .quarto-figure>figure { width: 100%; margin-bottom: 0; } .quarto-figure-left>figure>p, .quarto-figure-left>figure>div /* for mermaid and dot diagrams */ { text-align: left; } .quarto-figure-center>figure>p, .quarto-figure-center>figure>div /* for mermaid and dot diagrams */ { text-align: center; } .quarto-figure-right>figure>p, .quarto-figure-right>figure>div /* for mermaid and dot diagrams */ { text-align: right; } .quarto-figure>figure>div.cell-annotation, .quarto-figure>figure>div code { text-align: left; /* override align center for code blocks */ } figure>p:empty { display: none; } figure>p:first-child { margin-top: 0; margin-bottom: 0; } figure>figcaption.quarto-float-caption-bottom { margin-bottom: 0.5em; } figure>figcaption.quarto-float-caption-top { margin-top: 0.5em; } // mermaid --------------------------------------------------------- :root { --mermaid-bg-color: transparent; --mermaid-edge-color: var(--bs-secondary); --mermaid-fg-color: var(--bs-body-color); --mermaid-fg-color--lighter: RGBA(var(--bs-body-color-rgb), 0.9); --mermaid-fg-color--lightest: RGBA(var(--bs-body-color-rgb), 0.8); --mermaid-font-family: var(--bs-body-font-family); --mermaid-label-bg-color: var(--bs-primary); --mermaid-label-fg-color: var(--bs-body-color); --mermaid-node-bg-color: RGBA(var(--bs-primary-rgb), 0.1); --mermaid-node-fg-color: var(--bs-primary); } // auto-dark mode for rendered images ------------------------------ @mixin invert-filter { // vignette figures img.r-plt, // example figures pre .r-plt.img img, // quarto figures .cell-output-display img, .html-widget { filter: invert(100%) hue-rotate(180deg); } } [data-bs-theme="dark"] { @include invert-filter; .no-invert-dark-mode { @include invert-filter; } } pkgdown/inst/BS5/templates/0000755000176200001440000000000015100735002015260 5ustar liggesuserspkgdown/inst/BS5/templates/content-news.html0000644000176200001440000000075714633374223020621 0ustar liggesusers
    {{#contents}} {{{html}}} {{/contents}}
    pkgdown/inst/BS5/templates/config-docsearch.json0000644000176200001440000000354214633374223021373 0ustar liggesusers{ "index_name": "{{index}}", "start_urls": [ { "url": "{{url}}/index.html", "selectors_key": "homepage", "tags": [ "homepage" ] }, { "url": "{{url}}/reference", "selectors_key": "reference", "tags": [ "reference" ] }, { "url": "{{url}}/articles", "selectors_key": "articles", "tags": [ "articles" ] } ], "stop_urls": [ "/reference/$", "/reference/index.html", "/articles/$", "/articles/index.html" ], "sitemap_urls": [ "{{url}}/sitemap.xml" ], "selectors": { "homepage": { "lvl0": { "selector": "main h1", "default_value": "{{package}} Home page" }, "lvl1": { "selector": "main h2" }, "lvl2": { "selector": "main h3", "default_value": "Context" }, "lvl3": ".ref-arguments td, .ref-description", "text": "main p, main li, main .pre" }, "reference": { "lvl0": { "selector": "main h1" }, "lvl1": { "selector": "main .name", "default_value": "Argument" }, "lvl2": { "selector": ".ref-arguments th", "default_value": "Description" }, "lvl3": ".ref-arguments td, .ref-description", "text": "main p, main li" }, "articles": { "lvl0": { "selector": "main h1" }, "lvl1": { "selector": "main .name" }, "lvl2": { "selector": "main h2, main h3", "default_value": "Context" }, "text": "main p, main li" } }, "selectors_exclude": [ ".dont-index" ], "min_indexed_level": 2, "custom_settings": { "separatorsToIndex": "_", "attributesToRetrieve": [ "hierarchy", "content", "anchor", "url", "url_without_anchor" ] } } pkgdown/inst/BS5/templates/content-article-index.html0000644000176200001440000000130014633374223022356 0ustar liggesusers
    {{#sections}}

    {{{title}}}

    {{{desc}}}
    {{#contents}}
    {{title}}
    {{{description}}} {{/contents}}
    {{/sections}}
    pkgdown/inst/BS5/templates/content-home.html0000644000176200001440000000023414633374223020563 0ustar liggesusers
    {{{index}}}
    pkgdown/inst/BS5/templates/content-article.html0000644000176200001440000000271614634573316021272 0ustar liggesusers{{^as_is}}$for(header-includes)$ $header-includes$ $endfor${{/as_is}}
    $for(include-before)$ $include-before$ $endfor$ $if(abstract)$

    {{#translate}}{{abstract}}{{/translate}}

    $abstract$
    $endif$ $body$
    {{#toc}} {{/toc}}
    $for(include-after)$ $include-after$ $endfor$ pkgdown/inst/BS5/templates/content-title-body.html0000644000176200001440000000073114633374223021711 0ustar liggesusers
    {{{body}}}
    pkgdown/inst/BS5/templates/content-tutorial-index.html0000644000176200001440000000076514633374223022614 0ustar liggesusers
    pkgdown/inst/BS5/templates/content-reference-topic.html0000644000176200001440000000221614633374223022707 0ustar liggesusers
    {{#description}} {{#contents}} {{{.}}} {{/contents}} {{/description}}
    {{#usage}}

    {{{title}}}

    {{#contents}} {{{.}}} {{/contents}}
    {{/usage}} {{#sections}}

    {{{title}}}

    {{#contents}} {{{.}}} {{/contents}}
    {{/sections}} {{#examples}}

    {{#translate}}{{examples}}{{/translate}}

    {{{.}}}
    {{/examples}}
    pkgdown/inst/BS5/templates/after-body.html0000644000176200001440000000005314136064064020213 0ustar liggesusers{{#includes}}{{{after_body}}}{{/includes}} pkgdown/inst/BS5/templates/before-body.html0000644000176200001440000000005414136064064020355 0ustar liggesusers{{#includes}}{{{before_body}}}{{/includes}} pkgdown/inst/BS5/templates/content-authors.html0000644000176200001440000000130614770274305021323 0ustar liggesusers
    {{{before}}}
      {{#authors}}
    • {{{name}}}. {{{roles}}}. {{{orcid}}}{{{ror}}} {{#comment}}
      {{{.}}}{{/comment}}

    • {{/authors}}
    {{{after}}}
    pkgdown/inst/BS5/templates/content-news-index.html0000644000176200001440000000103714633374223021716 0ustar liggesusers
    pkgdown/inst/BS5/templates/content-quarto.html0000644000176200001440000000176314634573316021163 0ustar liggesusers
    {{#abstract}}

    {{#translate}}{{abstract}}{{/translate}}

    {{{.}}}
    {{/abstract}} {{#includes}}{{{before}}}{{/includes}} {{{body}}} {{#includes}}{{{after}}}{{/includes}}
    {{#toc}} {{/toc}}
    pkgdown/inst/BS5/templates/content-tutorial.html0000644000176200001440000000071414633374223021501 0ustar liggesusers
  • pkgdown/inst/BS5/templates/header.html0000644000176200001440000000000014134110164017366 0ustar liggesuserspkgdown/inst/BS5/templates/content-citation-authors.html0000644000176200001440000000230714770274305023135 0ustar liggesusers

    {{#translate}}{{authors}}{{/translate}}

    {{{before}}}
      {{#authors}}
    • {{{name}}}. {{{roles}}}. {{{orcid}}}{{{ror}}} {{#comment}}
      {{{.}}}{{/comment}}

    • {{/authors}}
    {{{after}}}

    {{#translate}}{{citation}}{{/translate}}

    {{#source}}{{{.}}}{{/source}}

    {{#citations}} {{{html}}}
    {{bibtex}}
    {{/citations}}
    {{#inst}}

    {{#translate}}{{author_details}}{{/translate}}

    {{.}}
    {{/inst}}
    pkgdown/inst/BS5/templates/layout.html0000644000176200001440000000073714633374223017510 0ustar liggesusers {{{ head }}} {{{ in-header }}} {{#translate}}{{skip}}{{/translate}} {{{ before-body }}} {{{ navbar }}}
    {{{ content }}}
    {{{ footer }}}
    {{{ docsearch }}} {{{ after-body }}} pkgdown/inst/BS5/templates/in-header.html0000644000176200001440000000005214136064064020012 0ustar liggesusers{{#includes}}{{{in_header}}}{{/includes}} pkgdown/inst/BS5/templates/content-reference-index.html0000644000176200001440000000202615100735002022661 0ustar liggesusers
    {{#rows}}
    {{#title}}

    {{{.}}}

    {{/title}} {{#subtitle}}

    {{{.}}}

    {{/subtitle}} {{#desc}}
    {{{desc}}}
    {{/desc}}
    {{#topics}}
    {{#has_icons}}{{#icon}}{{/icon}}{{/has_icons}} {{#aliases}}{{{.}}} {{/aliases}} {{#lifecycle}}{{.}}{{/lifecycle}}
    {{{title}}}
    {{/topics}}
    {{/rows}}
    pkgdown/inst/BS5/templates/footer.html0000644000176200001440000000024614633374223017464 0ustar liggesusers{{#footer}} {{/footer}} pkgdown/inst/BS5/templates/navbar.html0000644000176200001440000000236115011466501017427 0ustar liggesusers{{#navbar}} {{/navbar}} pkgdown/inst/BS5/templates/layout-redirect.html0000644000176200001440000000026514633374223021303 0ustar liggesusers pkgdown/inst/BS5/templates/head.html0000644000176200001440000000770414770274305017077 0ustar liggesusers {{{pagetitle}}} • {{#site}}{{title}}{{/site}} {{#has_favicons}} {{/has_favicons}} {{#uses_katex}} {{/uses_katex}} {{#uses_mathjax}} {{/uses_mathjax}} {{#lightswitch}}{{/lightswitch}} {{{headdeps}}} {{#includes}}{{{head}}}{{/includes}} {{#extra}} {{#css}}{{/css}} {{#js}}{{/js}} {{/extra}} {{#opengraph}} {{#description}} {{/description}} {{#image}} {{#alt}}{{/alt}} {{/image}} {{#twitter}} {{#card}}{{/card}} {{#creator}}{{/creator}} {{#site}}{{/site}} {{/twitter}} {{/opengraph}} {{#yaml}}{{#noindex}}{{/noindex}}{{/yaml}} {{#development}}{{#in_dev}}{{/in_dev}}{{/development}} {{#yaml}}{{#google_site_verification}} {{/google_site_verification}}{{/yaml}} {{#yaml}}{{#ganalytics}} {{/ganalytics}}{{/yaml}} {{#has_trailingslash}} {{/has_trailingslash}} {{#has_deps}} {{{dependencies}}} {{/has_deps}} pkgdown/inst/quarto/0000755000176200001440000000000014634573316014227 5ustar liggesuserspkgdown/inst/quarto/template.html0000644000176200001440000000164414634573316016735 0ustar liggesusers $pagetitle$ $for(css)$ $endfor$ $for(header-includes)$ $header-includes$ $endfor$
    $for(include-before)$ $include-before$ $endfor$
    $if(title)$

    $title$

    $endif$ $if(subtitle)$

    $subtitle$

    $endif$ $for(author)$

    $author$

    $endfor$ $if(date)$

    $date$

    $endif$ $if(abstract)$
    $abstract$
    $endif$
    $body$
    $for(include-after)$ $include-after$ $endfor$
    pkgdown/inst/highlight-styles/0000755000176200001440000000000014633374223016177 5ustar liggesuserspkgdown/inst/highlight-styles/radical.scss0000644000176200001440000000356414633374223020503 0ustar liggesuserspre code /* Normal */ {color:#7c9c9e} pre code span.al /* Alert */ {color:#ff427b; background-color:#2f183b; font-weight: bold} pre code span.an /* Annotation */ {color:#fda8bc} pre code span.at /* Attribute */ {color:#5af5f0} pre code span.bn /* BaseN */ {color:#f834bb} pre code span.bu /* BuiltIn */ {color:#999ee1} pre code span.cf /* ControlFlow */ {color:#d5358f; font-weight: bold} pre code span.ch /* Char */ {color:#dff959} pre code span.cn /* Constant */ {color:#fa61b8; font-weight: bold} pre code span.co /* Comment */ {color:#45898c; font-style: italic} pre code span.cv /* CommentVar */ {color:#a8c0c2} pre code span.do /* Documentation */ {color:#75b7bb} pre code span.dt /* DataType */ {color:#ff85a1} pre code span.dv /* DecVal */ {color:#fa61b8} pre code span.er /* Error */ {color:#ff427b; font-weight: bold; font-style: italic; text-decoration: underline} pre code span.ex /* Extension */ {color:#a8ffdb; font-weight: bold} pre code span.fl /* Float */ {color:#f834bb} pre code span.fu /* Function */ {color:#a9fef7} pre code span.im /* Import */ {color:#a9fef7} pre code span.in /* Information */ {color:#ffd000} pre code span.kw /* Keyword */ {color:#d5358f; font-weight: bold} pre code span.op /* Operator */ {color:#d5358f} pre code span.ot /* Others */ {color:#5effbd} pre code span.pp /* Preprocessor */ {color:#d5358f} pre code span.re /* RegionMarker */ {color:#baf7fc; background-color:#242560} pre code span.sc /* SpecialChar */ {color:#c3f920} pre code span.ss /* SpecialString */ {color:#ff96aa} pre code span.st /* String */ {color:#a9fef7} pre code span.va /* Variable */ {color:#c7e3ee} pre code span.vs /* VerbatimString */ {color:#a8ffdb} pre code span.wa /* Warning */ {color:#ff427b} pkgdown/inst/highlight-styles/arrow-light.scss0000644000176200001440000000322714633374223021337 0ustar liggesuserspre {background-color: #f1f3f5;} pre code /* Normal */ {color:#003B4F} pre code span.al /* Alert */ {color:#AD0000} pre code span.an /* Annotation */ {color:#5E5E5E} pre code span.at /* Attribute */ {color:#657422} pre code span.bn /* BaseN */ {color:#AD0000} pre code span.bu /* BuiltIn */ {} pre code span.cf /* ControlFlow */ {color:#003B4F} pre code span.ch /* Char */ {color:#20794D} pre code span.cn /* Constant */ {color:#8f5902} pre code span.co /* Comment */ {color:#5E5E5E} pre code span.cv /* CommentVar */ {color:#5E5E5E; font-style: italic} pre code span.do /* Documentation */ {color:#5E5E5E; font-style: italic} pre code span.dt /* DataType */ {color:#AD0000} pre code span.dv /* DecVal */ {color:#AD0000} pre code span.er /* Error */ {color:#AD0000} pre code span.ex /* Extension */ {} pre code span.fl /* Float */ {color:#AD0000} pre code span.fu /* Function */ {color:#4758AB} pre code span.im /* Import */ {color:#00769E} pre code span.in /* Information */ {color:#5E5E5E} pre code span.kw /* Keyword */ {color:#003B4F} pre code span.op /* Operator */ {color:#5E5E5E} pre code span.ot /* Other */ {color:#003B4F} pre code span.pp /* Preprocessor */ {color:#AD0000} pre code span.sc /* SpecialChar */ {color:#5E5E5E} pre code span.ss /* SpecialString */ {color:#20794D} pre code span.st /* String */ {color:#20794D} pre code span.va /* Variable */ {color:#111111} pre code span.vs /* VerbatimString */ {color:#20794D} pre code span.wa /* Warning */ {color:#5E5E5E; font-style: italic} pkgdown/inst/highlight-styles/a11y-light.scss0000644000176200001440000000321214633374223020752 0ustar liggesuserspre {background-color: #fefefe;} pre code /* Normal */ {color:#545454} pre code span.al /* Alert */ {color:#7928a1} pre code span.an /* Annotation */ {color:#696969} pre code span.at /* Attribute */ {color:#aa5d00} pre code span.bn /* BaseN */ {color:#7928a1} pre code span.bu /* BuiltIn */ {} pre code span.cf /* ControlFlow */ {color:#d91e18} pre code span.ch /* Char */ {color:#008000} pre code span.cn /* Constant */ {color:#d91e18} pre code span.co /* Comment */ {color:#696969} pre code span.cv /* CommentVar */ {color:#696969; font-style: italic} pre code span.do /* Documentation */ {color:#696969; font-style: italic} pre code span.dt /* DataType */ {color:#7928a1} pre code span.dv /* DecVal */ {color:#7928a1} pre code span.er /* Error */ {color:#7928a1} pre code span.ex /* Extension */ {} pre code span.fl /* Float */ {color:#aa5d00} pre code span.fu /* Function */ {color:#06287e} pre code span.im /* Import */ {} pre code span.in /* Information */ {color:#696969} pre code span.kw /* Keyword */ {color:#d91e18} pre code span.op /* Operator */ {color:#007faa} pre code span.ot /* Other */ {color:#d91e18} pre code span.pp /* Preprocessor */ {color:#7928a1} pre code span.sc /* SpecialChar */ {color:#007faa} pre code span.ss /* SpecialString */ {color:#008000} pre code span.st /* String */ {color:#008000} pre code span.va /* Variable */ {color:#aa5d00} pre code span.vs /* VerbatimString */ {color:#008000} pre code span.wa /* Warning */ {color:#696969; font-style: italic} pkgdown/inst/highlight-styles/monochrome-light.scss0000644000176200001440000000346314633374223022355 0ustar liggesuserspre {background-color: #ffffff; color: #000000;} pre code /* Normal */ {color:#000000} pre code span.al /* Alert */ {color:#000000} pre code span.an /* Annotation */ {color:#000000; font-style: italic} pre code span.at /* Attribute */ {color:#000000} pre code span.bn /* BaseN */ {color:#000000} pre code span.bu /* BuiltIn */ {color:#000000} pre code span.cf /* ControlFlow */ {color:#000000} pre code span.ch /* Char */ {color:#000000} pre code span.cn /* Constant */ {color:#000000} pre code span.co /* Comment */ {color:#000000; font-style: italic} pre code span.cv /* CommentVar */ {color:#000000; font-style: italic} pre code span.do /* Documentation */ {color:#000000; font-style: italic} pre code span.dt /* DataType */ {color:#000000} pre code span.dv /* DecVal */ {color:#000000} pre code span.er /* Error */ {color:#000000} pre code span.ex /* Extension */ {color:#000000} pre code span.fl /* Float */ {color:#000000} pre code span.fu /* Function */ {color:#000000} pre code span.im /* Import */ {color:#000000} pre code span.in /* Information */ {color:#000000; font-style: italic} pre code span.kw /* Keyword */ {color:#000000} pre code span.op /* Operator */ {color:#000000} pre code span.ot /* Other */ {color:#000000} pre code span.pp /* Preprocessor */ {color:#000000} pre code span.re /* RegionMarker */ {color:#000000} pre code span.sc /* SpecialChar */ {color:#000000} pre code span.ss /* SpecialString */ {color:#000000} pre code span.st /* String */ {color:#000000} pre code span.va /* Variable */ {color:#000000} pre code span.vs /* VerbatimString */ {color:#000000} pre code span.wa /* Warning */ {color:#000000; font-style: italic} pkgdown/inst/highlight-styles/ayu-light.scss0000644000176200001440000000353314246155422021001 0ustar liggesuserspre {background-color: #fafafa;} pre code /* Normal */ {color:#575f66} pre code span.al /* Alert */ {color:#f51818; background-color:#faefef; font-weight: bold} pre code span.an /* Annotation */ {color:#e6ba7e} pre code span.at /* Attribute */ {color:#399ee6} pre code span.bn /* BaseN */ {color:#ff9940} pre code span.bu /* BuiltIn */ {color:#4cbf99} pre code span.cf /* ControlFlow */ {color:#fa8d3e; font-weight: bold} pre code span.ch /* Char */ {color:#4cbf99} pre code span.cn /* Constant */ {color:#a37acc} pre code span.co /* Comment */ {color:#607880; font-style: italic} pre code span.cv /* CommentVar */ {color:#a37acc} pre code span.do /* Documentation */ {color:#607880} pre code span.dt /* DataType */ {color:#fa8d3e} pre code span.dv /* DecVal */ {color:#ff9940} pre code span.er /* Error */ {color:#f51818; text-decoration: underline} pre code span.ex /* Extension */ {color:#399ee6; font-weight: bold} pre code span.fl /* Float */ {color:#ff9940} pre code span.fu /* Function */ {color:#f2ae49} pre code span.im /* Import */ {color:#86b300} pre code span.in /* Information */ {color:#ff9940} pre code span.kw /* Keyword */ {color:#fa8d3e; font-weight: bold} pre code span.op /* Operator */ {color:#ed9366} pre code span.ot /* Others */ {color:#55b4d4} pre code span.pp /* Preprocessor */ {color:#f07171} pre code span.re /* RegionMarker */ {color:#399ee6; background-color:#ddecf3} pre code span.sc /* SpecialChar */ {color:#4cbf99} pre code span.ss /* SpecialString */ {color:#4cbf99} pre code span.st /* String */ {color:#86b300} pre code span.va /* Variable */ {color:#55b4d4} pre code span.vs /* VerbatimString */ {color:#86b300} pre code span.wa /* Warning */ {color:#f07171} pkgdown/inst/highlight-styles/haddock.scss0000644000176200001440000000233314245770621020473 0ustar liggesuserspre code span.al /* Alert */ {color:#ff0000} pre code span.an /* Annotation */ {color:#008000} pre code span.at /* Attribute */ {} pre code span.bu /* BuiltIn */ {} pre code span.cf /* ControlFlow */ {color:#0000ff} pre code span.ch /* Char */ {color:#008080} pre code span.cn /* Constant */ {} pre code span.co /* Comment */ {color:#008000} pre code span.cv /* CommentVar */ {color:#008000} pre code span.do /* Documentation */ {color:#008000} pre code span.er /* Error */ {color:#ff0000; font-weight: bold} pre code span.ex /* Extension */ {} pre code span.im /* Import */ {} pre code span.in /* Information */ {color:#008000} pre code span.kw /* Keyword */ {color:#0000ff} pre code span.op /* Operator */ {} pre code span.ot /* Other */ {color:#ff4000} pre code span.pp /* Preprocessor */ {color:#ff4000} pre code span.sc /* SpecialChar */ {color:#008080} pre code span.ss /* SpecialString */ {color:#008080} pre code span.st /* String */ {color:#008080} pre code span.va /* Variable */ {} pre code span.vs /* VerbatimString */ {color:#008080} pre code span.wa /* Warning */ {color:#008000; font-weight: bold} pkgdown/inst/highlight-styles/breeze-dark.scss0000644000176200001440000000353214246155422021270 0ustar liggesuserspre {background-color: #232629;} pre code /* Normal */ {color:#cfcfc2} pre code span.al /* Alert */ {color:#95da4c; background-color:#4d1f24; font-weight: bold} pre code span.an /* Annotation */ {color:#3f8058} pre code span.at /* Attribute */ {color:#2980b9} pre code span.bn /* BaseN */ {color:#f67400} pre code span.bu /* BuiltIn */ {color:#7f8c8d} pre code span.cf /* ControlFlow */ {color:#fdbc4b; font-weight: bold} pre code span.ch /* Char */ {color:#3daee9} pre code span.cn /* Constant */ {color:#27aeae; font-weight: bold} pre code span.co /* Comment */ {color:#7a7c7d} pre code span.cv /* CommentVar */ {color:#7f8c8d} pre code span.do /* Documentation */ {color:#a43340} pre code span.dt /* DataType */ {color:#2980b9} pre code span.dv /* DecVal */ {color:#f67400} pre code span.er /* Error */ {color:#da4453; text-decoration: underline} pre code span.ex /* Extension */ {color:#0099ff; font-weight: bold} pre code span.fl /* Float */ {color:#f67400} pre code span.fu /* Function */ {color:#8e44ad} pre code span.im /* Import */ {color:#27ae60} pre code span.in /* Information */ {color:#c45b00} pre code span.kw /* Keyword */ {color:#cfcfc2; font-weight: bold} pre code span.op /* Operator */ {color:#3f8058} pre code span.ot /* Others */ {color:#27ae60} pre code span.pp /* Preprocessor */ {color:#27ae60} pre code span.re /* RegionMarker */ {color:#2980b9; background-color:#153042} pre code span.sc /* SpecialChar */ {color:#3daee9} pre code span.ss /* SpecialString */ {color:#da4453} pre code span.st /* String */ {color:#f44f4f} pre code span.va /* Variable */ {color:#27aeae} pre code span.vs /* VerbatimString */ {color:#da4453} pre code span.wa /* Warning */ {color:#da4453} pkgdown/inst/highlight-styles/printing.scss0000644000176200001440000000350714246155422020731 0ustar liggesuserspre {background-color: #ffffff;} pre code /* Normal */ {color:#000000} pre code span.al /* Alert */ {color:#bf0303; background-color:#f7e6e6; font-weight: bold} pre code span.an /* Annotation */ {color:#ca60ca} pre code span.at /* Attribute */ {color:#0057ae} pre code span.bn /* BaseN */ {color:#b08000} pre code span.bu /* BuiltIn */ {color:#644a9b} pre code span.cf /* ControlFlow */ {color:#000000; font-weight: bold} pre code span.ch /* Char */ {color:#924c9d} pre code span.cn /* Constant */ {color:#aa5500} pre code span.co /* Comment */ {color:#898887} pre code span.cv /* CommentVar */ {color:#0095ff} pre code span.do /* Documentation */ {color:#607880} pre code span.dt /* DataType */ {color:#0057ae} pre code span.dv /* DecVal */ {color:#b08000} pre code span.er /* Error */ {color:#bf0303; text-decoration: underline} pre code span.ex /* Extension */ {color:#0095ff; font-weight: bold} pre code span.fl /* Float */ {color:#b08000} pre code span.fu /* Function */ {color:#644a9b} pre code span.im /* Import */ {color:#644a9b} pre code span.in /* Information */ {color:#b08000} pre code span.kw /* Keyword */ {color:#000000; font-weight: bold} pre code span.op /* Operator */ {color:#000000} pre code span.ot /* Others */ {color:#006e28} pre code span.pp /* Preprocessor */ {color:#006e28} pre code span.re /* RegionMarker */ {color:#0057ae; background-color:#e0e9f8} pre code span.sc /* SpecialChar */ {color:#ff5500} pre code span.ss /* SpecialString */ {color:#ff5500} pre code span.st /* String */ {color:#bf0303} pre code span.va /* Variable */ {color:#0057ae} pre code span.vs /* VerbatimString */ {color:#bf0303} pre code span.wa /* Warning */ {color:#bf0303} pkgdown/inst/highlight-styles/ayu-mirage.scss0000644000176200001440000000353314633374223021140 0ustar liggesuserspre {background-color: #1f2430;} pre code /* Normal */ {color:#cbccc6} pre code span.al /* Alert */ {color:#ff3333; background-color:#332430; font-weight: bold} pre code span.an /* Annotation */ {color:#ffe6b3} pre code span.at /* Attribute */ {color:#73d0ff} pre code span.bn /* BaseN */ {color:#ffcc66} pre code span.bu /* BuiltIn */ {color:#95e6cb} pre code span.cf /* ControlFlow */ {color:#ffa759; font-weight: bold} pre code span.ch /* Char */ {color:#95e6cb} pre code span.cn /* Constant */ {color:#d4bfff} pre code span.co /* Comment */ {color:#5c6773; font-style: italic} pre code span.cv /* CommentVar */ {color:#d4bfff} pre code span.do /* Documentation */ {color:#5c6773} pre code span.dt /* DataType */ {color:#ffa759} pre code span.dv /* DecVal */ {color:#ffcc66} pre code span.er /* Error */ {color:#ff3333; text-decoration: underline} pre code span.ex /* Extension */ {color:#73d0ff; font-weight: bold} pre code span.fl /* Float */ {color:#ffcc66} pre code span.fu /* Function */ {color:#ffd580} pre code span.im /* Import */ {color:#bae67e} pre code span.in /* Information */ {color:#ffcc66} pre code span.kw /* Keyword */ {color:#ffa759; font-weight: bold} pre code span.op /* Operator */ {color:#f29e74} pre code span.ot /* Other */ {color:#5ccfe6} pre code span.pp /* Preprocessor */ {color:#f28779} pre code span.re /* RegionMarker */ {color:#73d0ff; background-color:#2a4254} pre code span.sc /* SpecialChar */ {color:#95e6cb} pre code span.ss /* SpecialString */ {color:#95e6cb} pre code span.st /* String */ {color:#bae67e} pre code span.va /* Variable */ {color:#5ccfe6} pre code span.vs /* VerbatimString */ {color:#bae67e} pre code span.wa /* Warning */ {color:#f28779} pkgdown/inst/highlight-styles/zenburn.scss0000644000176200001440000000320014246155422020550 0ustar liggesuserspre {background-color: #303030; color: #cccccc;} pre code span.al /* Alert */ {color:#ffcfaf} pre code span.an /* Annotation */ {color:#7f9f7f; font-weight: bold} pre code span.at /* Attribute */ {} pre code span.bn /* BaseN */ {color:#dca3a3} pre code span.bu /* BuiltIn */ {} pre code span.cf /* ControlFlow */ {color:#f0dfaf} pre code span.ch /* Char */ {color:#dca3a3} pre code span.cn /* Constant */ {color:#dca3a3; font-weight: bold} pre code span.co /* Comment */ {color:#7f9f7f} pre code span.cv /* CommentVar */ {color:#7f9f7f; font-weight: bold} pre code span.do /* Documentation */ {color:#7f9f7f} pre code span.dt /* DataType */ {color:#dfdfbf} pre code span.dv /* DecVal */ {color:#dcdccc} pre code span.er /* Error */ {color:#c3bf9f} pre code span.ex /* Extension */ {} pre code span.fl /* Float */ {color:#c0bed1} pre code span.fu /* Function */ {color:#efef8f} pre code span.im /* Import */ {} pre code span.in /* Information */ {color:#7f9f7f; font-weight: bold} pre code span.kw /* Keyword */ {color:#f0dfaf} pre code span.op /* Operator */ {color:#f0efd0} pre code span.ot /* Other */ {color:#efef8f} pre code span.pp /* Preprocessor */ {color:#ffcfaf; font-weight: bold} pre code span.sc /* SpecialChar */ {color:#dca3a3} pre code span.ss /* SpecialString */ {color:#cc9393} pre code span.st /* String */ {color:#cc9393} pre code span.va /* Variable */ {} pre code span.vs /* VerbatimString */ {color:#cc9393} pre code span.wa /* Warning */ {color:#7f9f7f; font-weight: bold} pkgdown/inst/highlight-styles/tango.scss0000644000176200001440000000344614246155422020211 0ustar liggesuserspre {background-color: #f8f8f8;} pre code span.al /* Alert */ {color:#ef2929} pre code span.an /* Annotation */ {color:#8f5902; font-weight: bold; font-style: italic} pre code span.at /* Attribute */ {color:#c4a000} pre code span.bn /* BaseN */ {color:#0000cf} pre code span.cf /* ControlFlow */ {color:#204a87; font-weight: bold} pre code span.ch /* Char */ {color:#4e9a06} pre code span.cn /* Constant */ {color:#000000} pre code span.co /* Comment */ {color:#8f5902; font-style: italic} pre code span.cv /* CommentVar */ {color:#8f5902; font-weight: bold; font-style: italic} pre code span.do /* Documentation */ {color:#8f5902; font-weight: bold; font-style: italic} pre code span.dt /* DataType */ {color:#204a87} pre code span.dv /* DecVal */ {color:#0000cf} pre code span.er /* Error */ {color:#a40000; font-weight: bold} pre code span.ex /* Extension */ {} pre code span.fl /* Float */ {color:#0000cf} pre code span.fu /* Function */ {color:#000000} pre code span.im /* Import */ {} pre code span.in /* Information */ {color:#8f5902; font-weight: bold; font-style: italic} pre code span.kw /* Keyword */ {color:#204a87; font-weight: bold} pre code span.op /* Operator */ {color:#ce5c00; font-weight: bold} pre code span.ot /* Other */ {color:#8f5902} pre code span.pp /* Preprocessor */ {color:#8f5902; font-style: italic} pre code span.sc /* SpecialChar */ {color:#000000} pre code span.ss /* SpecialString */ {color:#4e9a06} pre code span.st /* String */ {color:#4e9a06} pre code span.va /* Variable */ {color:#000000} pre code span.vs /* VerbatimString */ {color:#4e9a06} pre code span.wa /* Warning */ {color:#8f5902; font-weight: bold; font-style: italic} pkgdown/inst/highlight-styles/gruvbox-light.scss0000644000176200001440000000361614246155422021701 0ustar liggesuserspre {background-color: #fbf1c7;} pre code /* Normal */ {color:#3c3836} pre code span.al /* Alert */ {color:#282828; background-color:#cc241d; font-weight: bold} pre code span.an /* Annotation */ {color:#98971a} pre code span.at /* Attribute */ {color:#d79921} pre code span.bn /* BaseN */ {color:#f67400} pre code span.bu /* BuiltIn */ {color:#d65d0e} pre code span.cf /* ControlFlow */ {color:#cc241d; font-weight: bold} pre code span.ch /* Char */ {color:#b16286} pre code span.cn /* Constant */ {color:#b16286; font-weight: bold} pre code span.co /* Comment */ {color:#928374} pre code span.cv /* CommentVar */ {color:#928374} pre code span.do /* Documentation */ {color:#98971a} pre code span.dt /* DataType */ {color:#d79921} pre code span.dv /* DecVal */ {color:#f67400} pre code span.er /* Error */ {color:#cc241d; text-decoration: underline} pre code span.ex /* Extension */ {color:#689d6a; font-weight: bold} pre code span.fl /* Float */ {color:#f67400} pre code span.fu /* Function */ {color:#689d6a} pre code span.im /* Import */ {color:#689d6a} pre code span.in /* Information */ {color:#282828; background-color:#83a598} pre code span.kw /* Keyword */ {color:#3c3836; font-weight: bold} pre code span.op /* Operator */ {color:#3c3836} pre code span.ot /* Others */ {color:#689d6a} pre code span.pp /* Preprocessor */ {color:#d65d0e} pre code span.re /* RegionMarker */ {color:#928374; background-color:#f9f5d7} pre code span.sc /* SpecialChar */ {color:#b16286} pre code span.ss /* SpecialString */ {color:#98971a} pre code span.st /* String */ {color:#98971a} pre code span.va /* Variable */ {color:#458588} pre code span.vs /* VerbatimString */ {color:#98971a} pre code span.wa /* Warning */ {color:#282828; background-color:#fabd2f} pkgdown/inst/highlight-styles/monokai.scss0000644000176200001440000000340114633374223020527 0ustar liggesuserspre {background-color: #2e3440;} pre code /* Normal */ {color:#f8f8f2} pre code span.al /* Alert */ {color:#ff5555; font-weight: bold} pre code span.an /* Annotation */ {color:#75715e} pre code span.at /* Attribute */ {color:#f92672} pre code span.bn /* BaseN */ {color:#ae81ff} pre code span.bu /* BuiltIn */ {color:#66D9EF} pre code span.cf /* ControlFlow */ {color:#f92672} pre code span.ch /* Char */ {color:#e6db74} pre code span.cn /* Constant */ {color:#ae81ff} pre code span.co /* Comment */ {color:#75715e} pre code span.cv /* CommentVar */ {color:#75715e} pre code span.do /* Documentation */ {color:#75715e} pre code span.dt /* DataType */ {color:#66d9ef; font-style: italic} pre code span.dv /* DecVal */ {color:#ae81ff} pre code span.er /* Error */ {color:#ff5555; text-decoration: underline} pre code span.ex /* Extension */ {color:#a6e22e; font-weight: bold} pre code span.fl /* Float */ {color:#ae81ff} pre code span.fu /* Function */ {color:#a6e22e} pre code span.im /* Import */ {color:#f92672} pre code span.in /* Information */ {color:#f1fa8c} pre code span.kw /* Keyword */ {color:#f92672} pre code span.op /* Operator */ {color:#f8f8f2} pre code span.ot /* Others */ {color:#a6e22e} pre code span.pp /* Preprocessor */ {color:#f92672} pre code span.re /* RegionMarker */ {color:#75715e} pre code span.sc /* SpecialChar */ {color:#ae81ff} pre code span.ss /* SpecialString */ {color:#e6db74} pre code span.st /* String */ {color:#e6db74} pre code span.va /* Variable */ {color:#f8f8f2} pre code span.vs /* VerbatimString */ {color:#e6db74} pre code span.wa /* Warning */ {color:#ff5555} pkgdown/inst/highlight-styles/monochrome.scss0000644000176200001440000000127314245770621021246 0ustar liggesuserspre code span.al /* Alert */ {font-weight: bold} pre code span.an /* Annotation */ {font-style: italic} pre code span.cf /* ControlFlow */ {font-weight: bold} pre code span.co /* Comment */ {font-style: italic} pre code span.cv /* CommentVar */ {font-style: italic} pre code span.do /* Documentation */ {font-style: italic} pre code span.dt /* DataType */ {text-decoration: underline} pre code span.er /* Error */ {font-weight: bold} pre code span.in /* Information */ {font-style: italic} pre code span.kw /* Keyword */ {font-weight: bold} pre code span.pp /* Preprocessor */ {font-weight: bold} pre code span.wa /* Warning */ {font-style: italic} pkgdown/inst/highlight-styles/breezedark.scss0000644000176200001440000000355214246155422021215 0ustar liggesuserspre {background-color: #232629; color: #cfcfc2;} pre code /* Normal */ {color:#cfcfc2} pre code span.al /* Alert */ {color:#95da4c; background-color:#4d1f24; font-weight: bold} pre code span.an /* Annotation */ {color:#3f8058} pre code span.at /* Attribute */ {color:#2980b9} pre code span.bn /* BaseN */ {color:#f67400} pre code span.bu /* BuiltIn */ {color:#7f8c8d} pre code span.cf /* ControlFlow */ {color:#fdbc4b; font-weight: bold} pre code span.ch /* Char */ {color:#3daee9} pre code span.cn /* Constant */ {color:#27aeae; font-weight: bold} pre code span.co /* Comment */ {color:#7a7c7d} pre code span.cv /* CommentVar */ {color:#7f8c8d} pre code span.do /* Documentation */ {color:#a43340} pre code span.dt /* DataType */ {color:#2980b9} pre code span.dv /* DecVal */ {color:#f67400} pre code span.er /* Error */ {color:#da4453; text-decoration: underline} pre code span.ex /* Extension */ {color:#0099ff; font-weight: bold} pre code span.fl /* Float */ {color:#f67400} pre code span.fu /* Function */ {color:#8e44ad} pre code span.im /* Import */ {color:#27ae60} pre code span.in /* Information */ {color:#c45b00} pre code span.kw /* Keyword */ {color:#cfcfc2; font-weight: bold} pre code span.op /* Operator */ {color:#cfcfc2} pre code span.ot /* Other */ {color:#27ae60} pre code span.pp /* Preprocessor */ {color:#27ae60} pre code span.re /* RegionMarker */ {color:#2980b9; background-color:#153042} pre code span.sc /* SpecialChar */ {color:#3daee9} pre code span.ss /* SpecialString */ {color:#da4453} pre code span.st /* String */ {color:#f44f4f} pre code span.va /* Variable */ {color:#27aeae} pre code span.vs /* VerbatimString */ {color:#da4453} pre code span.wa /* Warning */ {color:#da4453} pkgdown/inst/highlight-styles/pygments.scss0000644000176200001440000000340714245770621020747 0ustar liggesuserspre code span.al /* Alert */ {color:#ff0000; font-weight: bold} pre code span.an /* Annotation */ {color:#60a0b0; font-weight: bold; font-style: italic} pre code span.at /* Attribute */ {color:#7d9029} pre code span.bn /* BaseN */ {color:#40a070} pre code span.bu /* BuiltIn */ {} pre code span.cf /* ControlFlow */ {color:#007020; font-weight: bold} pre code span.ch /* Char */ {color:#4070a0} pre code span.cn /* Constant */ {color:#880000} pre code span.co /* Comment */ {color:#60a0b0; font-style: italic} pre code span.cv /* CommentVar */ {color:#60a0b0; font-weight: bold; font-style: italic} pre code span.do /* Documentation */ {color:#ba2121; font-style: italic} pre code span.dt /* DataType */ {color:#902000} pre code span.dv /* DecVal */ {color:#40a070} pre code span.er /* Error */ {color:#ff0000; font-weight: bold} pre code span.ex /* Extension */ {} pre code span.fl /* Float */ {color:#40a070} pre code span.fu /* Function */ {color:#06287e} pre code span.im /* Import */ {} pre code span.in /* Information */ {color:#60a0b0; font-weight: bold; font-style: italic} pre code span.kw /* Keyword */ {color:#007020; font-weight: bold} pre code span.op /* Operator */ {color:#666666} pre code span.ot /* Other */ {color:#007020} pre code span.pp /* Preprocessor */ {color:#bc7a00} pre code span.sc /* SpecialChar */ {color:#4070a0} pre code span.ss /* SpecialString */ {color:#bb6688} pre code span.st /* String */ {color:#4070a0} pre code span.va /* Variable */ {color:#19177c} pre code span.vs /* VerbatimString */ {color:#4070a0} pre code span.wa /* Warning */ {color:#60a0b0; font-weight: bold; font-style: italic} pkgdown/inst/highlight-styles/espresso.scss0000644000176200001440000000320114246155422020731 0ustar liggesuserspre {background-color: #2a211c; color: #bdae9d;} pre code span.al /* Alert */ {color:#ffff00} pre code span.an /* Annotation */ {color:#0066ff; font-weight: bold; font-style: italic} pre code span.at /* Attribute */ {} pre code span.bn /* BaseN */ {color:#44aa43} pre code span.bu /* BuiltIn */ {} pre code span.cf /* ControlFlow */ {color:#43a8ed; font-weight: bold} pre code span.ch /* Char */ {color:#049b0a} pre code span.cn /* Constant */ {} pre code span.co /* Comment */ {color:#0066ff; font-weight: bold; font-style: italic} pre code span.do /* Documentation */ {color:#0066ff; font-style: italic} pre code span.dt /* DataType */ {text-decoration: underline} pre code span.dv /* DecVal */ {color:#44aa43} pre code span.er /* Error */ {color:#ffff00; font-weight: bold} pre code span.ex /* Extension */ {} pre code span.fl /* Float */ {color:#44aa43} pre code span.fu /* Function */ {color:#ff9358; font-weight: bold} pre code span.im /* Import */ {} pre code span.in /* Information */ {color:#0066ff; font-weight: bold; font-style: italic} pre code span.kw /* Keyword */ {color:#43a8ed; font-weight: bold} pre code span.op /* Operator */ {} pre code span.pp /* Preprocessor */ {font-weight: bold} pre code span.sc /* SpecialChar */ {color:#049b0a} pre code span.ss /* SpecialString */ {color:#049b0a} pre code span.st /* String */ {color:#049b0a} pre code span.va /* Variable */ {} pre code span.vs /* VerbatimString */ {color:#049b0a} pre code span.wa /* Warning */ {color:#ffff00; font-weight: bold} pkgdown/inst/highlight-styles/github-light.scss0000644000176200001440000000335514246155422021467 0ustar liggesuserspre {background-color: #ffffff;} pre code /* Normal */ {color:#24292e} pre code span.al /* Alert */ {color:#ff5555; font-weight: bold} pre code span.an /* Annotation */ {color:#6a737d} pre code span.at /* Attribute */ {color:#d73a49} pre code span.bn /* BaseN */ {color:#005cc5} pre code span.bu /* BuiltIn */ {color:#d73a49} pre code span.cf /* ControlFlow */ {color:#d73a49} pre code span.ch /* Char */ {color:#032f62} pre code span.cn /* Constant */ {color:#005cc5} pre code span.co /* Comment */ {color:#6a737d} pre code span.cv /* CommentVar */ {color:#6a737d} pre code span.do /* Documentation */ {color:#6a737d} pre code span.dt /* DataType */ {color:#d73a49} pre code span.dv /* DecVal */ {color:#005cc5} pre code span.er /* Error */ {color:#ff5555; text-decoration: underline} pre code span.ex /* Extension */ {color:#d73a49; font-weight: bold} pre code span.fl /* Float */ {color:#005cc5} pre code span.fu /* Function */ {color:#6f42c1} pre code span.im /* Import */ {color:#032f62} pre code span.in /* Information */ {color:#6a737d} pre code span.kw /* Keyword */ {color:#d73a49} pre code span.op /* Operator */ {color:#24292e} pre code span.ot /* Others */ {color:#6f42c1} pre code span.pp /* Preprocessor */ {color:#d73a49} pre code span.re /* RegionMarker */ {color:#6a737d} pre code span.sc /* SpecialChar */ {color:#005cc5} pre code span.ss /* SpecialString */ {color:#032f62} pre code span.st /* String */ {color:#032f62} pre code span.va /* Variable */ {color:#e36209} pre code span.vs /* VerbatimString */ {color:#032f62} pre code span.wa /* Warning */ {color:#ff5555} pkgdown/inst/highlight-styles/oblivion.scss0000644000176200001440000000355514246155422020723 0ustar liggesuserspre {background-color: #201f1f;} pre code /* Normal */ {color:#d3d7c1} pre code span.al /* Alert */ {color:#e85848; background-color:#451e1a; font-weight: bold} pre code span.an /* Annotation */ {color:#ad7fa8} pre code span.at /* Attribute */ {color:#ad7fa8} pre code span.bn /* BaseN */ {color:#edd400} pre code span.bu /* BuiltIn */ {color:#729fcf} pre code span.cf /* ControlFlow */ {color:#ffffff; font-weight: bold} pre code span.ch /* Char */ {color:#ce5c00} pre code span.cn /* Constant */ {color:#edd400; font-weight: bold} pre code span.co /* Comment */ {color:#30a100} pre code span.cv /* CommentVar */ {color:#ad7fa8} pre code span.do /* Documentation */ {color:#4e9a06} pre code span.dt /* DataType */ {color:#508ed8} pre code span.dv /* DecVal */ {color:#edd400} pre code span.er /* Error */ {color:#e85848; text-decoration: underline} pre code span.ex /* Extension */ {color:#508ed8; font-weight: bold} pre code span.fl /* Float */ {color:#ce5c00} pre code span.fu /* Function */ {color:#729fcf; font-weight: bold} pre code span.im /* Import */ {color:#ad7fa8} pre code span.in /* Information */ {color:#c0a25f} pre code span.kw /* Keyword */ {color:#ffffff; font-weight: bold} pre code span.op /* Operator */ {color:#eeeeec} pre code span.ot /* Others */ {color:#edd400} pre code span.pp /* Preprocessor */ {color:#ad7fa8} pre code span.re /* RegionMarker */ {color:#508ed8; background-color:#1c2c3f} pre code span.sc /* SpecialChar */ {color:#ce5c00} pre code span.ss /* SpecialString */ {color:#fce94f} pre code span.st /* String */ {color:#edd400} pre code span.va /* Variable */ {color:#ce5c00} pre code span.vs /* VerbatimString */ {color:#c4a000} pre code span.wa /* Warning */ {color:#e85848} pkgdown/inst/highlight-styles/monochrome-dark.scss0000644000176200001440000000346314633374223022167 0ustar liggesuserspre {background-color: #000000; color: #FFFFFF;} pre code /* Normal */ {color:#FFFFFF} pre code span.al /* Alert */ {color:#FFFFFF} pre code span.an /* Annotation */ {color:#FFFFFF; font-style: italic} pre code span.at /* Attribute */ {color:#FFFFFF} pre code span.bn /* BaseN */ {color:#FFFFFF} pre code span.bu /* BuiltIn */ {color:#FFFFFF} pre code span.cf /* ControlFlow */ {color:#FFFFFF} pre code span.ch /* Char */ {color:#FFFFFF} pre code span.cn /* Constant */ {color:#FFFFFF} pre code span.co /* Comment */ {color:#FFFFFF; font-style: italic} pre code span.cv /* CommentVar */ {color:#FFFFFF; font-style: italic} pre code span.do /* Documentation */ {color:#FFFFFF; font-style: italic} pre code span.dt /* DataType */ {color:#FFFFFF} pre code span.dv /* DecVal */ {color:#FFFFFF} pre code span.er /* Error */ {color:#FFFFFF} pre code span.ex /* Extension */ {color:#FFFFFF} pre code span.fl /* Float */ {color:#FFFFFF} pre code span.fu /* Function */ {color:#FFFFFF} pre code span.im /* Import */ {color:#FFFFFF} pre code span.in /* Information */ {color:#FFFFFF; font-style: italic} pre code span.kw /* Keyword */ {color:#FFFFFF} pre code span.op /* Operator */ {color:#FFFFFF} pre code span.ot /* Other */ {color:#FFFFFF} pre code span.pp /* Preprocessor */ {color:#FFFFFF} pre code span.re /* RegionMarker */ {color:#FFFFFF} pre code span.sc /* SpecialChar */ {color:#FFFFFF} pre code span.ss /* SpecialString */ {color:#FFFFFF} pre code span.st /* String */ {color:#FFFFFF} pre code span.va /* Variable */ {color:#FFFFFF} pre code span.vs /* VerbatimString */ {color:#FFFFFF} pre code span.wa /* Warning */ {color:#FFFFFF; font-style: italic} pkgdown/inst/highlight-styles/breeze-light.scss0000644000176200001440000000353214246155422021456 0ustar liggesuserspre {background-color: #ffffff;} pre code /* Normal */ {color:#1f1c1b} pre code span.al /* Alert */ {color:#bf0303; background-color:#f7e6e6; font-weight: bold} pre code span.an /* Annotation */ {color:#ca60ca} pre code span.at /* Attribute */ {color:#0057ae} pre code span.bn /* BaseN */ {color:#b08000} pre code span.bu /* BuiltIn */ {color:#644a9b; font-weight: bold} pre code span.cf /* ControlFlow */ {color:#1f1c1b; font-weight: bold} pre code span.ch /* Char */ {color:#924c9d} pre code span.cn /* Constant */ {color:#aa5500} pre code span.co /* Comment */ {color:#898887} pre code span.cv /* CommentVar */ {color:#0095ff} pre code span.do /* Documentation */ {color:#607880} pre code span.dt /* DataType */ {color:#0057ae} pre code span.dv /* DecVal */ {color:#b08000} pre code span.er /* Error */ {color:#bf0303; text-decoration: underline} pre code span.ex /* Extension */ {color:#0095ff; font-weight: bold} pre code span.fl /* Float */ {color:#b08000} pre code span.fu /* Function */ {color:#644a9b} pre code span.im /* Import */ {color:#ff5500} pre code span.in /* Information */ {color:#b08000} pre code span.kw /* Keyword */ {color:#1f1c1b; font-weight: bold} pre code span.op /* Operator */ {color:#ca60ca} pre code span.ot /* Others */ {color:#006e28} pre code span.pp /* Preprocessor */ {color:#006e28} pre code span.re /* RegionMarker */ {color:#0057ae; background-color:#e0e9f8} pre code span.sc /* SpecialChar */ {color:#3daee9} pre code span.ss /* SpecialString */ {color:#ff5500} pre code span.st /* String */ {color:#bf0303} pre code span.va /* Variable */ {color:#0057ae} pre code span.vs /* VerbatimString */ {color:#bf0303} pre code span.wa /* Warning */ {color:#bf0303} pkgdown/inst/highlight-styles/a11y-dark.scss0000644000176200001440000000321214633374223020564 0ustar liggesuserspre {background-color: #2b2b2b;} pre code /* Normal */ {color:#f8f8f2} pre code span.al /* Alert */ {color:#dcc6e0} pre code span.an /* Annotation */ {color:#d4d0ab} pre code span.at /* Attribute */ {color:#ffd700} pre code span.bn /* BaseN */ {color:#dcc6e0} pre code span.bu /* BuiltIn */ {} pre code span.cf /* ControlFlow */ {color:#ffa07a} pre code span.ch /* Char */ {color:#abe338} pre code span.cn /* Constant */ {color:#ffa07a} pre code span.co /* Comment */ {color:#d4d0ab} pre code span.cv /* CommentVar */ {color:#d4d0ab; font-style: italic} pre code span.do /* Documentation */ {color:#d4d0ab; font-style: italic} pre code span.dt /* DataType */ {color:#dcc6e0} pre code span.dv /* DecVal */ {color:#dcc6e0} pre code span.er /* Error */ {color:#dcc6e0} pre code span.ex /* Extension */ {} pre code span.fl /* Float */ {color:#f5ab35} pre code span.fu /* Function */ {color:#ffd700} pre code span.im /* Import */ {} pre code span.in /* Information */ {color:#d4d0ab} pre code span.kw /* Keyword */ {color:#ffa07a} pre code span.op /* Operator */ {color:#00e0e0} pre code span.ot /* Other */ {color:#ffa07a} pre code span.pp /* Preprocessor */ {color:#dcc6e0} pre code span.sc /* SpecialChar */ {color:#00e0e0} pre code span.ss /* SpecialString */ {color:#abe338} pre code span.st /* String */ {color:#abe338} pre code span.va /* Variable */ {color:#f5ab35} pre code span.vs /* VerbatimString */ {color:#abe338} pre code span.wa /* Warning */ {color:#d4d0ab; font-style: italic} pkgdown/inst/highlight-styles/solarized.scss0000644000176200001440000000354714633374223021101 0ustar liggesuserspre {background-color: #fdf6e3;} pre code /* Normal */ {color:#657b83} pre code span.al /* Alert */ {color:#d33682; font-weight: bold} pre code span.an /* Annotation */ {color:#268bd2} pre code span.at /* Attribute */ {color:#268bd2} pre code span.bn /* BaseN */ {color:#2aa198} pre code span.bu /* BuiltIn */ {color:#cb4b16} pre code span.cf /* ControlFlow */ {color:#859900; font-weight: bold} pre code span.ch /* Char */ {color:#2aa198} pre code span.cn /* Constant */ {color:#2aa198; font-weight: bold} pre code span.co /* Comment */ {color:#93a1a1; font-style: italic} pre code span.cv /* CommentVar */ {color:#2aa198} pre code span.do /* Documentation */ {color:#dc322f} pre code span.dt /* DataType */ {color:#b58900; font-weight: bold} pre code span.dv /* DecVal */ {color:#2aa198} pre code span.er /* Error */ {color:#dc322f; text-decoration: underline} pre code span.ex /* Extension */ {color:#268bd2; font-weight: bold} pre code span.fl /* Float */ {color:#2aa198} pre code span.fu /* Function */ {color:#268bd2} pre code span.im /* Import */ {color:#2aa198} pre code span.in /* Information */ {color:#b58900} pre code span.kw /* Keyword */ {color:#859900; font-weight: bold} pre code span.op /* Operator */ {color:#859900} pre code span.ot /* Others */ {color:#859900} pre code span.pp /* Preprocessor */ {color:#cb4b16} pre code span.re /* RegionMarker */ {color:#268bd2; background-color:#eee8d5} pre code span.sc /* SpecialChar */ {color:#dc322f} pre code span.ss /* SpecialString */ {color:#dc322f} pre code span.st /* String */ {color:#2aa198} pre code span.va /* Variable */ {color:#268bd2} pre code span.vs /* VerbatimString */ {color:#2aa198} pre code span.wa /* Warning */ {color:#cb4b16} pkgdown/inst/highlight-styles/dracula.scss0000644000176200001440000000340114246155422020503 0ustar liggesuserspre {background-color: #282a36;} pre code /* Normal */ {color:#f8f8f2} pre code span.al /* Alert */ {color:#ff5555; font-weight: bold} pre code span.an /* Annotation */ {color:#ff79c6} pre code span.at /* Attribute */ {color:#ff79c6} pre code span.bn /* BaseN */ {color:#bd93f9} pre code span.bu /* BuiltIn */ {color:#8be9fd} pre code span.cf /* ControlFlow */ {color:#ff79c6} pre code span.ch /* Char */ {color:#f1fa8c} pre code span.cn /* Constant */ {color:#bd93f9; font-weight: bold} pre code span.co /* Comment */ {color:#6272a4} pre code span.cv /* CommentVar */ {color:#8be9fd} pre code span.do /* Documentation */ {color:#ffb86c} pre code span.dt /* DataType */ {color:#8be9fd; font-style: italic} pre code span.dv /* DecVal */ {color:#bd93f9} pre code span.er /* Error */ {color:#ff5555; text-decoration: underline} pre code span.ex /* Extension */ {color:#8be9fd} pre code span.fl /* Float */ {color:#bd93f9} pre code span.fu /* Function */ {color:#50fa7b} pre code span.im /* Import */ {color:#ff79c6} pre code span.in /* Information */ {color:#f1fa8c} pre code span.kw /* Keyword */ {color:#ff79c6} pre code span.op /* Operator */ {color:#f8f8f2} pre code span.ot /* Others */ {color:#50fa7b} pre code span.pp /* Preprocessor */ {color:#ff79c6} pre code span.re /* RegionMarker */ {color:#8be9fd} pre code span.sc /* SpecialChar */ {color:#ff79c6} pre code span.ss /* SpecialString */ {color:#f1fa8c} pre code span.st /* String */ {color:#f1fa8c} pre code span.va /* Variable */ {color:#8be9fd} pre code span.vs /* VerbatimString */ {color:#f1fa8c} pre code span.wa /* Warning */ {color:#ff5555} pkgdown/inst/highlight-styles/gruvbox-dark.scss0000644000176200001440000000361614246155422021513 0ustar liggesuserspre {background-color: #282828;} pre code /* Normal */ {color:#ebdbb2} pre code span.al /* Alert */ {color:#282828; background-color:#cc241d; font-weight: bold} pre code span.an /* Annotation */ {color:#98971a} pre code span.at /* Attribute */ {color:#d79921} pre code span.bn /* BaseN */ {color:#f67400} pre code span.bu /* BuiltIn */ {color:#d65d0e} pre code span.cf /* ControlFlow */ {color:#cc241d; font-weight: bold} pre code span.ch /* Char */ {color:#b16286} pre code span.cn /* Constant */ {color:#b16286; font-weight: bold} pre code span.co /* Comment */ {color:#928374} pre code span.cv /* CommentVar */ {color:#928374} pre code span.do /* Documentation */ {color:#98971a} pre code span.dt /* DataType */ {color:#d79921} pre code span.dv /* DecVal */ {color:#f67400} pre code span.er /* Error */ {color:#cc241d; text-decoration: underline} pre code span.ex /* Extension */ {color:#689d6a; font-weight: bold} pre code span.fl /* Float */ {color:#f67400} pre code span.fu /* Function */ {color:#689d6a} pre code span.im /* Import */ {color:#689d6a} pre code span.in /* Information */ {color:#282828; background-color:#83a598} pre code span.kw /* Keyword */ {color:#ebdbb2; font-weight: bold} pre code span.op /* Operator */ {color:#ebdbb2} pre code span.ot /* Others */ {color:#689d6a} pre code span.pp /* Preprocessor */ {color:#d65d0e} pre code span.re /* RegionMarker */ {color:#928374; background-color:#1d2021} pre code span.sc /* SpecialChar */ {color:#b16286} pre code span.ss /* SpecialString */ {color:#98971a} pre code span.st /* String */ {color:#98971a} pre code span.va /* Variable */ {color:#458588} pre code span.vs /* VerbatimString */ {color:#98971a} pre code span.wa /* Warning */ {color:#282828; background-color:#fabd2f} pkgdown/inst/highlight-styles/vim-dark.scss0000644000176200001440000000355514246155422020614 0ustar liggesuserspre {background-color: #000000;} pre code /* Normal */ {color:#b2b2b2} pre code span.al /* Alert */ {color:#ff0000; background-color:#3f0000; font-weight: bold} pre code span.an /* Annotation */ {color:#ff00ff} pre code span.at /* Attribute */ {color:#ffffaf} pre code span.bn /* BaseN */ {color:#ff8b8b} pre code span.bu /* BuiltIn */ {color:#87ffaf; font-weight: bold} pre code span.cf /* ControlFlow */ {color:#ffff54; font-weight: bold} pre code span.ch /* Char */ {color:#ff5454} pre code span.cn /* Constant */ {color:#af7f00; font-weight: bold} pre code span.co /* Comment */ {color:#54ffff} pre code span.cv /* CommentVar */ {color:#0095ff} pre code span.do /* Documentation */ {color:#e0ffff} pre code span.dt /* DataType */ {color:#ffff54} pre code span.dv /* DecVal */ {color:#ff8b8b} pre code span.er /* Error */ {color:#ff5500; text-decoration: underline} pre code span.ex /* Extension */ {color:#0095ff; font-weight: bold} pre code span.fl /* Float */ {color:#ff8b8b} pre code span.fu /* Function */ {color:#cd00cd} pre code span.im /* Import */ {color:#ff54ff} pre code span.in /* Information */ {color:#ffaa00} pre code span.kw /* Keyword */ {color:#5fd7ff; font-weight: bold} pre code span.op /* Operator */ {color:#b2b2b2} pre code span.ot /* Others */ {color:#54ff54} pre code span.pp /* Preprocessor */ {color:#87ffaf} pre code span.re /* RegionMarker */ {color:#0095ff; background-color:#22226d} pre code span.sc /* SpecialChar */ {color:#0095ff} pre code span.ss /* SpecialString */ {color:#ff5500} pre code span.st /* String */ {color:#ff54ff} pre code span.va /* Variable */ {color:#06989a} pre code span.vs /* VerbatimString */ {color:#ff54ff} pre code span.wa /* Warning */ {color:#ff0000} pkgdown/inst/highlight-styles/kate.scss0000644000176200001440000000355214246155422020023 0ustar liggesuserspre {background-color: #ffffff; color: #1f1c1b;} pre code /* Normal */ {color:#1f1c1b} pre code span.al /* Alert */ {color:#bf0303; background-color:#f7e6e6; font-weight: bold} pre code span.an /* Annotation */ {color:#ca60ca} pre code span.at /* Attribute */ {color:#0057ae} pre code span.bn /* BaseN */ {color:#b08000} pre code span.bu /* BuiltIn */ {color:#644a9b; font-weight: bold} pre code span.cf /* ControlFlow */ {color:#1f1c1b; font-weight: bold} pre code span.ch /* Char */ {color:#924c9d} pre code span.cn /* Constant */ {color:#aa5500} pre code span.co /* Comment */ {color:#898887} pre code span.cv /* CommentVar */ {color:#0095ff} pre code span.do /* Documentation */ {color:#607880} pre code span.dt /* DataType */ {color:#0057ae} pre code span.dv /* DecVal */ {color:#b08000} pre code span.er /* Error */ {color:#bf0303; text-decoration: underline} pre code span.ex /* Extension */ {color:#0095ff; font-weight: bold} pre code span.fl /* Float */ {color:#b08000} pre code span.fu /* Function */ {color:#644a9b} pre code span.im /* Import */ {color:#ff5500} pre code span.in /* Information */ {color:#b08000} pre code span.kw /* Keyword */ {color:#1f1c1b; font-weight: bold} pre code span.op /* Operator */ {color:#1f1c1b} pre code span.ot /* Other */ {color:#006e28} pre code span.pp /* Preprocessor */ {color:#006e28} pre code span.re /* RegionMarker */ {color:#0057ae; background-color:#e0e9f8} pre code span.sc /* SpecialChar */ {color:#3daee9} pre code span.ss /* SpecialString */ {color:#ff5500} pre code span.st /* String */ {color:#bf0303} pre code span.va /* Variable */ {color:#0057ae} pre code span.vs /* VerbatimString */ {color:#bf0303} pre code span.wa /* Warning */ {color:#bf0303} pkgdown/inst/highlight-styles/nord.scss0000644000176200001440000000355614246155422020045 0ustar liggesuserspre {background-color: #2e3440;} pre code /* Normal */ {color:#d8dee9} pre code span.al /* Alert */ {color:#bf616a; background-color:#3b4252; font-weight: bold} pre code span.an /* Annotation */ {color:#d08770} pre code span.at /* Attribute */ {color:#8fbcbb} pre code span.bn /* BaseN */ {color:#b48ead} pre code span.bu /* BuiltIn */ {color:#88c0d0; font-style: italic} pre code span.cf /* ControlFlow */ {color:#81a1c1; font-weight: bold} pre code span.ch /* Char */ {color:#ebcb8b} pre code span.cn /* Constant */ {color:#eceff4; font-weight: bold} pre code span.co /* Comment */ {color:#616e88} pre code span.cv /* CommentVar */ {color:#e5e9f0} pre code span.do /* Documentation */ {color:#5e81ac} pre code span.dt /* DataType */ {color:#81a1c1} pre code span.dv /* DecVal */ {color:#b48ead} pre code span.er /* Error */ {color:#bf616a; text-decoration: underline} pre code span.ex /* Extension */ {color:#8fbcbb; font-weight: bold} pre code span.fl /* Float */ {color:#b48ead} pre code span.fu /* Function */ {color:#88c0d0} pre code span.im /* Import */ {color:#a3be8c} pre code span.in /* Information */ {color:#ebcb8b} pre code span.kw /* Keyword */ {color:#81a1c1; font-weight: bold} pre code span.op /* Operator */ {color:#81a1c1} pre code span.ot /* Others */ {color:#8fbcbb} pre code span.pp /* Preprocessor */ {color:#5e81ac} pre code span.re /* RegionMarker */ {color:#88c0d0; background-color:#3b4252} pre code span.sc /* SpecialChar */ {color:#ebcb8b} pre code span.ss /* SpecialString */ {color:#d08770} pre code span.st /* String */ {color:#a3be8c} pre code span.va /* Variable */ {color:#5e81ac} pre code span.vs /* VerbatimString */ {color:#a3be8c} pre code span.wa /* Warning */ {color:#bf616a} pkgdown/inst/highlight-styles/github-dark.scss0000644000176200001440000000335514246155422021301 0ustar liggesuserspre {background-color: #24292e;} pre code /* Normal */ {color:#e1e4e8} pre code span.al /* Alert */ {color:#ff5555; font-weight: bold} pre code span.an /* Annotation */ {color:#6a737d} pre code span.at /* Attribute */ {color:#f97583} pre code span.bn /* BaseN */ {color:#79b8ff} pre code span.bu /* BuiltIn */ {color:#f97583} pre code span.cf /* ControlFlow */ {color:#f97583} pre code span.ch /* Char */ {color:#9ecbff} pre code span.cn /* Constant */ {color:#79b8ff} pre code span.co /* Comment */ {color:#6a737d} pre code span.cv /* CommentVar */ {color:#6a737d} pre code span.do /* Documentation */ {color:#6a737d} pre code span.dt /* DataType */ {color:#f97583} pre code span.dv /* DecVal */ {color:#79b8ff} pre code span.er /* Error */ {color:#ff5555; text-decoration: underline} pre code span.ex /* Extension */ {color:#f97583; font-weight: bold} pre code span.fl /* Float */ {color:#79b8ff} pre code span.fu /* Function */ {color:#b392f0} pre code span.im /* Import */ {color:#9ecbff} pre code span.in /* Information */ {color:#6a737d} pre code span.kw /* Keyword */ {color:#f97583} pre code span.op /* Operator */ {color:#e1e4e8} pre code span.ot /* Others */ {color:#b392f0} pre code span.pp /* Preprocessor */ {color:#f97583} pre code span.re /* RegionMarker */ {color:#6a737d} pre code span.sc /* SpecialChar */ {color:#79b8ff} pre code span.ss /* SpecialString */ {color:#9ecbff} pre code span.st /* String */ {color:#9ecbff} pre code span.va /* Variable */ {color:#ffab70} pre code span.vs /* VerbatimString */ {color:#9ecbff} pre code span.wa /* Warning */ {color:#ff5555} pkgdown/inst/highlight-styles/atom-one-light.scss0000644000176200001440000000345014245770621021723 0ustar liggesuserspre code /* Normal */ {color:#383a42} pre code span.al /* Alert */ {color:#95da4c; background-color:#4d1f24; font-weight: bold} pre code span.an /* Annotation */ {color:#50a14f} pre code span.at /* Attribute */ {color:#a626a4} pre code span.bn /* BaseN */ {color:#986801} pre code span.bu /* BuiltIn */ {color:#a626a4} pre code span.cf /* ControlFlow */ {color:#a626a4} pre code span.ch /* Char */ {color:#50a14f} pre code span.cn /* Constant */ {color:#986801} pre code span.co /* Comment */ {color:#a0a1a7; font-style: italic} pre code span.cv /* CommentVar */ {color:#e45649; font-style: italic} pre code span.do /* Documentation */ {color:#e45649} pre code span.dt /* DataType */ {color:#a626a4} pre code span.dv /* DecVal */ {color:#986801} pre code span.er /* Error */ {color:#f44747; text-decoration: underline} pre code span.ex /* Extension */ {color:#4078f2; font-weight: bold} pre code span.fl /* Float */ {color:#986801} pre code span.fu /* Function */ {color:#4078f2} pre code span.im /* Import */ {color:#50a14f} pre code span.in /* Information */ {color:#c45b00} pre code span.kw /* Keyword */ {color:#a626a4} pre code span.op /* Operator */ {color:#a626a4} pre code span.ot /* Others */ {color:#27ae60} pre code span.pp /* Preprocessor */ {color:#a626a4} pre code span.re /* RegionMarker */ {color:#2980b9; background-color:#153042} pre code span.sc /* SpecialChar */ {color:#0184bc} pre code span.ss /* SpecialString */ {color:#da4453} pre code span.st /* String */ {color:#50a14f} pre code span.va /* Variable */ {color:#e45649} pre code span.vs /* VerbatimString */ {color:#da4453} pre code span.wa /* Warning */ {color:#da4453} pkgdown/inst/highlight-styles/ayu-dark.scss0000644000176200001440000000353314246155422020613 0ustar liggesuserspre {background-color: #0a0e14;} pre code /* Normal */ {color:#b3b1ad} pre code span.al /* Alert */ {color:#ff3333; background-color:#2a0f15; font-weight: bold} pre code span.an /* Annotation */ {color:#e6b673} pre code span.at /* Attribute */ {color:#59c2ff} pre code span.bn /* BaseN */ {color:#e6b450} pre code span.bu /* BuiltIn */ {color:#95e6cb} pre code span.cf /* ControlFlow */ {color:#ff8f40; font-weight: bold} pre code span.ch /* Char */ {color:#95e6cb} pre code span.cn /* Constant */ {color:#ffee99} pre code span.co /* Comment */ {color:#626a73; font-style: italic} pre code span.cv /* CommentVar */ {color:#ffee99} pre code span.do /* Documentation */ {color:#626a73} pre code span.dt /* DataType */ {color:#ff8f40} pre code span.dv /* DecVal */ {color:#e6b450} pre code span.er /* Error */ {color:#ff3333; text-decoration: underline} pre code span.ex /* Extension */ {color:#59c2ff; font-weight: bold} pre code span.fl /* Float */ {color:#e6b450} pre code span.fu /* Function */ {color:#ffb454} pre code span.im /* Import */ {color:#c2d94c} pre code span.in /* Information */ {color:#e6b450} pre code span.kw /* Keyword */ {color:#ff8f40; font-weight: bold} pre code span.op /* Operator */ {color:#f29668} pre code span.ot /* Others */ {color:#39bae6} pre code span.pp /* Preprocessor */ {color:#f07178} pre code span.re /* RegionMarker */ {color:#59c2ff; background-color:#173649} pre code span.sc /* SpecialChar */ {color:#95e6cb} pre code span.ss /* SpecialString */ {color:#95e6cb} pre code span.st /* String */ {color:#c2d94c} pre code span.va /* Variable */ {color:#39bae6} pre code span.vs /* VerbatimString */ {color:#c2d94c} pre code span.wa /* Warning */ {color:#f07178} pkgdown/inst/highlight-styles/arrow-dark.scss0000644000176200001440000000347214633374223021153 0ustar liggesuserspre code /* Normal */ {color:#f8f8f2} pre code span.al /* Alert */ {color:#f07178; background-color:#2a0f15; font-weight: bold} pre code span.an /* Annotation */ {color:#d4d0ab} pre code span.at /* Attribute */ {color:#00e0e0} pre code span.bn /* BaseN */ {color:#d4d0ab} pre code span.bu /* BuiltIn */ {color:#abe338} pre code span.cf /* ControlFlow */ {color:#ffa07a; font-weight: bold} pre code span.ch /* Char */ {color:#abe338} pre code span.cn /* Constant */ {color:#ffd700} pre code span.co /* Comment */ {color:#f8f8f2; font-style: italic} pre code span.cv /* CommentVar */ {color:#ffd700} pre code span.do /* Documentation */ {color:#f8f8f2} pre code span.dt /* DataType */ {color:#ffa07a} pre code span.dv /* DecVal */ {color:#d4d0ab} pre code span.er /* Error */ {color:#f07178; text-decoration: underline} pre code span.ex /* Extension */ {color:#00e0e0; font-weight: bold} pre code span.fl /* Float */ {color:#d4d0ab} pre code span.fu /* Function */ {color:#ffa07a} pre code span.im /* Import */ {color:#abe338} pre code span.in /* Information */ {color:#d4d0ab} pre code span.kw /* Keyword */ {color:#ffa07a; font-weight: bold} pre code span.op /* Operator */ {color:#ffa07a} pre code span.ot /* Other */ {color:#00e0e0} pre code span.pp /* Preprocessor */ {color:#dcc6e0} pre code span.re /* RegionMarker */ {color:#00e0e0; background-color:#f8f8f2} pre code span.sc /* SpecialChar */ {color:#abe338} pre code span.ss /* SpecialString */ {color:#abe338} pre code span.st /* String */ {color:#abe338} pre code span.va /* Variable */ {color:#00e0e0} pre code span.vs /* VerbatimString */ {color:#abe338} pre code span.wa /* Warning */ {color:#dcc6e0} pkgdown/inst/highlight-styles/atom-one-dark.scss0000644000176200001440000000345014245770621021535 0ustar liggesuserspre code /* Normal */ {color:#abb2bf} pre code span.al /* Alert */ {color:#95da4c; background-color:#4d1f24; font-weight: bold} pre code span.an /* Annotation */ {color:#98c379} pre code span.at /* Attribute */ {color:#c678dd} pre code span.bn /* BaseN */ {color:#d19a66} pre code span.bu /* BuiltIn */ {color:#c678dd} pre code span.cf /* ControlFlow */ {color:#c678dd} pre code span.ch /* Char */ {color:#98c379} pre code span.cn /* Constant */ {color:#d19a66} pre code span.co /* Comment */ {color:#5c6370; font-style: italic} pre code span.cv /* CommentVar */ {color:#e06c75; font-style: italic} pre code span.do /* Documentation */ {color:#a43340} pre code span.dt /* DataType */ {color:#c678dd} pre code span.dv /* DecVal */ {color:#d19a66} pre code span.er /* Error */ {color:#f44747; text-decoration: underline} pre code span.ex /* Extension */ {color:#61afef; font-weight: bold} pre code span.fl /* Float */ {color:#d19a66} pre code span.fu /* Function */ {color:#61afef} pre code span.im /* Import */ {color:#98c379} pre code span.in /* Information */ {color:#c45b00} pre code span.kw /* Keyword */ {color:#c678dd} pre code span.op /* Operator */ {color:#c678dd} pre code span.ot /* Others */ {color:#27ae60} pre code span.pp /* Preprocessor */ {color:#c678dd} pre code span.re /* RegionMarker */ {color:#2980b9; background-color:#153042} pre code span.sc /* SpecialChar */ {color:#56b6c2} pre code span.ss /* SpecialString */ {color:#da4453} pre code span.st /* String */ {color:#98c379} pre code span.va /* Variable */ {color:#e06c75} pre code span.vs /* VerbatimString */ {color:#da4453} pre code span.wa /* Warning */ {color:#da4453} pkgdown/inst/highlight-styles/solarized-dark.scss0000644000176200001440000000343314134110660021777 0ustar liggesuserspre {background-color: #002b36;} pre code /* Normal */ {color:#839496} pre code span.al /* Alert */ {color:#d33682; font-weight: bold} pre code span.an /* Annotation */ {color:#268bd2} pre code span.at /* Attribute */ {color:#268bd2} pre code span.bn /* BaseN */ {color:#2aa198} pre code span.bu /* BuiltIn */ {color:#cb4b16} pre code span.cf /* ControlFlow */ {color:#859900} pre code span.ch /* Char */ {color:#2aa198} pre code span.cn /* Constant */ {color:#2aa198; font-weight: bold} pre code span.co /* Comment */ {color:#586e75; font-style: italic} pre code span.cv /* CommentVar */ {color:#2aa198} pre code span.do /* Documentation */ {color:#dc322f} pre code span.dt /* DataType */ {color:#b58900} pre code span.dv /* DecVal */ {color:#2aa198} pre code span.er /* Error */ {color:#dc322f; text-decoration: underline} pre code span.ex /* Extension */ {color:#268bd2} pre code span.fl /* Float */ {color:#2aa198} pre code span.fu /* Function */ {color:#268bd2} pre code span.im /* Import */ {color:#2aa198} pre code span.in /* Information */ {color:#b58900} pre code span.kw /* Keyword */ {color:#859900} pre code span.op /* Operator */ {color:#859900} pre code span.ot /* Others */ {color:#859900} pre code span.pp /* Preprocessor */ {color:#cb4b16} pre code span.re /* RegionMarker */ {color:#268bd2; background-color:#073642} pre code span.sc /* SpecialChar */ {color:#dc322f} pre code span.ss /* SpecialString */ {color:#dc322f} pre code span.st /* String */ {color:#2aa198} pre code span.va /* Variable */ {color:#268bd2} pre code span.vs /* VerbatimString */ {color:#2aa198} pre code span.wa /* Warning */ {color:#cb4b16} pkgdown/inst/highlight-styles/solarized-light.scss0000644000176200001440000000354714134110660022173 0ustar liggesuserspre {background-color: #fdf6e3;} pre code /* Normal */ {color:#657b83} pre code span.al /* Alert */ {color:#d33682; font-weight: bold} pre code span.an /* Annotation */ {color:#268bd2} pre code span.at /* Attribute */ {color:#268bd2} pre code span.bn /* BaseN */ {color:#2aa198} pre code span.bu /* BuiltIn */ {color:#cb4b16} pre code span.cf /* ControlFlow */ {color:#859900; font-weight: bold} pre code span.ch /* Char */ {color:#2aa198} pre code span.cn /* Constant */ {color:#2aa198; font-weight: bold} pre code span.co /* Comment */ {color:#93a1a1; font-style: italic} pre code span.cv /* CommentVar */ {color:#2aa198} pre code span.do /* Documentation */ {color:#dc322f} pre code span.dt /* DataType */ {color:#b58900; font-weight: bold} pre code span.dv /* DecVal */ {color:#2aa198} pre code span.er /* Error */ {color:#dc322f; text-decoration: underline} pre code span.ex /* Extension */ {color:#268bd2; font-weight: bold} pre code span.fl /* Float */ {color:#2aa198} pre code span.fu /* Function */ {color:#268bd2} pre code span.im /* Import */ {color:#2aa198} pre code span.in /* Information */ {color:#b58900} pre code span.kw /* Keyword */ {color:#859900; font-weight: bold} pre code span.op /* Operator */ {color:#859900} pre code span.ot /* Others */ {color:#859900} pre code span.pp /* Preprocessor */ {color:#cb4b16} pre code span.re /* RegionMarker */ {color:#268bd2; background-color:#eee8d5} pre code span.sc /* SpecialChar */ {color:#dc322f} pre code span.ss /* SpecialString */ {color:#dc322f} pre code span.st /* String */ {color:#2aa198} pre code span.va /* Variable */ {color:#268bd2} pre code span.vs /* VerbatimString */ {color:#2aa198} pre code span.wa /* Warning */ {color:#cb4b16} pkgdown/README.md0000644000176200001440000000721415100736010013177 0ustar liggesusers # pkgdown pkgdown website CRAN Status R-CMD-check [![Codecov test coverage](https://codecov.io/gh/r-lib/pkgdown/graph/badge.svg)](https://app.codecov.io/gh/r-lib/pkgdown) pkgdown is designed to make it quick and easy to build a website for your package. You can see pkgdown in action at : this is the output of pkgdown applied to the latest version of pkgdown. Learn more in `vignette("pkgdown")` or `?build_site`. ## Installation
    ``` r # Install released version from CRAN install.packages("pkgdown") ```
    ``` r # Install development version from GitHub # install.packages("pak") pak::pak("r-lib/pkgdown") ```
    ## Usage Get started with [usethis](https://usethis.r-lib.org/): ``` r # Run once to configure your package to use and deploy pkgdown usethis::use_pkgdown_github_pages() ``` ``` r # Preview your site locally before publishing pkgdown::build_site() ``` This adds the necessary components and sets up GitHub Actions[^1] for automatic site building when deploying. Your `README.md` becomes the homepage, documentation in `man/` generates a function reference, and vignettes will be rendered into `articles/`. ### pkgdown 2.0.0 and Bootstrap 5 pkgdown 2.0.0 includes an upgrade from Bootstrap 3 to Bootstrap 5, which is accompanied by a whole bunch of minor UI improvements. If you’ve heavily customised your site, there’s a small chance that this will break your site, so everyone needs to explicitly opt-in to the upgrade by adding the following to `_pkgdown.yml`: ``` yaml template: bootstrap: 5 ``` Then learn about the many new ways to customise your site in `vignette("customise")`. ## In the wild At last count, pkgdown is used [by over 12,000 packages](https://github.com/search?q=path%3A_pkgdown.yml+language%3AYAML&type=code&l=YAML). Here are a few examples: - [bayesplot](http://mc-stan.org/bayesplot/index.html) ([source](https://github.com/stan-dev/bayesplot/tree/gh-pages)): plotting functions for posterior analysis, model checking, and MCMC diagnostics. - [valr](https://rnabioco.github.io/valr/) ([source](https://github.com/rnabioco/valr)): read and manipulate genome intervals and signals. - [mkin](https://pkgdown.jrwb.de/mkin/) ([source](https://github.com/jranke/mkin)): calculation routines based on the FOCUS Kinetics Report - [NMF](http://renozao.github.io/NMF/master/index.html) ([source](https://github.com/renozao/NMF)): a framework to perform non-negative matrix factorization (NMF). - [tidyverse and r-lib packages source](https://github.com/search?q=path%3A%22_pkgdown.yml%22+AND+%28org%3Atidyverse+OR+org%3Ar-lib%29&type=code) Comparing the source and output of these sites is a great way to learn new pkgdown techniques. ## Code of conduct Please note that this project is released with a [Contributor Code of Conduct](https://pkgdown.r-lib.org/CODE_OF_CONDUCT.html). By participating in this project you agree to abide by its terms. [^1]: If you don’t use GitHub, you can use `usethis::use_pkgdown()` + `pkgdown::build_site()` to create a website. pkgdown/build/0000755000176200001440000000000015102677757013043 5ustar liggesuserspkgdown/build/vignette.rds0000644000176200001440000000064115102677757015403 0ustar liggesusersRMS0,P*c@ 806B6$͟IL!rࢇ&do]ߴav h{ױ!"5 7,FeȔkC#lSBF5C n%\X 2C!֫E,sQT.FxwQehc`8ȓ)G#AD8* _}F8 ōN \1GJ@A aDuՌIsyt~ ,( †KFyBNR'PrM2OcjDyVdO@Ϧi)O 97:i ^Lؚ~f\*>Q2c/[v)({yIrpkgdown/build/stage23.rdb0000644000176200001440000000550615102677751015004 0ustar liggesusers\r(RDH[XXoumn:rǝRHxR4XR@@[ƝJOt:yX.(hfuŃ=o^ !ÿ [ÿa*\>gELo^Ȗ][m;ȸӬf0:R5|q  d3Ե Ε;{?}}Vر%7ini<Y5Ƅw϶0rd(&\!wt[ \jWZآ2ɿ? |j[ b}t9j $6ƴ7,[{pVCĿh6VOջ~ܑzа;htebtdۮhGd2{x0Q"r8_6^} H|bMQhDne?%2kGj*.2\Luыalx̀^Q5)dNEcuovr#.t$q$q~c!7) gR @7O$I5ى;tdQ(9DyBK cNq'Ӭ4, |u<$0 |3EP;K࿌74g>LVG%贚( -!CZ&C -_<@kQRW˒,ȉAA㏮Oi%bR C[( R~ NoYkě2Ɇw-.rjO׌AmhŒPwI*e D9kTlԔS P t<'Zgƃ2@'[WN Ћ_L,TpcWڐN%ؐF"$)mHモcL qX@:=91-,ue4Gm.ʀ2&40pAMqA_z Kb@\T]wڨX$|3W*V +B'$Qay>1:O i_P-**lQQ$T@BeXQaR0bO#+f%!'4V^>QU| ?z+CA+HZzltTUiڜz' O:jlQDfLQDԦÒm @c(zD;aʭՂ:%, k@aaPX*,J,#%Z7Ԏ U)i:.c KwlKAHyU<D}&{7bDв0sZNPFhm2}2l ]{eRIA3\dӪ BWOn]A:DFhޜ:-D}В`D*#\~^AHP%{m(ݕ$G {L‹2GfQ"}HE )s`nWGYF)} e, d=LjK{E$t90B*ktQrz-)sPs>(f= >dc%yɴ \|Bk>چHl jLC3ߜ$B-SWG8QHwGܻEIWqm3hռ^C"Kx<;T5E<d@}/=ZHM@sQFg%X2TH/e^U(&2Yl5=7[smY. .^%> #W8xG9gBJp?&N^&pqiwF<-@F$iZ QB8#R4Y<2Pޟ8pB򒨾B/-+m:Ejvc[Ip7gvu )<ռg pO Y \42-]ˑoO6#c%ņѸƄNr=DU=[9Mrjq|09 3E9NjЂX,f^Y l%Ng7Lј53Þ@bռi:a"Y5 FxUI¥1j)<"9¼d!vL|Ķ0t `"/mtyl7~hc4ul;05+߸u/?rz |{/mos9K{($' {Jk9F#nctwLӀ119Rpq .@ dlJ]SyE߳% \94"o"n" q8J熪yK4"ui}q!Hmw_?2X$XES6Dǃ? UtXWC>F{9xLJ=J)ֶXY_99~!k(}}\preformatted{# foofy 1.0.0 ## Major changes * Can now work with all grooveable grobbles! ## Minor improvements and bug fixes * Printing scrobbles no longer errors (@githubusername, #100) * Wibbles are now 55\% less jibbly (#200) }\if{html}{\out{
    }} Issues and contributors will be automatically linked to the corresponding pages on GitHub if the GitHub repo can be discovered from the \code{DESCRIPTION} (typically from a \code{URL} entry containing \code{github.com}) If a version is available on CRAN, the release date will automatically be added to the heading (see below for how to suppress); if not available on CRAN, "Unreleased" will be added. } \section{YAML config}{ To automatically link to release announcements, include a \code{releases} section. \if{html}{\out{
    }}\preformatted{news: releases: - text: "usethis 1.3.0" href: https://www.tidyverse.org/articles/2018/02/usethis-1-3-0/ - text: "usethis 1.0.0 (and 1.1.0)" href: https://www.tidyverse.org/articles/2017/11/usethis-1.0.0/ }\if{html}{\out{
    }} Control whether news is present on one page or multiple pages with the \code{one_page} field. The default is \code{true}. \if{html}{\out{
    }}\preformatted{news: one_page: false }\if{html}{\out{
    }} Suppress the default addition of CRAN release dates with: \if{html}{\out{
    }}\preformatted{news: cran_dates: false }\if{html}{\out{
    }} } \seealso{ \href{https://style.tidyverse.org/news.html}{Tidyverse style for News} Other site components: \code{\link{build_articles}()}, \code{\link{build_home}()}, \code{\link{build_llm_docs}()}, \code{\link{build_reference}()}, \code{\link{build_tutorials}()} } \concept{site components} pkgdown/man/test-verbatim.Rd0000644000176200001440000000260314740246027015562 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/test.R \name{test-verbatim} \alias{test-verbatim} \title{Test case: preformatted blocks & syntax highlighting} \description{ Manual test cases for various ways of embedding code in sections. All code blocks should have copy and paste button. } \section{Should be highlighted}{ Valid R code in \verb{\preformatted{}}: \if{html}{\out{
    }}\preformatted{mean(a + 1) }\if{html}{\out{
    }} R code in \code{R} block: \if{html}{\out{
    }}\preformatted{mean(a + 1) }\if{html}{\out{
    }} R code in \code{r} block: \if{html}{\out{
    }}\preformatted{mean(a + 1) }\if{html}{\out{
    }} Yaml \if{html}{\out{
    }}\preformatted{yaml: [a, 1] }\if{html}{\out{
    }} } \section{Shouldn't be highlighted}{ Non-R code in \verb{\preformatted{}} \if{html}{\out{
    }}\preformatted{yaml: [a, b, c] }\if{html}{\out{
    }} } \seealso{ Other tests: \code{\link{index}}, \code{\link{test-crayon}}, \code{\link{test-dont}}, \code{\link{test-figures}}, \code{\link{test-links}}, \code{\link{test-lists}}, \code{\link{test-long-lines}}, \code{\link{test-math-examples}}, \code{\link{test-output-styles}}, \code{\link{test-params}}, \code{\link{test-sexpr-title}}, \code{\link{test-tables}} } \concept{tests} \keyword{internal} pkgdown/man/test-lists.Rd0000644000176200001440000000376514740246027015121 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/test.R \name{test-lists} \alias{test-lists} \title{Test case: lists} \description{ \subsection{Bulleted list}{ \itemize{ \item a \item This is an item... That spans multiple paragraphs. } } \subsection{Bulleted list (single item)}{ \itemize{\item a} } \subsection{Numbered list}{ \enumerate{ \item a \item b } } \subsection{Definition list}{ \describe{ \item{short}{short} \item{short}{Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.} \item{Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.}{short} \item{Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.}{Lorem ipsum adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.} } } } \seealso{ Other tests: \code{\link{index}}, \code{\link{test-crayon}}, \code{\link{test-dont}}, \code{\link{test-figures}}, \code{\link{test-links}}, \code{\link{test-long-lines}}, \code{\link{test-math-examples}}, \code{\link{test-output-styles}}, \code{\link{test-params}}, \code{\link{test-sexpr-title}}, \code{\link{test-tables}}, \code{\link{test-verbatim}} } \concept{tests} \keyword{internal} pkgdown/man/build_home.Rd0000644000176200001440000002706415100735002015076 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/build-home.R, R/build-home-index.R \name{build_home} \alias{build_home} \alias{build_home_index} \title{Build home section} \usage{ build_home(pkg = ".", override = list(), preview = FALSE, quiet = TRUE) build_home_index(pkg = ".", override = list(), quiet = TRUE) } \arguments{ \item{pkg}{Path to package.} \item{override}{An optional named list used to temporarily override values in \verb{_pkgdown.yml}} \item{preview}{If \code{TRUE}, or \code{is.na(preview) && interactive()}, will preview freshly generated section in browser.} \item{quiet}{Set to \code{FALSE} to display output of knitr and pandoc. This is useful when debugging.} } \description{ \code{build_home()} function generates pages at the top-level of the site including: \itemize{ \item The home page \item HTML files from any \code{.md} files in \verb{./} or \verb{.github/}. \item The authors page (from \code{DESCRIPTION}) \item The citation page (from \code{inst/CITATION}, if present). \item The license page \item A default 404 page if \verb{.github/404.md} is not found. } \code{build_home_index()} rebuilds just the index page; it's useful for rapidly iterating when experimenting with site styles. } \section{Home page}{ The main content of the home page (\code{index.html}) is generated from \code{pkgdown/index.md}, \code{index.md}, or \code{README.md}, in that order. Most packages will use \code{README.md} because that's also displayed by GitHub and CRAN. Use \code{index.md} if you want your package website to look different to your README, and use \code{pkgdown/index.md} if you don't want that file to live in your package root directory. If you use \code{index.Rmd} or \code{README.Rmd} it's your responsibility to knit the document to create the corresponding \code{.md}. pkgdown does not do this for you because it only touches files in the \verb{doc/} directory. Extra markdown files in the base directory (e.g. \code{ROADMAP.md}) or in \verb{.github/} (e.g. \code{CODE_OF_CONDUCT.md}) are copied by \code{build_home()} to \verb{docs/} and converted to HTML. The home page also features a sidebar with information extracted from the package. You can tweak it via the configuration file, to help make the home page an as informative as possible landing page. \subsection{Images and figures}{ If you want to include images in your \code{README.md}, they must be stored somewhere in the package so that they can be displayed on the CRAN website. The best place to put them is \code{man/figures}. If you are generating figures with R Markdown, make sure you set up \code{fig.path} as followed: \if{html}{\out{
    }}\preformatted{knitr::opts_chunk$set( fig.path = "man/figures/" ) }\if{html}{\out{
    }} This should usually go in a chunk with \code{include = FALSE}. \if{html}{\out{
    }}\preformatted{```\{r chunk-name, include=FALSE\}`r ''` knitr::opts_chunk$set( fig.path = "man/figures/" ) ``` }\if{html}{\out{
    }} } \subsection{Package logo}{ If you have a package logo, you can include it at the top of your README in a level-one heading: \if{html}{\out{
    }}\preformatted{# pkgdown }\if{html}{\out{
    }} \code{\link[=init_site]{init_site()}} will also automatically create a favicon set from your package logo. } \subsection{YAML config - title and description}{ By default, the page title and description are extracted automatically from the \code{Title} and \code{Description} fields \code{DESCRIPTION} (stripping single quotes off quoted words). CRAN ensures that these fields don't contain phrases like "R package" because that's obvious on CRAN. To make your package more findable on search engines, it's good practice to override the \code{title} and \code{description}, thinking about what people might search for: \if{html}{\out{
    }}\preformatted{home: title: An R package for pool-noodle discovery description: > Do you love R? Do you love pool-noodles? If so, you might enjoy using this package to automatically discover and add pool-noodles to your growing collection. }\if{html}{\out{
    }} (Note the use of YAML's \code{>} i.e. "YAML pipes"; this is a convenient way of writing paragraphs of text.) } \subsection{Dev badges}{ pkgdown identifies badges in three ways: \itemize{ \item Any image-containing links between \verb{} and \verb{}, as e.g. created by \code{usethis::use_readme_md()} or \code{usethis::use_readme_rmd()}. There should always be an empty line after the \verb{} line. If you divide badges into paragraphs, make sure to add an empty line before the \verb{} line. \item Any image-containing links within \verb{
    }. \item Within the first paragraph, if it only contains image-containing links. } Identified badges are \strong{removed} from the \emph{main content}. They are shown or not in the \emph{sidebar} depending on the development mode and sidebar customization, see the sidebar section. } } \section{Authors}{ By default, pkgdown will display author information in three places: \itemize{ \item the sidebar, \item the left part side of the footer, \item the author page. } This documentation describes how to customise the overall author display. See \code{?build_home} and \code{?build_site} for details about changing the location of the authors information within the home sidebar and the site footer. \subsection{Authors ORCID, ROR and bio}{ Author ORCID identification numbers in the \code{DESCRIPTION} are linked using the ORCID logo, author ROR identification numbers are linked using the ROR logo: \if{html}{\out{
    }}\preformatted{Authors@R: c( person("Hadley", "Wickham", , "hadley@rstudio.com", role = c("aut", "cre"), comment = c(ORCID = "0000-0003-4757-117X") ), person("Jay", "Hesselberth", role = "aut", comment = c(ORCID = "0000-0002-6299-179X") ), person("Posit Software, PBC", role = c("cph", "fnd"), comment = c(ROR = "03wc8by49")) ) }\if{html}{\out{
    }} If you want to add more details about authors or their involvement with the package, you can use the comment field, which will be rendered on the authors page. \if{html}{\out{
    }}\preformatted{Authors@R: c( person("Hadley", "Wickham", , "hadley@rstudio.com", role = c("aut", "cre"), comment = c(ORCID = "0000-0003-4757-117X", "Indenter-in-chief") ), person("Jay", "Hesselberth", role = "aut", comment = c(ORCID = "0000-0002-6299-179X") ) ) }\if{html}{\out{
    }} } \subsection{Additional control via YAML}{ You can control additional aspects of the authors display via the \code{authors} YAML field: \itemize{ \item display of each author in the footer, sidebar and authors page, \item which authors (by role) are displayed in the sidebar and footer, \item text before authors in the footer, \item text before and after authors in the sidebar, \item text before and after authors on the authors page. } You can modify how each author's name is displayed by adding a subsection for \code{authors}. Each entry in \code{authors} should be named the author's name (matching \code{DESCRIPTION}) and can contain \code{href} and/or \code{html} fields: \itemize{ \item If \code{href} is provided, the author's name will be linked to this URL. \item If \code{html} is provided, it will be shown instead of the author's name. This is particularly useful if you want to display the logo of a corporate sponsor. Use an absolute URL to an image, not a relative link. Use an empty alternative text rather than no alternative text so a screen-reader would skip over it. } \if{html}{\out{
    }}\preformatted{authors: firstname lastname: href: "http://name-website.com" html: "" }\if{html}{\out{
    }} By default, the "developers" list shown in the sidebar and footer is populated by the maintainer ("cre"), authors ("aut"), and funder ("fnd") from the \code{DESCRIPTION}. You could choose other roles for filtering. With the configuration below: \itemize{ \item only the maintainer and funder(s) appear in the footer, after the text "Crafted by", \item all authors and contributors appear in the sidebar, \item the authors list on the sidebar is preceded and followed by some text, \item the authors list on the authors page is preceded and followed by some text. } \if{html}{\out{
    }}\preformatted{authors: footer: roles: [cre, fnd] text: "Crafted by" sidebar: roles: [aut, ctb] before: "So *who* does the work?" after: "Thanks all!" before: "This package is proudly brought to you by:" after: "See the [changelog](news/index.html) for other contributors. :pray:" }\if{html}{\out{
    }} If you want to filter authors based on something else than their roles, consider using a custom sidebar/footer component (see \code{?build_home}/\code{?build_site}, respectively). } } \section{Sidebar}{ You can customise the homepage sidebar with the \code{home.sidebar} field. It's made up of two pieces: \code{structure}, which defines the overall layout, and \code{components}, which defines what each piece looks like. This organisation makes it easy to mix and match the pkgdown defaults with your own customisations. This is the default structure: \if{html}{\out{
    }}\preformatted{home: sidebar: structure: [links, license, community, citation, authors, dev] }\if{html}{\out{
    }} These are drawn from seven built-in components: \itemize{ \item \code{links}: automated links generated from \code{URL} and \code{BugReports} fields from \code{DESCRIPTION} plus manual links from the \code{home.links} field: \if{html}{\out{
    }}\preformatted{home: links: - text: Link text href: https://website.com - text: Roadmap href: /roadmap.html }\if{html}{\out{
    }} \item \code{license}: Licensing information if \code{LICENSE}/\code{LICENCE} or \code{LICENSE.md}/\code{LICENCE.md} files are present. \item \code{community}: links to to \code{.github/CONTRIBUTING.md}, \code{.github/CODE_OF_CONDUCT.md}, etc. \item \code{citation}: link to package citation information. Uses either \code{inst/CITATION} or, if absent, information from the \code{DESCRIPTION}. \item \code{authors}: selected authors from the \code{DESCRIPTION}. \item \code{dev}: development status badges extracted from \code{README.md}/\code{index.md}. This is only shown for "development" versions of websites; see "Development mode" in \code{?build_site} for details. \item \code{toc}: a table of contents for the README (not shown by default). } You can also add your own components, where \code{text} is markdown text: \if{html}{\out{
    }}\preformatted{home: sidebar: structure: [authors, custom, toc, dev] components: custom: title: Funding text: We are *grateful* for funding! }\if{html}{\out{
    }} Alternatively, you can provide a ready-made sidebar HTML: \if{html}{\out{
    }}\preformatted{home: sidebar: html: path-to-sidebar.html }\if{html}{\out{
    }} Or completely remove it: \if{html}{\out{
    }}\preformatted{home: sidebar: FALSE }\if{html}{\out{
    }} } \seealso{ Other site components: \code{\link{build_articles}()}, \code{\link{build_llm_docs}()}, \code{\link{build_news}()}, \code{\link{build_reference}()}, \code{\link{build_tutorials}()} } \concept{site components} pkgdown/man/as_pkgdown.Rd0000644000176200001440000000102714605012704015120 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/package.R \name{as_pkgdown} \alias{as_pkgdown} \title{Generate pkgdown data structure} \usage{ as_pkgdown(pkg = ".", override = list()) } \arguments{ \item{pkg}{Path to package.} \item{override}{An optional named list used to temporarily override values in \verb{_pkgdown.yml}} } \description{ You will generally not need to use this unless you need a custom site design and you're writing your own equivalent of \code{\link[=build_site]{build_site()}}. } pkgdown/man/fig_settings.Rd0000644000176200001440000000152214633374223015461 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/figure.R \name{fig_settings} \alias{fig_settings} \title{Get current settings for figures} \usage{ fig_settings() } \value{ A list containing the entries from the \code{figures} field in \verb{_pkgdown.yml} (see \code{\link[=build_reference]{build_reference()}}), with default values added. Computed \code{width} and \code{height} values (in pixels) are also included. } \description{ You will generally not need to use this function unless you are handling custom plot output. Packages needing custom parameters should ask users to place them within the \code{other.parameters} entry under the package name, e.g. \if{html}{\out{
    }}\preformatted{figures: other.parameters: rgl: fig.asp: 1 }\if{html}{\out{
    }} } \keyword{internal} pkgdown/man/build_redirects.Rd0000644000176200001440000000253214633374223016141 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/build-redirects.R \name{build_redirects} \alias{build_redirects} \title{Build redirects} \usage{ build_redirects(pkg = ".", override = list()) } \arguments{ \item{pkg}{Path to package.} \item{override}{An optional named list used to temporarily override values in \verb{_pkgdown.yml}} } \description{ If you change the structure of your documentation (by renaming vignettes or help topics) you can setup redirects from the old content to the new content. One or several now-absent pages can be redirected to a new page (or to a new section of a new page). This works by creating a html page that performs a "meta refresh", which isn't the best way of doing a redirect but works everywhere that you might deploy your site. The syntax is the following, with old paths on the left, and new paths or URLs on the right. \if{html}{\out{
    }}\preformatted{redirects: - ["articles/old-vignette-name.html", "articles/new-vignette-name.html"] - ["articles/another-old-vignette-name.html", "articles/new-vignette-name.html"] - ["articles/yet-another-old-vignette-name.html", "https://pkgdown.r-lib.org/dev"] }\if{html}{\out{
    }} If for some reason you choose to redirect an existing page make sure to exclude it from the search index, see \code{?build_search}. } pkgdown/man/clean.Rd0000644000176200001440000000110514740246027014052 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/clean.R \name{clean_site} \alias{clean_site} \alias{clean_cache} \title{Clean site} \usage{ clean_site(pkg = ".", quiet = FALSE, force = FALSE) clean_cache(pkg = ".", quiet = FALSE) } \arguments{ \item{pkg}{Path to package.} \item{quiet}{If \code{TRUE}, suppresses a message.} \item{force}{If \code{TRUE}, delete contents of \code{docs} even if it is not a pkgdown site.} } \description{ Delete all files in \verb{docs/} (except for \code{CNAME}). Delete all files in the pkgdown cache directory. } pkgdown/man/build_favicons.Rd0000644000176200001440000000205514634573316015772 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/build-favicons.R \name{build_favicons} \alias{build_favicons} \title{Initialise favicons from package logo} \usage{ build_favicons(pkg = ".", overwrite = FALSE) } \arguments{ \item{pkg}{Path to package.} \item{overwrite}{If \code{TRUE}, re-create favicons from package logo.} } \description{ This function auto-detects the location of your package logo (with the name \code{logo.svg} (recommended format) or \code{logo.png}, created with \code{usethis::use_logo()}) and runs it through the \url{https://realfavicongenerator.net} API to build a complete set of favicons with different sizes, as needed for modern web usage. You only need to run the function once. The favicon set will be stored in \code{pkgdown/favicon} and copied by \code{\link[=init_site]{init_site()}} to the relevant location when the website is rebuilt. Once complete, you should add \verb{pkgdown/} to \code{.Rbuildignore } to avoid a NOTE during package checking. (\code{usethis::use_logo()} does this for you!) } pkgdown/man/check_pkgdown.Rd0000644000176200001440000000150714633374223015605 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/check.R \name{check_pkgdown} \alias{check_pkgdown} \alias{pkgdown_sitrep} \title{Check \verb{_pkgdown.yml}} \usage{ check_pkgdown(pkg = ".") pkgdown_sitrep(pkg = ".") } \arguments{ \item{pkg}{Path to package.} } \description{ This pair of functions checks that your \verb{_pkgdown.yml} is valid without building the whole site. \code{check_pkgdown()} errors at the first problem; \code{pkgdown_sitrep()} reports the status of all checks. Currently they check that: \itemize{ \item There's a \code{url} in the pkgdown configuration, which is also recorded in the \code{URL} field of the \code{DESCRIPTION}. \item All opengraph metadata is valid. \item All reference topics are included in the index. \item All articles/vignettes are included in the index. } } pkgdown/man/deploy_site_github.Rd0000644000176200001440000000414514770274305016664 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/deploy-site.R \name{deploy_site_github} \alias{deploy_site_github} \title{Deploy a pkgdown site on Travis-CI to Github Pages} \usage{ deploy_site_github( pkg = ".", install = TRUE, tarball = Sys.getenv("PKG_TARBALL", ""), ssh_id = Sys.getenv("id_rsa", ""), commit_message = construct_commit_message(pkg), clean = FALSE, verbose = FALSE, host = "github.com", ..., repo_slug = Sys.getenv("TRAVIS_REPO_SLUG", "") ) } \arguments{ \item{pkg}{Path to package.} \item{install}{Optionally, opt-out of automatic installation. This is necessary if the package you're documenting is a dependency of pkgdown} \item{tarball}{The location of the built package tarball. The default Travis configuration for R packages sets \code{PKG_TARBALL} to this path.} \item{ssh_id}{The private id to use, a base64 encoded content of the private pem file. This should \emph{not} be your personal private key. Instead create a new keypair specifically for deploying the site. The easiest way is to use \code{travis::use_travis_deploy()}.} \item{commit_message}{The commit message to be used for the commit.} \item{clean}{Clean all files from old site.} \item{verbose}{Print verbose output} \item{host}{The GitHub host url.} \item{...}{Additional arguments passed to \code{\link[=build_site]{build_site()}}.} \item{repo_slug}{The \code{user/repo} slug for the repository.} } \description{ \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#superseded}{\figure{lifecycle-superseded.svg}{options: alt='[Superseded]'}}}{\strong{[Superseded]}} \code{deploy_site_github()} was designed to deploy your site from Travis CI, which we no longer recommend, so this function is deprecated. There are two replacements: \itemize{ \item \code{\link[usethis:use_pkgdown]{usethis::use_pkgdown_github_pages()}} will setup a GitHub action to automatically build and deploy your package website to GitHub pages. \item \code{\link[=deploy_to_branch]{deploy_to_branch()}} can be called locally to build and deploy your website to any desired branch. } } \keyword{internal} pkgdown/man/init_site.Rd0000644000176200001440000000300614770274305014764 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/init.R \name{init_site} \alias{init_site} \title{Initialise site infrastructure} \usage{ init_site(pkg = ".", override = list()) } \arguments{ \item{pkg}{Path to package.} \item{override}{An optional named list used to temporarily override values in \verb{_pkgdown.yml}} } \description{ \code{init_site()}: \itemize{ \item creates the output directory (\verb{docs/}), \item generates a machine readable description of the site, used for autolinking, \item copies CSS/JS assets and extra files, and \item runs \code{build_favicons()}, if needed. } Typically, you will not need to call this function directly, as all \verb{build_*()} functions will run \code{init_site()} if needed. The only good reasons to call \code{init_site()} directly are the following: \itemize{ \item If you add or modify a package logo. \item If you add or modify \code{pkgdown/extra.scss}. \item If you modify \code{template.bslib} variables in \verb{_pkgdown.yml}. } See \code{vignette("customise")} for the various ways you can customise the display of your site. } \section{Build-ignored files}{ We recommend using \code{\link[usethis:use_pkgdown]{usethis::use_pkgdown_github_pages()}} to build-ignore \verb{docs/} and \verb{_pkgdown.yml}. If use another directory, or create the site manually, you'll need to add them to \code{.Rbuildignore} yourself. A \code{NOTE} about an unexpected file during \verb{R CMD CHECK} is an indication you have not correctly ignored these files. } pkgdown/man/test-crayon.Rd0000644000176200001440000000137114740246027015245 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/test.R \name{test-crayon} \alias{test-crayon} \title{Test case: crayon} \description{ Test case: crayon } \examples{ cat(cli::col_red("This is red"), "\n") cat(cli::col_blue("This is blue"), "\n") message(cli::col_green("This is green")) warning(cli::style_bold("This is bold")) } \seealso{ Other tests: \code{\link{index}}, \code{\link{test-dont}}, \code{\link{test-figures}}, \code{\link{test-links}}, \code{\link{test-lists}}, \code{\link{test-long-lines}}, \code{\link{test-math-examples}}, \code{\link{test-output-styles}}, \code{\link{test-params}}, \code{\link{test-sexpr-title}}, \code{\link{test-tables}}, \code{\link{test-verbatim}} } \concept{tests} \keyword{internal} pkgdown/man/index.Rd0000644000176200001440000000107514740246027014105 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/test.R \name{index} \alias{index} \alias{test-index} \title{Index} \description{ Index } \seealso{ Other tests: \code{\link{test-crayon}}, \code{\link{test-dont}}, \code{\link{test-figures}}, \code{\link{test-links}}, \code{\link{test-lists}}, \code{\link{test-long-lines}}, \code{\link{test-math-examples}}, \code{\link{test-output-styles}}, \code{\link{test-params}}, \code{\link{test-sexpr-title}}, \code{\link{test-tables}}, \code{\link{test-verbatim}} } \concept{tests} \keyword{internal} pkgdown/man/build_articles.Rd0000644000176200001440000002425415100735002015752 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/build-articles.R, R/build-article.R \name{build_articles} \alias{build_articles} \alias{build_article} \alias{build_articles_index} \title{Build articles section} \usage{ build_articles( pkg = ".", quiet = TRUE, lazy = TRUE, seed = 1014L, override = list(), preview = FALSE ) build_article( name, pkg = ".", lazy = FALSE, seed = 1014L, new_process = TRUE, pandoc_args = character(), override = list(), quiet = TRUE ) build_articles_index(pkg = ".", override = list()) } \arguments{ \item{pkg}{Path to package.} \item{quiet}{Set to \code{FALSE} to display output of knitr and pandoc. This is useful when debugging.} \item{lazy}{If \code{TRUE}, will only re-build article if input file has been modified more recently than the output file.} \item{seed}{Seed used to initialize random number generation in order to make article output reproducible. An integer scalar or \code{NULL} for no seed.} \item{override}{An optional named list used to temporarily override values in \verb{_pkgdown.yml}} \item{preview}{If \code{TRUE}, or \code{is.na(preview) && interactive()}, will preview freshly generated section in browser.} \item{name}{Name of article to render. This should be either a path relative to \verb{vignettes/} \emph{without extension}, or \code{index} or \code{README}.} \item{new_process}{Build the article in a clean R process? The default, \code{TRUE}, ensures that every article is build in a fresh environment, but you may want to set it to \code{FALSE} to make debugging easier.} \item{pandoc_args}{Pass additional arguments to pandoc. Used for testing.} } \description{ \code{build_articles()} renders each R Markdown file underneath \verb{vignettes/} and saves it to \verb{articles/}. There are two exceptions: \itemize{ \item Files that start with \verb{_} (e.g., \verb{_index.Rmd}) are ignored, enabling the use of child documents. \item Files in \code{vignettes/tutorials} are handled by \code{\link[=build_tutorials]{build_tutorials()}} } Vignettes are rendered using a special document format that reconciles \code{\link[rmarkdown:html_document]{rmarkdown::html_document()}} with the pkgdown template. This means articles behave slightly differently to vignettes, particularly with respect to external files, and custom output formats. See below for more details. Note that when you run \code{build_articles()} directly (outside of \code{\link[=build_site]{build_site()}}) vignettes will use the currently installed version of the package, not the current source version. This makes iteration quicker when you are primarily working on the text of an article. } \section{Index and navbar}{ You can control the articles index and navbar with a \code{articles} field in your \verb{_pkgdown.yml}. If you use it, pkgdown will check that all articles are included, and will error if you have missed any. The \code{articles} field defines a list of sections, each of which can contain four fields: \itemize{ \item \code{title} (required): title of section, which appears as a heading on the articles index. \item \code{desc} (optional): An optional markdown description displayed underneath the section title. \item \code{navbar} (optional): A couple of words used to label this section in the navbar. If omitted, this section of vignettes will not appear in the navbar. \item \code{contents} (required): a list of article names to include in the section. This can either be names of individual vignettes or a call to \code{starts_with()}. The name of a vignette includes its path under \code{vignettes} without extension so that the name of the vignette found at \code{vignettes/pizza/slice.Rmd} is \code{pizza/slice}. } The title and description of individual vignettes displayed on the index comes from \code{title} and \code{description} fields of the YAML header in the Rmds. For example, this yaml might be used for some version of dplyr: \if{html}{\out{
    }}\preformatted{articles: - title: Main verbs navbar: ~ contents: - one-table - two-table - rowwise - colwise - title: Developer desc: Vignettes aimed at package developers contents: - programming - packages }\if{html}{\out{
    }} Note the use of the \code{navbar} fields. \verb{navbar: ~} means that the "Main verbs" will appear in the navbar without a heading; the absence of the \code{navbar} field in the developer vignettes means that they will only be accessible via the articles index. The navbar will include a link to the articles index if one or more vignettes are not available through the navbar. If some vignettes appear in the navbar drop-down list and others do not, the list will automatically include a "More ..." link at the bottom; if no vignettes appear in the the navbar, it will link directly to the articles index instead of providing a drop-down. \subsection{Get started}{ Note that a vignette with the same name as the package (e.g., \code{vignettes/pkgdown.Rmd} or \code{vignettes/articles/pkgdown.Rmd}) automatically becomes a top-level "Get started" link, and will not appear in the articles drop-down. (If your package name includes a \code{.}, e.g. \code{pack.down}, use a \code{-} in the vignette name, e.g. \code{pack-down.Rmd}.) } \subsection{Missing articles}{ pkgdown will warn if there are (non-internal) articles that aren't listed in the articles index. You can suppress such warnings by listing the affected articles in a section with \code{title: internal} (case sensitive); this section will not be displayed on the index page. } \subsection{External articles}{ You can link to arbitrary additional articles by adding an \code{external-articles} entry to \verb{_pkgdown.yml}. It should contain an array of objects with fields \code{name}, \code{title}, \code{href}, and \code{description}. \if{html}{\out{
    }}\preformatted{external-articles: - name: subsampling title: Subsampling for Class Imbalances description: Improve model performance in imbalanced data sets through undersampling or oversampling. href: https://www.tidymodels.org/learn/models/sub-sampling/ }\if{html}{\out{
    }} If you've defined a custom articles index, you'll need to include the name in one of the \code{contents} fields. } } \section{External files}{ pkgdown differs from base R in its handling of external files. When building vignettes, R assumes that vignettes are self-contained (a reasonable assumption when most vignettes were PDFs) and only copies files explicitly listed in \code{.install_extras}. pkgdown takes a different approach based on \code{\link[rmarkdown:find_external_resources]{rmarkdown::find_external_resources()}}, and it will also copy any images that you link to. If for some reason the automatic detection doesn't work, you will need to add a \code{resource_files} field to the yaml metadata, e.g.: \if{html}{\out{
    }}\preformatted{--- title: My Document resource_files: - data/mydata.csv - images/figure.png --- }\if{html}{\out{
    }} Note that you can not use the \code{fig.path} to change the output directory of generated figures as its default value is a strong assumption of rmarkdown. } \section{Embedding Shiny apps}{ If you would like to embed a Shiny app into an article, the app will have to be hosted independently, (e.g. \url{https://www.shinyapps.io}). Then, you can embed the app into your article using an \verb{