Full Code of hadley/pkgdown for AI

main a6abe43ed48e cached
439 files
1.2 MB
397.4k tokens
8 symbols
1 requests
Download .txt
Showing preview only (1,304K chars total). Download the full file or copy to clipboard to get everything.
Repository: hadley/pkgdown
Branch: main
Commit: a6abe43ed48e
Files: 439
Total size: 1.2 MB

Directory structure:
gitextract_6_cfe080/

├── .Rbuildignore
├── .git-blame-ignore-revs
├── .gitattributes
├── .github/
│   ├── .gitignore
│   ├── 404.md
│   ├── CODEOWNERS
│   ├── CODE_OF_CONDUCT.md
│   ├── CONTRIBUTING.md
│   └── workflows/
│       ├── R-CMD-check.yaml
│       ├── lint.yaml
│       ├── netlify.yaml
│       ├── no-pandoc.yaml
│       ├── pkgdown.yaml
│       ├── pr-commands.yaml
│       ├── site-languages.yml
│       └── test-coverage.yaml
├── .gitignore
├── .lintr.R
├── .vscode/
│   ├── extensions.json
│   └── settings.json
├── DESCRIPTION
├── LICENSE
├── LICENSE.md
├── NAMESPACE
├── NEWS.md
├── R/
│   ├── build-404.R
│   ├── build-article.R
│   ├── build-articles.R
│   ├── build-favicons.R
│   ├── build-footer.R
│   ├── build-github.R
│   ├── build-home-authors.R
│   ├── build-home-community.R
│   ├── build-home-index.R
│   ├── build-home-license.R
│   ├── build-home-md.R
│   ├── build-home.R
│   ├── build-llm-dl.R
│   ├── build-llm.R
│   ├── build-logo.R
│   ├── build-news.R
│   ├── build-quarto-articles.R
│   ├── build-redirects.R
│   ├── build-reference-index.R
│   ├── build-reference.R
│   ├── build-search-docs.R
│   ├── build-tutorials.R
│   ├── build.R
│   ├── check-built.R
│   ├── check.R
│   ├── clean.R
│   ├── config.R
│   ├── context.R
│   ├── deploy-site.R
│   ├── development.R
│   ├── external-deps.R
│   ├── figure.R
│   ├── highlight.R
│   ├── html-build.R
│   ├── import-standalone-obj-type.R
│   ├── import-standalone-types-check.R
│   ├── init.R
│   ├── markdown.R
│   ├── navbar-menu.R
│   ├── navbar.R
│   ├── package.R
│   ├── pkgdown-package.R
│   ├── pkgdown.R
│   ├── pkgdown_print.R
│   ├── preview.R
│   ├── rd-data.R
│   ├── rd-example.R
│   ├── rd-html.R
│   ├── rd.R
│   ├── render.R
│   ├── repo.R
│   ├── template.R
│   ├── templates.R
│   ├── test.R
│   ├── theme.R
│   ├── topics-external.R
│   ├── topics.R
│   ├── tweak-homepage.R
│   ├── tweak-navbar.R
│   ├── tweak-page.R
│   ├── tweak-reference.R
│   ├── tweak-tabset.R
│   ├── tweak-tags.R
│   ├── tweak.R
│   ├── usage.R
│   ├── utils-fs.R
│   ├── utils-io.R
│   ├── utils-pdf.R
│   └── utils.R
├── README.Rmd
├── README.md
├── air.toml
├── codecov.yml
├── cran-comments.md
├── inst/
│   ├── BS3/
│   │   ├── assets/
│   │   │   ├── bootstrap-toc.css
│   │   │   ├── bootstrap-toc.js
│   │   │   ├── docsearch.css
│   │   │   ├── docsearch.js
│   │   │   ├── pkgdown.css
│   │   │   └── pkgdown.js
│   │   └── templates/
│   │       ├── after-body.html
│   │       ├── before-body.html
│   │       ├── config-docsearch.json
│   │       ├── content-article-index.html
│   │       ├── content-article.html
│   │       ├── content-citation-authors.html
│   │       ├── content-home.html
│   │       ├── content-news-index.html
│   │       ├── content-news.html
│   │       ├── content-reference-index.html
│   │       ├── content-reference-topic.html
│   │       ├── content-title-body.html
│   │       ├── content-tutorial-index.html
│   │       ├── content-tutorial.html
│   │       ├── docsearch.html
│   │       ├── footer.html
│   │       ├── head.html
│   │       ├── header.html
│   │       ├── in-header.html
│   │       ├── layout-redirect.html
│   │       ├── layout.html
│   │       └── navbar.html
│   ├── BS5/
│   │   ├── assets/
│   │   │   ├── katex-auto.js
│   │   │   ├── lightswitch.js
│   │   │   ├── pkgdown.js
│   │   │   └── pkgdown.scss
│   │   └── templates/
│   │       ├── after-body.html
│   │       ├── before-body.html
│   │       ├── config-docsearch.json
│   │       ├── content-article-index.html
│   │       ├── content-article.html
│   │       ├── content-authors.html
│   │       ├── content-citation-authors.html
│   │       ├── content-home.html
│   │       ├── content-news-index.html
│   │       ├── content-news.html
│   │       ├── content-quarto.html
│   │       ├── content-reference-index.html
│   │       ├── content-reference-topic.html
│   │       ├── content-title-body.html
│   │       ├── content-tutorial-index.html
│   │       ├── content-tutorial.html
│   │       ├── footer.html
│   │       ├── head.html
│   │       ├── header.html
│   │       ├── in-header.html
│   │       ├── layout-redirect.html
│   │       ├── layout.html
│   │       └── navbar.html
│   ├── highlight-styles/
│   │   ├── a11y-dark.scss
│   │   ├── a11y-light.scss
│   │   ├── arrow-dark.scss
│   │   ├── arrow-light.scss
│   │   ├── atom-one-dark.scss
│   │   ├── atom-one-light.scss
│   │   ├── ayu-dark.scss
│   │   ├── ayu-light.scss
│   │   ├── ayu-mirage.scss
│   │   ├── breeze-dark.scss
│   │   ├── breeze-light.scss
│   │   ├── breezedark.scss
│   │   ├── dracula.scss
│   │   ├── espresso.scss
│   │   ├── github-dark.scss
│   │   ├── github-light.scss
│   │   ├── gruvbox-dark.scss
│   │   ├── gruvbox-light.scss
│   │   ├── haddock.scss
│   │   ├── kate.scss
│   │   ├── monochrome-dark.scss
│   │   ├── monochrome-light.scss
│   │   ├── monochrome.scss
│   │   ├── monokai.scss
│   │   ├── nord.scss
│   │   ├── oblivion.scss
│   │   ├── printing.scss
│   │   ├── pygments.scss
│   │   ├── radical.scss
│   │   ├── solarized-dark.scss
│   │   ├── solarized-light.scss
│   │   ├── solarized.scss
│   │   ├── tango.scss
│   │   ├── vim-dark.scss
│   │   └── zenburn.scss
│   ├── po/
│   │   ├── ca/
│   │   │   └── LC_MESSAGES/
│   │   │       └── R-pkgdown.mo
│   │   ├── de/
│   │   │   └── LC_MESSAGES/
│   │   │       └── R-pkgdown.mo
│   │   ├── dk/
│   │   │   └── LC_MESSAGES/
│   │   │       └── R-pkgdown.mo
│   │   ├── es/
│   │   │   └── LC_MESSAGES/
│   │   │       └── R-pkgdown.mo
│   │   ├── fr/
│   │   │   └── LC_MESSAGES/
│   │   │       └── R-pkgdown.mo
│   │   ├── ja/
│   │   │   └── LC_MESSAGES/
│   │   │       └── R-pkgdown.mo
│   │   ├── ko/
│   │   │   └── LC_MESSAGES/
│   │   │       └── R-pkgdown.mo
│   │   ├── kr/
│   │   │   └── LC_MESSAGES/
│   │   │       └── R-pkgdown.mo
│   │   ├── nl/
│   │   │   └── LC_MESSAGES/
│   │   │       └── R-pkgdown.mo
│   │   ├── pt/
│   │   │   └── LC_MESSAGES/
│   │   │       └── R-pkgdown.mo
│   │   ├── tr/
│   │   │   └── LC_MESSAGES/
│   │   │       └── R-pkgdown.mo
│   │   └── zh_CN/
│   │       └── LC_MESSAGES/
│   │           └── R-pkgdown.mo
│   ├── quarto/
│   │   └── template.html
│   └── rstudio/
│       └── addins.dcf
├── man/
│   ├── as_pkgdown.Rd
│   ├── build_articles.Rd
│   ├── build_favicons.Rd
│   ├── build_home.Rd
│   ├── build_llm_docs.Rd
│   ├── build_news.Rd
│   ├── build_redirects.Rd
│   ├── build_reference.Rd
│   ├── build_search.Rd
│   ├── build_site.Rd
│   ├── build_site_github_pages.Rd
│   ├── build_tutorials.Rd
│   ├── check_pkgdown.Rd
│   ├── clean.Rd
│   ├── deploy_site_github.Rd
│   ├── deploy_to_branch.Rd
│   ├── fig_settings.Rd
│   ├── in_pkgdown.Rd
│   ├── index.Rd
│   ├── init_site.Rd
│   ├── pkgdown-package.Rd
│   ├── pkgdown_print.Rd
│   ├── preview_site.Rd
│   ├── rd2html.Rd
│   ├── render_page.Rd
│   ├── stop_preview.Rd
│   ├── templates.Rd
│   ├── test-crayon.Rd
│   ├── test-dont.Rd
│   ├── test-figures.Rd
│   ├── test-links.Rd
│   ├── test-lists.Rd
│   ├── test-long-lines.Rd
│   ├── test-math-examples.Rd
│   ├── test-output-styles.Rd
│   ├── test-params.Rd
│   ├── test-sexpr-title.Rd
│   ├── test-tables.Rd
│   └── test-verbatim.Rd
├── pkgdown/
│   ├── _pkgdown.yml
│   └── favicon/
│       └── site.webmanifest
├── pkgdown.Rproj
├── po/
│   ├── R-ca.po
│   ├── R-de.po
│   ├── R-dk.po
│   ├── R-es.po
│   ├── R-fr.po
│   ├── R-ja.po
│   ├── R-ko.po
│   ├── R-nl.po
│   ├── R-pkgdown.pot
│   ├── R-pt.po
│   ├── R-tr.po
│   └── R-zh_CN.po
├── revdep/
│   ├── .gitignore
│   ├── README.md
│   ├── cran.md
│   ├── email.yml
│   ├── failures.md
│   └── problems.md
├── tests/
│   ├── testthat/
│   │   ├── .gitignore
│   │   ├── _snaps/
│   │   │   ├── build-article.md
│   │   │   ├── build-articles.md
│   │   │   ├── build-favicons.md
│   │   │   ├── build-footer.md
│   │   │   ├── build-github.md
│   │   │   ├── build-home-authors.md
│   │   │   ├── build-home-community.md
│   │   │   ├── build-home-index.md
│   │   │   ├── build-llm-dl.md
│   │   │   ├── build-llm.md
│   │   │   ├── build-news.md
│   │   │   ├── build-quarto-articles.md
│   │   │   ├── build-redirects.md
│   │   │   ├── build-reference-index.md
│   │   │   ├── build-reference.md
│   │   │   ├── build-search-docs.md
│   │   │   ├── check-built.md
│   │   │   ├── check.md
│   │   │   ├── config.md
│   │   │   ├── development.md
│   │   │   ├── external-deps.md
│   │   │   ├── highlight.md
│   │   │   ├── init.md
│   │   │   ├── markdown.md
│   │   │   ├── navbar-menu.md
│   │   │   ├── navbar.md
│   │   │   ├── not-in-rcmcheck/
│   │   │   │   └── build-article.md
│   │   │   ├── package.md
│   │   │   ├── preview.md
│   │   │   ├── rcmdcheck/
│   │   │   │   └── build-article.md
│   │   │   ├── rd-example.md
│   │   │   ├── rd-html.md
│   │   │   ├── render.md
│   │   │   ├── repo.md
│   │   │   ├── templates.md
│   │   │   ├── theme.md
│   │   │   ├── topics-external.md
│   │   │   ├── topics.md
│   │   │   ├── tweak-homepage.md
│   │   │   ├── tweak-tabset.md
│   │   │   ├── tweak-tags.md
│   │   │   ├── usage.md
│   │   │   └── utils-fs.md
│   │   ├── assets/
│   │   │   ├── -find-assets.html
│   │   │   ├── articles-images/
│   │   │   │   ├── .gitignore
│   │   │   │   ├── DESCRIPTION
│   │   │   │   ├── README.md
│   │   │   │   ├── _pkgdown.yml
│   │   │   │   ├── man/
│   │   │   │   │   └── kitten.Rd
│   │   │   │   ├── man-figures.Rproj
│   │   │   │   └── vignettes/
│   │   │   │       ├── .gitignore
│   │   │   │       └── kitten.Rmd
│   │   │   ├── figure/
│   │   │   │   ├── DESCRIPTION
│   │   │   │   ├── _pkgdown.yml
│   │   │   │   ├── man/
│   │   │   │   │   └── figure.Rd
│   │   │   │   └── vignettes/
│   │   │   │       └── figures.Rmd
│   │   │   ├── llm.html
│   │   │   ├── reference/
│   │   │   │   ├── DESCRIPTION
│   │   │   │   ├── NAMESPACE
│   │   │   │   ├── R/
│   │   │   │   │   └── funs.R
│   │   │   │   ├── _pkgdown.yml
│   │   │   │   └── man/
│   │   │   │       ├── a.Rd
│   │   │   │       ├── b.Rd
│   │   │   │       ├── c.Rd
│   │   │   │       ├── e.Rd
│   │   │   │       ├── f.Rd
│   │   │   │       ├── g.Rd
│   │   │   │       └── help.Rd
│   │   │   ├── reference-fail/
│   │   │   │   ├── DESCRIPTION
│   │   │   │   ├── NAMESPACE
│   │   │   │   ├── R/
│   │   │   │   │   └── f.R
│   │   │   │   └── man/
│   │   │   │       └── f.Rd
│   │   │   ├── reference-html-dep/
│   │   │   │   ├── DESCRIPTION
│   │   │   │   ├── NAMESPACE
│   │   │   │   ├── R/
│   │   │   │   │   └── funs.R
│   │   │   │   ├── _pkgdown.yml
│   │   │   │   └── man/
│   │   │   │       └── a.Rd
│   │   │   ├── reference-language/
│   │   │   │   ├── one/
│   │   │   │   │   └── DESCRIPTION
│   │   │   │   └── two/
│   │   │   │       └── DESCRIPTION
│   │   │   ├── reference-pre-post/
│   │   │   │   ├── DESCRIPTION
│   │   │   │   └── pkgdown/
│   │   │   │       ├── post-reference.R
│   │   │   │       └── pre-reference.R
│   │   │   ├── reference-selector/
│   │   │   │   ├── DESCRIPTION
│   │   │   │   ├── NAMESPACE
│   │   │   │   ├── NEWS.md
│   │   │   │   ├── R/
│   │   │   │   │   └── funs.R
│   │   │   │   ├── _pkgdown.yml
│   │   │   │   └── man/
│   │   │   │       ├── A.Rd
│   │   │   │       └── matches.Rd
│   │   │   ├── sitemaps-schema-0.9.xsd
│   │   │   └── templates-local/
│   │   │       ├── DESCRIPTION
│   │   │       └── pkgdown/
│   │   │           └── templates/
│   │   │               ├── content-article.html
│   │   │               └── footer-article.html
│   │   ├── helper.R
│   │   ├── test-build-article.R
│   │   ├── test-build-articles.R
│   │   ├── test-build-favicons.R
│   │   ├── test-build-footer.R
│   │   ├── test-build-github.R
│   │   ├── test-build-home-authors.R
│   │   ├── test-build-home-community.R
│   │   ├── test-build-home-index.R
│   │   ├── test-build-home-license.R
│   │   ├── test-build-home-md.R
│   │   ├── test-build-home.R
│   │   ├── test-build-llm-dl.R
│   │   ├── test-build-llm.R
│   │   ├── test-build-logo.R
│   │   ├── test-build-news.R
│   │   ├── test-build-quarto-articles.R
│   │   ├── test-build-redirects.R
│   │   ├── test-build-reference-index.R
│   │   ├── test-build-reference.R
│   │   ├── test-build-search-docs.R
│   │   ├── test-build-tutorials.R
│   │   ├── test-build.R
│   │   ├── test-check-built.R
│   │   ├── test-check.R
│   │   ├── test-config.R
│   │   ├── test-deploy-site.R
│   │   ├── test-development.R
│   │   ├── test-external-deps.R
│   │   ├── test-figure.R
│   │   ├── test-highlight.R
│   │   ├── test-html-build.R
│   │   ├── test-init.R
│   │   ├── test-markdown.R
│   │   ├── test-navbar-menu.R
│   │   ├── test-navbar.R
│   │   ├── test-package.R
│   │   ├── test-pkgdown_print.R
│   │   ├── test-preview.R
│   │   ├── test-rd-data.R
│   │   ├── test-rd-example.R
│   │   ├── test-rd-html.R
│   │   ├── test-render.R
│   │   ├── test-repo.R
│   │   ├── test-templates.R
│   │   ├── test-theme.R
│   │   ├── test-topics-external.R
│   │   ├── test-topics.R
│   │   ├── test-tweak-homepage.R
│   │   ├── test-tweak-navbar.R
│   │   ├── test-tweak-page.R
│   │   ├── test-tweak-reference.R
│   │   ├── test-tweak-tabset.R
│   │   ├── test-tweak-tags.R
│   │   ├── test-usage.R
│   │   ├── test-utils-fs.R
│   │   └── test-utils.R
│   └── testthat.R
├── tools/
│   └── syntax-highlight.R
└── vignettes/
    ├── .gitignore
    ├── accessibility.Rmd
    ├── articles/
    │   ├── .gitignore
    │   ├── test-quarto-article.qmd
    │   └── test-rmarkdown-article.Rmd
    ├── customise.Rmd
    ├── how-to-update-released-site.Rmd
    ├── linking.Rmd
    ├── metadata.Rmd
    ├── pkgdown.Rmd
    ├── quarto.qmd
    ├── test/
    │   ├── jss.Rmd
    │   ├── jss.bib
    │   ├── jss.bst
    │   ├── jss.cls
    │   ├── long-toc.Rmd
    │   ├── pdf.Rmd
    │   ├── quarto-features.qmd
    │   ├── rendering.Rmd
    │   ├── short.Rmd
    │   ├── test.txt
    │   └── widgets.Rmd
    └── translations.Rmd

================================================
FILE CONTENTS
================================================

================================================
FILE: .Rbuildignore
================================================
^.*\.Rproj$
^\.Rproj\.user$
^\.travis\.yml$
^inst/web$
^docs$
^_pkgdown\.yml$
^README\.Rmd$
^README-.*\.png$
^pkgdown$
^codecov\.yml$
^CODE_OF_CONDUCT\.md$
^LICENSE\.md$
^tests/testthat/assets/site-dot-github/.github$
^cran-comments\.md$
^CRAN-RELEASE$
^revdep$
^appveyor\.yml$
^\.github$
^fake-index.html$
^CRAN-SUBMISSION$
^tools$
^\.lintr.R$
^vignettes/\.quarto$
^vignettes/articles/\.quarto$
^vignettes/articles/*_files$
^vignettes/articles$
^\.vscode$
^[\.]?air\.toml$
^\.git-blame-ignore-revs$


================================================
FILE: .git-blame-ignore-revs
================================================
# This file lists revisions of large-scale formatting/style changes so that
# they can be excluded from git blame results.
#
# To set this file as the default ignore file for git blame, run:
#   $ git config blame.ignoreRevsFile .git-blame-ignore-revs

# https://github.com/r-lib/pkgdown/pull/2865
3245437e22fb284f9e9fbbb62df5ef0ccba47715

================================================
FILE: .gitattributes
================================================
docs/* linguist-generated=false


================================================
FILE: .github/.gitignore
================================================
*.html


================================================
FILE: .github/404.md
================================================
# Page not found (404)

Please use the links in the navigation bar.


================================================
FILE: .github/CODEOWNERS
================================================
# CODEOWNERS for pkgdown
# https://www.tidyverse.org/development/understudies
.github/CODEOWNERS @hadley @jayhesselberth


================================================
FILE: .github/CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct

## Our Pledge

We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, caste, color, religion, or sexual
identity and orientation.

We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.

## Our Standards

Examples of behavior that contributes to a positive environment for our
community include:

* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
  and learning from the experience
* Focusing on what is best not just for us as individuals, but for the overall
  community

Examples of unacceptable behavior include:

* The use of sexualized language or imagery, and sexual attention or advances of
  any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email address,
  without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
  professional setting

## Enforcement Responsibilities

Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.

Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.

## Scope

This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at codeofconduct@posit.co. 
All complaints will be reviewed and investigated promptly and fairly.

All community leaders are obligated to respect the privacy and security of the
reporter of any incident.

## Enforcement Guidelines

Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:

### 1. Correction

**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.

**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.

### 2. Warning

**Community Impact**: A violation through a single incident or series of
actions.

**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or permanent
ban.

### 3. Temporary Ban

**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.

**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.

### 4. Permanent Ban

**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.

**Consequence**: A permanent ban from any sort of public interaction within the
community.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.1, available at
<https://www.contributor-covenant.org/version/2/1/code_of_conduct.html>.

Community Impact Guidelines were inspired by
[Mozilla's code of conduct enforcement ladder][https://github.com/mozilla/inclusion].

For answers to common questions about this code of conduct, see the FAQ at
<https://www.contributor-covenant.org/faq>. Translations are available at <https://www.contributor-covenant.org/translations>.

[homepage]: https://www.contributor-covenant.org


================================================
FILE: .github/CONTRIBUTING.md
================================================
# Contributing to pkgdown

This document outlines how to propose a change to pkgdown. For more detailed
info about contributing to this and other tidyverse packages, please see the
[**tidyverse contribution guide**](https://rstd.io/tidy-contrib).

## pkgdown and Pandoc versions

The versions of pkgdown and Pandoc used to build a website are stored in the 
public facing `pkgdown.yml` file, e.g. <https://dplyr.tidyverse.org/pkgdown.yml>.

## Package reprexes

If you encounter unexpected errors after running `pkgdown::build_site()`, try
to build a minimal package that recreates the error. An ideal minimal package has
*no dependencies*, making it easy to install and quickly reproduce the error. An
example of a minimal package was [this issue](https://github.com/r-lib/pkgdown/issues/720#issuecomment-397606145),
where a minimal package containing a single `.R` file with two lines could reproduce
the error.

The quickest way to set up minimal example package is with `usethis::create_package()`:

```R
usethis::create_package("~/desktop/testpackage")
# ... edit files ...
pkgdown::build_site(tmp, new_process = FALSE, preview = FALSE)
```

Once you have built a minimal package that recreates the error, create a GitHub
repository from the package (e.g. with `usethis::use_git()` + `usethis::use_github()`), and file an issue with a link to the repository.

## Rd translation

If you encounter problems with Rd tags, please use `rd2html()` to create a reprexes:

```R
library(pkgdown)

rd2html("a\n%b\nc")
rd2html("a & b")
```

## Pull request process

*  We recommend that you create a Git branch for each pull request (PR).  
*  Look at the Travis and AppVeyor build status before and after making changes.
The `README` should contain badges for any continuous integration services used
by the package.  
*  New code should follow the tidyverse [style guide](http://style.tidyverse.org).
You can use the [styler](https://CRAN.R-project.org/package=styler) package to
apply these styles, but please don't restyle code that has nothing to do with 
your PR.  
*  We use [roxygen2](https://cran.r-project.org/package=roxygen2), with
[Markdown syntax](https://roxygen2.r-lib.org/articles/rd-formatting.html), 
for documentation.  
*  We use [testthat](https://cran.r-project.org/package=testthat). Contributions
with test cases included are easier to accept.  
*  For user-facing changes, add a bullet to the top of `NEWS.md` below the
current development version header describing the changes made followed by your
GitHub username, and links to relevant issue(s)/PR(s).

### Netlify

We might ask you for a Netlify preview of your changes i.e. how do your local changes affect the pkgdown website?

1. Build and install the amended package, then re-build the website (`clean_site()` and then `build_site()`) which will update the docs/ folder.
1. Log into Netlify at https://app.netlify.com/sites/, and scroll to the bottom. You'll see a box with dashed outline that says "Want to deploy a new site without connecting to Git?".
1. Open up a file browser, navigate to `docs/`, and drag the `docs/` folder to the dashed box, which will copy all the files into a temporary netlify site.
1. After the file transfer completes, netlify will generate a temporary URL on a new page that you can copy/paste in the PR discussion.

## Fixing typos

Small typos or grammatical errors in documentation may be edited directly using
the GitHub web interface, so long as the changes are made in the _source_ file.

*  YES: you edit a roxygen comment in a `.R` file below `R/`.
*  NO: you edit an `.Rd` file below `man/`.

## Prerequisites

Before you make a substantial pull request, you should always file an issue and
make sure someone from the team agrees that it’s a problem. If you’ve found a
bug, create an associated issue and illustrate the bug with a minimal 
[reprex](https://www.tidyverse.org/help/#reprex).

## Code of Conduct

Please note that the pkgdown project is released with a
[Contributor Code of Conduct](CODE_OF_CONDUCT.md). By contributing to this
project you agree to abide by its terms.


================================================
FILE: .github/workflows/R-CMD-check.yaml
================================================
# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
#
# NOTE: This workflow is overkill for most R packages and
# check-standard.yaml is likely a better choice.
# usethis::use_github_action("check-standard") will install it.
on:
  push:
    branches: [main, master]
  pull_request:

name: R-CMD-check.yaml

permissions: read-all

jobs:
  R-CMD-check:
    runs-on: ${{ matrix.config.os }}

    name: ${{ matrix.config.os }} (${{ matrix.config.r }})

    strategy:
      fail-fast: false
      matrix:
        config:
          - {os: macos-latest,   r: 'release'}

          - {os: windows-latest, r: 'release'}
          # use 4.0 or 4.1 to check with rtools40's older compiler
          - {os: windows-latest, r: 'oldrel-3'}

          - {os: ubuntu-latest,  r: 'devel', http-user-agent: 'release'}
          - {os: ubuntu-latest,  r: 'release'}
          - {os: ubuntu-latest,  r: 'oldrel-1'}
          - {os: ubuntu-latest,  r: 'oldrel-2'}
          - {os: ubuntu-latest,  r: 'oldrel-3'}
          - {os: ubuntu-latest,  r: 'oldrel-4'}

    env:
      GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
      R_KEEP_PKG_SOURCE: yes

    steps:
      - uses: actions/checkout@v4

      - uses: r-lib/actions/setup-pandoc@v2

      - uses: r-lib/actions/setup-tinytex@v2
        env:
          TINYTEX_INSTALLER: TinyTeX

      - uses: r-lib/actions/setup-r@v2
        with:
          r-version: ${{ matrix.config.r }}
          http-user-agent: ${{ matrix.config.http-user-agent }}
          use-public-rspm: true

      - uses: r-lib/actions/setup-r-dependencies@v2
        with:
          extra-packages: any::rcmdcheck
          needs: check

      - uses: r-lib/actions/check-r-package@v2
        env:
          R_QUARTO_QUIET: false
        with:
          upload-snapshots: true
          build_args: 'c("--no-manual","--compact-vignettes=gs+qpdf")'


================================================
FILE: .github/workflows/lint.yaml
================================================
# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
on:
  push:
    branches: [main, master]
  pull_request:
    branches: [main, master]

name: lint

permissions: read-all

jobs:
  lint:
    runs-on: ubuntu-latest
    env:
      GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
    steps:
      - uses: actions/checkout@v4

      - uses: r-lib/actions/setup-r@v2
        with:
          use-public-rspm: true
      
      - uses: r-lib/actions/setup-r-dependencies@v2
        with:
          extra-packages: any::lintr, local::.
          needs: lint
          
      - uses: r-lib/actions/setup-tinytex@v2

      - name: Lint
        run: lintr::lint_package()
        shell: Rscript {0}
        env:
          LINTR_ERROR_ON_LINT: true


================================================
FILE: .github/workflows/netlify.yaml
================================================
on:
  pull_request:
    branches: [main, master]

name: pkgdown-pr

jobs:
  netlify:
    runs-on: ubuntu-latest
    env:
      GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
    steps:
      - uses: actions/checkout@v4

      - uses: r-lib/actions/setup-tinytex@v2

      - uses: r-lib/actions/setup-pandoc@v2

      - uses: r-lib/actions/setup-r@v2
        with:
          use-public-rspm: true

      - uses: r-lib/actions/setup-r-dependencies@v2
        with:
          extra-packages: any::pkgdown, local::.
          needs: website

      - name: Install package
        run: R CMD INSTALL .

      - name: Create website
        run: |
          pkgdown::build_site()
        shell: Rscript {0}

      - name: Create index file
        run: |
          echo '<!DOCTYPE html><html><head><meta http-equiv="refresh" content="0;URL=/dev/index.html" />  <script language="javascript"> window.location.replace('/dev/index.html')</script></head></html>' > ./docs/index.html

      - name: Deploy to Netlify
        uses: nwtgck/actions-netlify@v3.0
        with:
          publish-dir: './docs'
          production-branch: main
          github-token: ${{ secrets.GITHUB_TOKEN }}
          deploy-message:
            'Deploy from GHA: ${{ github.event.pull_request.title || github.event.head_commit.message }} (${{ github.sha }})'
          # these default to 'true'
          enable-commit-comment: false
          enable-github-deployment: false
        env:
          NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
          NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}


================================================
FILE: .github/workflows/no-pandoc.yaml
================================================
# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
on:
  push:
    branches: [main, master]
  pull_request:
    branches: [main, master]

name: no-pandoc

jobs:
  R-CMD-check:
    runs-on: ubuntu-latest
    env:
      GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
      R_KEEP_PKG_SOURCE: yes
    steps:
      - uses: actions/checkout@v4

      - uses: r-lib/actions/setup-r@v2
        with:
          use-public-rspm: true

      - uses: r-lib/actions/setup-r-dependencies@v2
        with:
          extra-packages: any::rcmdcheck
          needs: check

      - uses: r-lib/actions/setup-tinytex@v2
        env:
          TINYTEX_INSTALLER: TinyTeX

      - run: sudo apt-get --purge remove pandoc
      - run: rm -rf vignettes

      - uses: r-lib/actions/check-r-package@v2
        env:
          R_QUARTO_QUIET: false


================================================
FILE: .github/workflows/pkgdown.yaml
================================================
# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
on:
  push:
    branches: [main, master]
  pull_request:
  release:
    types: [published]
  workflow_dispatch:

name: pkgdown.yaml

permissions: read-all

jobs:
  pkgdown:
    runs-on: ubuntu-latest
    # Only restrict concurrency for non-PR jobs
    concurrency:
      group: pkgdown-${{ github.event_name != 'pull_request' || github.run_id }}
    env:
      GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
    permissions:
      contents: write
    steps:
      - uses: actions/checkout@v4

      - uses: r-lib/actions/setup-pandoc@v2

      - uses: r-lib/actions/setup-r@v2
        with:
          use-public-rspm: true

      - uses: r-lib/actions/setup-r-dependencies@v2
        with:
          extra-packages: any::pkgdown, local::.
          needs: website

      - uses: r-lib/actions/setup-tinytex@v2

      - name: Build site
        run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE)
        shell: Rscript {0}

      - name: Deploy to GitHub pages 🚀
        if: github.event_name != 'pull_request'
        uses: JamesIves/github-pages-deploy-action@v4.5.0
        with:
          clean: false
          branch: gh-pages
          folder: docs


================================================
FILE: .github/workflows/pr-commands.yaml
================================================
# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
on:
  issue_comment:
    types: [created]

name: pr-commands.yaml

permissions: read-all

jobs:
  document:
    if: ${{ github.event.issue.pull_request && (github.event.comment.author_association == 'MEMBER' || github.event.comment.author_association == 'OWNER') && startsWith(github.event.comment.body, '/document') }}
    name: document
    runs-on: ubuntu-latest
    env:
      GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
    permissions:
      contents: write
    steps:
      - uses: actions/checkout@v4

      - uses: r-lib/actions/pr-fetch@v2
        with:
          repo-token: ${{ secrets.GITHUB_TOKEN }}

      - uses: r-lib/actions/setup-r@v2
        with:
          use-public-rspm: true

      - uses: r-lib/actions/setup-r-dependencies@v2
        with:
          extra-packages: any::roxygen2
          needs: pr-document

      - name: Document
        run: roxygen2::roxygenise()
        shell: Rscript {0}

      - name: commit
        run: |
          git config --local user.name "$GITHUB_ACTOR"
          git config --local user.email "$GITHUB_ACTOR@users.noreply.github.com"
          git add man/\* NAMESPACE
          git commit -m 'Document'

      - uses: r-lib/actions/pr-push@v2
        with:
          repo-token: ${{ secrets.GITHUB_TOKEN }}

  style:
    if: ${{ github.event.issue.pull_request && (github.event.comment.author_association == 'MEMBER' || github.event.comment.author_association == 'OWNER') && startsWith(github.event.comment.body, '/style') }}
    name: style
    runs-on: ubuntu-latest
    env:
      GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
    permissions:
      contents: write
    steps:
      - uses: actions/checkout@v4

      - uses: r-lib/actions/pr-fetch@v2
        with:
          repo-token: ${{ secrets.GITHUB_TOKEN }}

      - uses: r-lib/actions/setup-r@v2

      - name: Install dependencies
        run: install.packages("styler")
        shell: Rscript {0}

      - name: Style
        run: styler::style_pkg()
        shell: Rscript {0}

      - name: commit
        run: |
          git config --local user.name "$GITHUB_ACTOR"
          git config --local user.email "$GITHUB_ACTOR@users.noreply.github.com"
          git add \*.R
          git commit -m 'Style'

      - uses: r-lib/actions/pr-push@v2
        with:
          repo-token: ${{ secrets.GITHUB_TOKEN }}


================================================
FILE: .github/workflows/site-languages.yml
================================================
on:
  workflow_dispatch:

name: pkgdown-i18n-netlify

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        include:
          - lang: ca
            locale: ca_ES.UTF-8
          - lang: de
            locale: de_DE.UTF-8
          - lang: dk
            locale: da_DK.UTF-8
          - lang: es
            locale: es_ES.UTF-8
          - lang: fr
            locale: fr_FR.UTF-8
          - lang: ko
            locale: ko_KR.UTF-8
          - lang: pt
            locale: pt_PT.UTF-8
          - lang: tr
            locale: tr_TR.UTF-8
          - lang: zh_CN
            locale: zh_CN.UTF-8
    env:
      GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
    steps:
      - uses: actions/checkout@v4

      - uses: r-lib/actions/setup-tinytex@v2

      - uses: r-lib/actions/setup-pandoc@v2

      - uses: r-lib/actions/setup-r@v2
        with:
          use-public-rspm: true

      - uses: r-lib/actions/setup-r-dependencies@v2
        with:
          extra-packages: any::pkgdown, local::.
          needs: website

      - name: Generate locale ${{ matrix.locale }}
        run: |
          sudo locale-gen ${{ matrix.locale }}
          sudo update-locale LANG=${{ matrix.locale }}
        shell: bash

      - name: Install package
        run: R CMD INSTALL .

      - name: Set lang in _pkgdown.yml
        run: |
          config <- yaml::read_yaml("pkgdown/_pkgdown.yml")
          config$lang <- "${{ matrix.lang }}"
          yaml::write_yaml(config, "pkgdown/_pkgdown.yml")
        shell: Rscript {0}

      - name: Build site for ${{ matrix.lang }}
        run: pkgdown::build_site()
        shell: Rscript {0}
        env:
          LANG: ${{ matrix.locale }}

      - name: Create index file
        run: |
          echo '<!DOCTYPE html><html><head><meta http-equiv="refresh" content="0;URL=/dev/index.html" />  <script language="javascript"> window.location.replace("/dev/index.html")</script></head></html>' > ./docs/index.html

      - name: Deploy to Netlify
        uses: nwtgck/actions-netlify@v3.0
        with:
          publish-dir: "./docs"
          production-branch: main
          github-token: ${{ secrets.GITHUB_TOKEN }}
          deploy-message: "Deploy ${{ matrix.lang }}: ${{ github.event.pull_request.title || github.event.head_commit.message }} (${{ github.sha }})"
          alias: ${{ matrix.lang }}
          enable-commit-comment: false
          enable-github-deployment: false
        env:
          NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
          NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}


================================================
FILE: .github/workflows/test-coverage.yaml
================================================
# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
on:
  push:
    branches: [main, master]
  pull_request:

name: test-coverage.yaml

permissions: read-all

jobs:
  test-coverage:
    runs-on: ubuntu-latest
    env:
      GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}

    steps:
      - uses: actions/checkout@v4

      - uses: r-lib/actions/setup-pandoc@v2

      - uses: r-lib/actions/setup-r@v2
        with:
          use-public-rspm: true

      - uses: r-lib/actions/setup-r-dependencies@v2
        with:
          extra-packages: any::covr, any::xml2
          needs: coverage

      - uses: r-lib/actions/setup-tinytex@v2
        env:
          TINYTEX_INSTALLER: TinyTeX

      - name: Test coverage
        run: |
          cov <- covr::package_coverage(
            quiet = FALSE,
            clean = FALSE,
            install_path = file.path(normalizePath(Sys.getenv("RUNNER_TEMP"), winslash = "/"), "package")
          )
          print(cov)
          covr::to_cobertura(cov)
        shell: Rscript {0}

      - uses: codecov/codecov-action@v5
        with:
          # Fail if error if not on PR, or if on PR and token is given
          fail_ci_if_error: ${{ github.event_name != 'pull_request' || secrets.CODECOV_TOKEN }}
          files: ./cobertura.xml
          plugins: noop
          disable_search: true
          token: ${{ secrets.CODECOV_TOKEN }}

      - name: Show testthat output
        if: always()
        run: |
          ## --------------------------------------------------------------------
          find '${{ runner.temp }}/package' -name 'testthat.Rout*' -exec cat '{}' \; || true
        shell: bash

      - name: Upload test results
        if: failure()
        uses: actions/upload-artifact@v4
        with:
          name: coverage-test-failures
          path: ${{ runner.temp }}/package


================================================
FILE: .gitignore
================================================
.Rproj.user
.Rhistory
.RData
inst/doc
*.orig
.env
*.tex
docs

/.quarto/
**/.quarto/


================================================
FILE: .lintr.R
================================================
linters <- list(lintr::undesirable_function_linter(
  fun = c(
    # Base messaging
    "message" = "use cli::cli_inform()",
    "warning" = "use cli::cli_warn()",
    "stop" = "use cli::cli_abort()",
    # rlang messaging
    "inform" = "use cli::cli_inform()",
    "warn" = "use cli::cli_warn()",
    "abort" = "use cli::cli_abort()",
    # older cli
    "cli_alert_danger" = "use cli::cli_inform()",
    "cli_alert_info" = "use cli::cli_inform()",
    "cli_alert_success" = "use cli::cli_inform()",
    "cli_alert_warning" = "use cli::cli_inform()",
    # fs
    "file.path" = "use path()",
    "dir" = "use dir_ls()",
    "dir.create" = "use dir_create()",
    "file.copy" = "use file_copy()",
    "file.create" = "use file_create()",
    "file.exists" = "use file_exists()",
    "file.info" = "use file_info()",
    "normalizePath" = "use path_real()",
    "unlink" = "use file_delete()",
    "basename" = "use path_file()",
    "dirname" = "use path_dir()",
    # i/o
    "readLines" = "use read_lines()",
    "writeLines" = "use write_lines()"
  ),
  symbol_is_undesirable = FALSE
))

exclusions <- list(
  "R/import-standalone-obj-type.R",
  "R/import-standalone-types-check.R",
  "vignettes",
  "tests/testthat/assets"
)

================================================
FILE: .vscode/extensions.json
================================================
{
    "recommendations": [
        "Posit.air-vscode"
    ]
}


================================================
FILE: .vscode/settings.json
================================================
{
    "[r]": {
        "editor.formatOnSave": true,
        "editor.defaultFormatter": "Posit.air-vscode"
    }
}


================================================
FILE: DESCRIPTION
================================================
Package: pkgdown
Title: Make Static HTML Documentation for a Package
Version: 2.2.0.9000
Authors@R: c(
    person("Hadley", "Wickham", , "hadley@posit.co", role = c("aut", "cre"),
           comment = c(ORCID = "0000-0003-4757-117X")),
    person("Jay", "Hesselberth", role = "aut",
           comment = c(ORCID = "0000-0002-6299-179X")),
    person("Maëlle", "Salmon", role = "aut",
           comment = c(ORCID = "0000-0002-2815-0399")),
    person("Olivier", "Roy", role = "aut"),
    person("Salim", "Brüggemann", role = "aut",
           comment = c(ORCID = "0000-0002-5329-5987")),
    person("Posit Software, PBC", role = c("cph", "fnd"),
           comment = c(ROR = "03wc8by49"))
  )
Description: Generate an attractive and useful website from a source
    package.  'pkgdown' converts your documentation, vignettes, 'README',
    and more to 'HTML' making it easy to share information about your
    package online.
License: MIT + file LICENSE
URL: https://pkgdown.r-lib.org/, https://github.com/r-lib/pkgdown
BugReports: https://github.com/r-lib/pkgdown/issues
Depends:
    R (>= 4.1)
Imports:
    bslib (>= 0.5.1),
    callr (>= 3.7.3),
    cli (>= 3.6.1),
    desc (>= 1.4.0),
    downlit (>= 0.4.4),
    fontawesome,
    fs (>= 1.4.0),
    httr2 (>= 1.0.2),
    jsonlite,
    lifecycle,
    openssl,
    nanonext (>= 1.8.0),
    purrr (>= 1.0.0),
    ragg (>= 1.4.0),
    rlang (>= 1.1.4),
    rmarkdown (>= 2.27),
    tibble,
    whisker,
    withr (>= 2.4.3),
    xml2 (>= 1.3.1),
    yaml (>= 2.3.9)
Suggests:
    covr,
    diffviewer,
    evaluate (>= 0.24.0),
    gert,
    gt,
    htmltools,
    htmlwidgets,
    knitr (>= 1.50),
    magick,
    methods,
    pkgload (>= 1.0.2),
    quarto,
    rsconnect,
    rstudioapi,
    rticles,
    sass,
    testthat (>= 3.1.3),
    tools
VignetteBuilder:
    knitr,
    quarto
Config/Needs/website: usethis, servr
Config/potools/style: explicit
Config/testthat/edition: 3
Config/testthat/parallel: true
Config/testthat/start-first: build-article, build-quarto-article,
    build-reference, build
Config/usethis/last-upkeep: 2025-09-07
Encoding: UTF-8
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.3.3
SystemRequirements: pandoc (>= 2.10.1)


================================================
FILE: LICENSE
================================================
YEAR: 2025
COPYRIGHT HOLDER: pkgdown authors


================================================
FILE: LICENSE.md
================================================
# MIT License

Copyright (c) 2025 pkgdown authors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: NAMESPACE
================================================
# Generated by roxygen2: do not edit by hand

S3method("[",tag)
S3method(as_data,"NULL")
S3method(as_data,tag_arguments)
S3method(as_data,tag_author)
S3method(as_data,tag_description)
S3method(as_data,tag_details)
S3method(as_data,tag_format)
S3method(as_data,tag_note)
S3method(as_data,tag_references)
S3method(as_data,tag_section)
S3method(as_data,tag_seealso)
S3method(as_data,tag_source)
S3method(as_data,tag_usage)
S3method(as_data,tag_value)
S3method(as_example,COMMENT)
S3method(as_example,RCODE)
S3method(as_example,TEXT)
S3method(as_example,VERB)
S3method(as_example,tag)
S3method(as_example,tag_dontrun)
S3method(as_example,tag_dontshow)
S3method(as_example,tag_donttest)
S3method(as_example,tag_dots)
S3method(as_example,tag_if)
S3method(as_example,tag_ifelse)
S3method(as_example,tag_ldots)
S3method(as_example,tag_out)
S3method(as_example,tag_testonly)
S3method(as_html,"#ifdef")
S3method(as_html,"#ifndef")
S3method(as_html,COMMENT)
S3method(as_html,LIST)
S3method(as_html,RCODE)
S3method(as_html,Rd)
S3method(as_html,TEXT)
S3method(as_html,USERMACRO)
S3method(as_html,VERB)
S3method(as_html,character)
S3method(as_html,tag)
S3method(as_html,tag_R)
S3method(as_html,tag_S3method)
S3method(as_html,tag_S4method)
S3method(as_html,tag_Sexpr)
S3method(as_html,tag_acronym)
S3method(as_html,tag_bold)
S3method(as_html,tag_cite)
S3method(as_html,tag_code)
S3method(as_html,tag_command)
S3method(as_html,tag_cr)
S3method(as_html,tag_dQuote)
S3method(as_html,tag_deqn)
S3method(as_html,tag_describe)
S3method(as_html,tag_dfn)
S3method(as_html,tag_dots)
S3method(as_html,tag_email)
S3method(as_html,tag_emph)
S3method(as_html,tag_enc)
S3method(as_html,tag_enumerate)
S3method(as_html,tag_env)
S3method(as_html,tag_eqn)
S3method(as_html,tag_figure)
S3method(as_html,tag_file)
S3method(as_html,tag_href)
S3method(as_html,tag_if)
S3method(as_html,tag_ifelse)
S3method(as_html,tag_item)
S3method(as_html,tag_itemize)
S3method(as_html,tag_kbd)
S3method(as_html,tag_ldots)
S3method(as_html,tag_link)
S3method(as_html,tag_linkS4class)
S3method(as_html,tag_method)
S3method(as_html,tag_newcommand)
S3method(as_html,tag_option)
S3method(as_html,tag_out)
S3method(as_html,tag_pkg)
S3method(as_html,tag_preformatted)
S3method(as_html,tag_renewcommand)
S3method(as_html,tag_sQuote)
S3method(as_html,tag_samp)
S3method(as_html,tag_special)
S3method(as_html,tag_strong)
S3method(as_html,tag_subsection)
S3method(as_html,tag_tab)
S3method(as_html,tag_tabular)
S3method(as_html,tag_url)
S3method(as_html,tag_var)
S3method(as_html,tag_verb)
S3method(pkgdown_print,default)
S3method(pkgdown_print,gt_tbl)
S3method(pkgdown_print,htmlwidget)
S3method(print,pkgdown_xml)
S3method(print,print_yaml)
S3method(print,tag)
S3method(usage_code,"NULL")
S3method(usage_code,COMMENT)
S3method(usage_code,RCODE)
S3method(usage_code,Rd)
S3method(usage_code,TEXT)
S3method(usage_code,VERB)
S3method(usage_code,tag)
S3method(usage_code,tag_S3method)
S3method(usage_code,tag_S4method)
S3method(usage_code,tag_dots)
S3method(usage_code,tag_ldots)
S3method(usage_code,tag_method)
S3method(usage_code,tag_special)
S3method(usage_code,tag_usage)
export(as_pkgdown)
export(build_article)
export(build_articles)
export(build_articles_index)
export(build_favicons)
export(build_home)
export(build_home_index)
export(build_llm_docs)
export(build_news)
export(build_redirects)
export(build_reference)
export(build_reference_index)
export(build_search)
export(build_site)
export(build_site_github_pages)
export(build_tutorials)
export(check_pkgdown)
export(clean_cache)
export(clean_site)
export(data_template)
export(deploy_site_github)
export(deploy_to_branch)
export(fig_settings)
export(in_pkgdown)
export(init_site)
export(pkgdown_print)
export(pkgdown_sitrep)
export(preview_site)
export(rd2html)
export(render_page)
export(stop_preview)
export(template_articles)
export(template_navbar)
export(template_reference)
import(fs)
import(rlang)
importFrom(lifecycle,deprecated)
importFrom(utils,installed.packages)


================================================
FILE: NEWS.md
================================================
# pkgdown (development version)

* When previewing a site, it is now served via a local http server. This enables dynamic features such as search to work correctly (@shikokuchuo, #2975).

* do not autolink code that is in a link (href) in Rd files (#2972)

# pkgdown 2.2.0

* Make `build_llm_docs()` more robust to the use of old Pandoc (@nanxstats, @galachad, #2952, #2954)

## Lifecycle changes

* `autolink_html()` deprecated in 1.6.0 and `preview_page()` have been removed.

## New features

* New `build_llm_docs()` generates a `llms.txt` at the root directory of your site, and provides a `.md` version of every page. You can disable by adding `llm-docs: false` to your `_pkgdown.yaml` (#2914, @maelle)
* `build_articles()` now executes quarto vignettes in the same working directory as RMarkdown vignettes, namely the directory in which they live (#2877).

## Minor improvements and bug fixes

* `build_site()` gained a `quiet` argument, which is propagated to other functions (e.g., `build_articles()`) and is useful for debugging build errors on GH actions.
* New translations were add for Dutch (`nl`) and Japanese (`ja`), thanks to @pepijn-devires and @shikokuchuo respectively.
* Links generated with `\code{\link{foo}()}` now have the `()` moved into the `<a>` in the generated output (@maelle).
* Plots in dark mode are now transformed with a CSS filter to improve their visibility (thanks to @gadenbuie).
* Updated the translations vignette with instructions for building non-English sites through Github Actions.
* Added documentation explaining how to solve incorrect rendering of plotmath expressions under ragg devices on Linux. (@remlapmot, #2908)
* Improved the LaTeX syntax in one of the math rendering test cases (@remlapmot)

# pkgdown 2.1.3

* Menu items can now set `class` and `id`.

# pkgdown 2.1.2

## New features

* ROR IDs in `DESCRIPTION` are transformed into icons, similar to ORCID IDs. (#2850)
* New `clean_site(force = TRUE)` for cleaning of `docs/` regardless of whether it was built by pkgdown (#2827).
* The language of the site is set from the first `Language:` in the `DESCRIPTION` if it is available and no other language is specified (@jonthegeek, #2808).

## Bug fixes and minor improvements

* Option `pkgdown.internet` was removed because CDN file caching now requires an internet connection.
* Math rendering using katex and mathjax was improved and now includes necessary components using CDN (#2704).
* Articles have improved test cases (thanks to @venpopov and @ethanbass).
* Sass variables from bslib are now used to set the navbar background color: `$navbar-bg` for the background color in light and dark mode, or `$navbar-light-bg` and `$navbar-dark-bg` for individually controlling light and dark mode background colors. `pkgdown-navbar-bg` and `$pkgdown-navbar-bg-dark` both still provide pkgdown-specific overrides (@gadenbuie, #2847).
* Code repositories hosted on Codeberg are now supported in the `BugReports` and `URL` fields (@nfrerebeau, #2843).
* Links to favicons in page headers were updated to reflect changes to https://realfavicongenerator.net/ (#2804). Favicons should be re-generated by manually removing the `pkgdown/favicon` directory and then running `pkgdown::build_favicons()`.
* Reinstate Rd macro loading, which was accidentally disabled in v2.1.1 (#2782).

# pkgdown 2.1.1

* Added keyboard shortcut, `/`, to focus search bar (#2423).
* The `BugReports` field can now be an email (@catalamarti, #2275).
* New `clean_cache()` function removes the contents of the cache directory (#2718).
* pkgdown now depends on R >= 4.0.0 (#2714).
* Updated GitHub Actions advice and workflows around Quarto install (@tanho63, #2743).
* Support ANSI sequences in `index.md` (@krlmlr, #2787).

# pkgdown 2.1.0

## Major changes

* Added @olivroy and @salim-b as pkgdown authors in recognition of their contributions.
* `build_articles()` and `build_article()` now support articles/vignettes written with quarto (version 1.5 and above). Combining the disparate quarto and pkgdown templating systems is a delicate art, so while I've done my best to make it work, there may be some rough edges. So please file an issue you encounter quarto features that don't work quite right. Learn more in `vignette("quarto")`(#2210).
* New light switch makes it easy for users to switch between light and dark themes for the website (based on work in bslib by @gadenbuie). For now this behaviour is opt-in with `template.light-switch: true` but in the future we may turn it on automatically. See the customization vignette for details (#1696).
* New `vignette("translations")` that discusses non-English sites including how to submit new translations (#2605).
* New `vignette("accessibility")` describes what manual tasks you need to perform to make your site as accessible as possible (#2344).
* New `template.math-rendering` allows you to control how math is rendered across your site. The default uses `mathml` which is low-dependency, but has the lowest fidelity. You can also use `mathjax`, the previous default, and `katex`, a faster alternative. (#1966).
* All external assets (JS, CSS, fonts) are now directly included in the site instead of fetched from external CDN (@salim-b, #2249)
* YAML validation has been substantially improved so you should get much clearer errors if you have made a mistake (#1927). Please file an issue if you find a case where the error message is not helpful.

## Lifecycle changes

* `autolink_html()` was deprecated in pkgdown 1.6.0 and now warns every time you use it. `downlit::downlit_html_path()` should be used instead.
* `build_site(document)` and `build_reference(document)` has been removed after being deprecated in pkgdown 1.4.0. `devel` should be used instead.
* `preview_page()` has been deprecated (#2650).
* Bootstrap 3 has been deprecated. It was superseded in December 2021, and now we're starting to more directly encourage folks to move away from it.

## Front end changes

* When built on GitHub, source urls now use the name of the current upstream branch (rather than `HEAD`), which is more likely to generate correct links (#2597).
* The search dropdown has been tweaked to look more like the other navbar menu items (#2338).
* Improve HTML5 compliance (#2369):
  * No longer support IE9 or earlier
  * Strip trailing whitespace
  * Label `<nav>`s and improve navbar html.
* Tweaked navbar display on mobile so that long titles in drop downs (e.g. article titles) are now wrapped, and the search input spans the full width (#2512).
* The title for the "Reference" page is now "Package index" since this page might contain more than just function details (#2181).
* Very wide words are now automatically broken across lines and hyphenated (when possible) when they'd otherwise create a horizontal scrollbar on mobile (#1888).
* The mobile version of pkgdown sites no longer has a scrollburglar (a small amount of horizontal scroll) (#2179, @netique).
* Anchors are displayed when they're the target of a link.
* New translation for "Search site", the label applied to the search box for screenreaders. This was previously incorrectly labelled as "Toggle navigation" (#2320).
* pkgdown no longer overrides the default selection colours. This improves accessibility for users who have set their own colours in their browser settings (#2139, @glin).
* If you put a dropdown menu (e.g. articles) on the right hand side of the navbar, it will now be right aligned. This makes longer titles more likely to stay on the page (#2421).
* BS5 templates no longer include empty link to logo when none exists (#2536).
* Updated translations from @jplecavalier, @dieghernan, @krlmlr, @LDalby, @rich-iannone, @jmaspons, and @mine-cetinkaya-rundel (#2659).

## `_pkgdown.yaml`

* Anywhere you can use `_pkgdown.yml`, you can now use `_pkgdown.yaml` (#2244).
* Custom navbars that specify `icon` but not `aria-label` will now generate a message reminding you to provide one for to improve accessibility (#2533).
* The `repo.source.url` field no longer requires a trailing slash (#2017).
* The `template.bslib` item now also accepts a `bootswatch` key (@gadenbuie, #2483).
* You can now choose where the search box is placed with the "search" navbar component. This has been documented for a very long time, but as far as I can tell, never worked (#2320). If you have made your own template with a custom `navbar`, you will need to remove the `<form>` with `role="search"` to avoid getting two search boxes.

## Minor improvements and bug fixes

* pkgdown now uses httr2 instead of httr (#2600).
* Mathjax now uses version 3.2.2.
* The addin now runs `build_site()` instead of `build_site_external()`, which generally should be more reliable (#2252).
* `<source>` tags now have their `srcref` attributes tweaked in the same way that the `src` attributes of `<img>` tags are (#2402).
* `as.pkgdown()` will no longer prompt you to install a missing template package from CRAN, since these are almost always found in GitHub (#2076).
* `build_articles()` now recognises a new `external-articles` top-level field that allows you to define articles that live in other packages (#2028).
* `build_article()` no longer has a `data` argument. This is technically a breaking change, but I can't figure out why anyone would have ever used it.
* `build_*()` (apart from `build_site()`) functions no longer default to previewing in interactive sessions since they now all emit specific links to newly generated files.
* `build_article()` now translates the "Abstract" title if it's used.
* `build_article()` now escapes html characters in the title (#2286).
* `build_article()` no longer generates the wrong source link when you build your site outside of the root directory (#2172).
* `build_articles()` now reports if you are missing alt-text for any images (#2357).
* `build_articles()` now drops a section called "internal". This allows you to have articles that either aren't indexed at all or are included manually elsewhere in the navbar (#2205).
* `build_home()` now correctly escapes special HTML characters in the bibtex citation (#2022).
* `build_home()` no longer checks if the README is missing any images. This check is now performed in `build_site()`, after `build_articles()` so you can refer to images created by vignettes with warnings (#2194).
* `build_home()` now includes the contents of `inst/AUTHORS` on the authors page (#2506).
* `build_home_index()` now reports when rendering the home page (#2544).
* `build_home_index()` now renders math if you use it in your home page (#2263).
* `build_news()` now works if your package has been archived at some point (#2687).
* `build_news()` only syntax highlights the page once, not twice, which prevents every block of R code getting a blank line at the start (#2630).

    ```R
    1 + 1
    ```
* `build_reference()` no longer displays `\dontshow{}` or `\testonly{}` blocks in examples. It will run the code in `\dontshow{}`; it won't run the code in `\testonly{}`(#2188).
* `build_reference()` does a better job of parsing `\value{}` blocks (#2371).
* `build_reference()` now generates the usage that users actually type for infix and replacement methods (#2303).
* `build_reference()` now automatically translates `--`, `---`, ``` `` ```, and `''` to their unicode equivalents (#2530).
* `build_reference()` now supports `\Sexpr[results=verbatim]` (@bastistician, #2510).
* `build_reference()` adds anchors to arguments making it possible to link directly to an argument, if desired. A subtle visual treatment makes it easy to see which argument is targeted (#2228).
* `build_reference()` now automatically renders any tables created by gt (#2326).
* `build_reference()` matches usage for S3 and S4 methods to the style used by R 4.0.0 and later (#2187).
* `build_reference_index()` now displays function lifecycle badges next to the function name (#2123). The badges are extracted only from the function description. You can now also use `has_lifecycle()` to select functions by their lifecycle status.
* `build_redirects()` is now exported to make it easier to document (#2500).
* `build_redirects()` now automatically adds redirects for topic
aliases. This matches the behaviour of `?` and will help keep links stable in the long term (#1876).
* `build_redirects()` now reports which redirects it is generating.
* `build_site()` automatically runs `pkgdown_sitrep()` at the start of the process (#2380).
* `build_sitemap()` no longer includes redirected pages (#2582).
* `check_pkgdown()` and `pkgdown_sitrep()` have been unified so that they both report on the same problems. They now only differ in the style of their output: `pkgdown_sitrep()` reports whether each category is ok or not ok, while `check_pkgdown()` errors on the first issue (#2463).
* `init_site()` will no longer automatically build favicons on CI systems (e.g. GHA). This is an expensive operation that uses an external service so it should only be run locally (#2553).
* `init_site()` once again describes one copy per line, and now uses a better prefix when copying assets from pkgdown itself (#2445).
* `pkgdown_sitrep()`/`check_pkgdown()` now check that you have up-to-date favicons if you have a package logo.
* `template_reference()` and `template_article()` now only add backticks to function names if needed (#2561).
* `vignette("search")` has been removed since BS3 is deprecated and all the BS5 docs are also included in `build_search()` (#2564).

# pkgdown 2.0.9

* Fixes for regressions in 2.0.8:

  * Output links generated when building the site work once again (#2435).

  * pkgdown once again uses Bootstrap version specified in a template
    package (@gadenbuie, #2443).

* Front-end improvements:

  * The skip link now becomes visible when focussed (#2138). Thanks to @glin
    for the styles!

  * The left and right footers no longer contain an extra empty paragraph tag
    and the footer gains additional padding-top to keep the whitespace constant
    (#2381).

  * Clipboard buttons report their action again ("Copied!") (#2462)

* It is now easier to preview parts of the website locally interactively.
  `build_reference_index()` and friends will call `init_site()` automatically
  instead of erroring (@olivroy, #2329).

* `build_article()` gains a new `new_process` argument which allows to build a
   vignette in the current process for debugging purposes. We've also improved
   the error messages and tracebacks if an article fails to build, hopefully
   also making debugging easier (#2438).

* `build_article_index()` and `build_reference_index()` use an improved BS5
  template that correctly wraps each section description in a `<div>`, rather
  than a `<p>`. This eliminates an empty pargraph tag that preceded each section
  description (#2352).

* `build_home()` no longer errors when you have an empty `.md` file (#2309).
  It alos no longer renders Github issue and pull request templates
  (@hsloot, #2362)

* `build_news()` now warns if it doesn't find any version headings, suggesting
  that that `NEWS.md` is structured incorrectly (#2213).

* `build_readme()` now correctly tweaks links to markdown files that use an
  anchor, e.g. `foo.md#heading-name` (#2313).

* `build_reference_index()` gives more informative errors if your `contents`
  field is malformed (#2323).

* `check_pkgdown()` no longer errors if your intro vignette is an article is
  not listed in `_pkgdown.yml` (@olivroy #2150).

* `data_template()` gives a more informative error if you've misspecified the navbar (#2312).

# pkgdown 2.0.8

* pkgdown is now compatible with (and requires) bslib >= 0.5.1
  (@gadenbuie, #2395), including a fix to BS5 navbar template to get
  `navbar.type: dark` to work with Bootstrap 5.3+ (@tanho63, #2388)

* Now uses [cli](https://github.com/r-lib/cli) to provide interactive feedback.

* Avoid unwanted linebreaks from parsing `DESCRIPTION` (@salim-b, #2247).

* Translations
  * New Catalan translation (@jmaspons, #2333).
  * Citation sections are correctly translated (@eliocamp, #2410).

* `build_article_index()` now sorts vignettes and non-vignette articles
   alphabetically by their filename (literally, their `basename()`), by default
   (@jennybc, #2253).

* Deprecated `build_favicon()` was removed (`build_favicons()` remains).

* `build_articles()` now sets RNG seed by default. Use
  `build_articles(seed = NULL)` for the old (unreproducible) behaviour.
  (@salim-b, #2354).

* `build_articles()` will process `.qmd` articles with the quarto vignette
  builder (@rcannood, #2404).

* `build_articles()` and `build_reference()` now set RNG seed for htmlwidgets
  IDs. This reduces noise in final HTML output, both for articles and examples
  that contain htmlwidgets (@salim-b, #2294, #2354).

* `build_news()` correctly parses  of github profiles and issues into links
  when present at the beginning of list items (@pearsonca, #2122)

* `build_reference()` sets `seed` correctly; it was previously reset too early
   (@salim-b, #2355)

* Rd -> html translation
  * `\cr` is now translated to `<br>` not `<br />` (#2400).
  * Correct usage for S3 methods with non-syntactic class names (#2384).
  * Preserve Markdown code blocks with class rmd from roxygen2 docs (@salim-b, #2298).

* `build_reference_index()` no longer generates redundant entries when multiple
  explicit `@usage` tags are provided (@klmr, #2302)

* `build_reference_index()` correctly handles topic names that conflict with
  selector functions (@dmurdoch, #2397).

# pkgdown 2.0.7

* Fix topic match selection when there is an unmatched selection followed by a matched selection (@bundfussr, #2234)
* Fix highlighting of nested not R code blocks (for instance, example of R
Markdown code with chunks) (@idavydov, #2237).
* Tweak German translation (@krlmlr, @mgirlich, @lhdjung, #2149, #2236)
* Remove mention of (defunct) Twitter card validator, provide alternatives (@Bisaloo, #2185)
* Fix `keywords` typo in `check_missing_topics()` message (@swsoyee, #2178).
* Use jsdeliver CDN for bootstrap-toc (@GregorDeCillia, #2207).

# pkgdown 2.0.6

* If you're using an RStudio daily, output file names are now clickable,
  previewing the generated HTML in the browser (#2157).

* Getting started vignette no longer needs to be included in the articles index
  (#2150).

* If there aren't any functions in the `\usage{}` block, then pkgdown will
  now shows all aliases on the reference index, rather than just the topic
  name (#1624).

# pkgdown 2.0.5

* Correctly generate downlit link targets for topics that have a file name
  ending in `.` (#2128).

* `build_articles()`: if build fails because the index doesn't include all
  articles, you're now told what articles are missing (@zkamvar, #2121).

* `build_home()` now escapes angle brackets in author comments(#2127).

* `build_home()` will automatically render and link `.github/SUPPORT.md`
  (@IndrajeetPatil, #2124).

* `build_news()` once again fails to link `@username` at start of
  bullet. I had to reverted #2030 because of #2122.

* `build_reference()`: restore accidentally nerfed `has_keyword()` and
  `has_concept()` reference selectors (#2126) and add tests.

# pkgdown 2.0.4

* New `check_pkgdown()` provides a lightweight way to check that your
  `_pkgdown.yml` is valid without building the site (#2056). Invalid
  `_pkgdown.yml` now consistently generates errors both locally and on
  CI (#2055).

* `build_article()` now supports inline markdown in the `title` (#2039).

* `build_home()` no longer shows development status badges on the released
  version of the site (#2054).

* `build_news()` support automated `@username` links in more places (#2030).

* `build_reference()`:

    * You can once again exclude topics from the reference index with `-` (#2040).

    * Inline markdown in `title`s and `subtitle`s is now supported(#2039).

    * Package logos will be automatically stripped from the `.Rd` you don't end
      up with two on one page. (#2083).

    * `\figure{file}{alternative text}` with multiline alt text is now parsed
      correctly (#2080)

    * roxygen 7.2.0 output for generic code blocks (#2092, @jabenninghoff) is
      processed correctly.

* Front end changes:

    * Automatically added links in code blocks are now styled less aggressively,
      so they occupy less visual weight on the page (#2007).

    * All article pages are given class `col-md-9` for consistency with other
      pages (#2045).

    * Fixed width HTML widgets are sized correctly (@dmurdoch, #2062).

    * Footnotes work with more contents, including code (@banfai, #2042).

    * Navbar components now accept `target` argument (#2089, @JSchoenbachler).

* New syntax highlighting themes a11y-light, a11y-dark, monochrome-light,
  monochrome-dark, and solarized

# pkgdown 2.0.3

* Fixes for R CMD check

# pkgdown 2.0.2

* New Korean (`ko`) translation thanks to @mrchypark and @peremen (#1944).
  New Danish (`dk`) translation thanks to @LDalby.

* `build_articles()` now adjusts the heading levels of vignettes/articles that
  use `<h1>` as section headings to ensure that there's one top-level heading
  (#2004). This ensures that there's one `<h1>`, the title, on each page,
  and makes the TOC in the sidebar work correctly.

* `build_home_index()` no longer spuriously complains about missing images
  if you use plots in your `README.Rmd` (#1980, #1977). It no longer
  tweaks the `src` path for `<img>` tags with absolute paths (#1955).

* `build_news()` once again works if `NEWS.md` uses `<h1>` headings (#1947).

* `build_reference()` now correctly interprets `title: internal`: it removes
  the section from the reference index _and_ it doesn't list the topics in that
  section as missing (#1958).

* `build_reference()` now gives a correct hint when the reference index YAML
  is not formatted correctly (e.g. empty item, or item such as "n" that needs
  to be escaped with quotes to not be interpreted as Boolean) (#1995).

* `deploy_to_branch()` gains a `subdir` argument, allowing you to deploy the
  site to a subdirectory (@gadenbuie, #2001).

* Front end changes:

    * The navbar gets a little more space after the version number, and aligns
      the baseline with rest of the navbar (#1989).

    * Long lines in code output once again scroll, rather than being wrapped.
      While this is different to what you'll see in the console, it's a better
      fit for web pages where the available code width varies based on the
      browser width (#1940).

    * scrollspy (which highlights the "active" heading in the sidebar) now
      computes the offset dynamically which makes it work better on sites with
      taller navbars (#1993).

    * Fixed js issues that occurred on pages without a table of contents
      (@gadenbuie, #1998).

    * When htmlwidgets with jQuery or Bootstrap dependencies are used in examples or
      articles, pkgdown's versions of jQuery and Boostrap will take precedence over
      the versions used by the htmlwidget (@gadenbuie, #1997).

* pkgdown no longer includes bundled author metadata for Hadley Wickham,
  RStudio, or the RConsortium, since there are now ways to include this
  meta data in template packages, and special casing these three entities
  feels increasingly weird (#1952).

# pkgdown 2.0.1

* Fix CRAN failures.

* Reference sections are de-duplicated correctly (#1935).

* Usage sections only generated for topics that have them; usage correctly
  displayed with BS3 (#1931)

* Empty `\value{}` no longer errors (#1930).

# pkgdown 2.0.0

## New authors

@maelle is now a pkgdown author in recognition of her significant and sustained contributions. She was the powerhouse behind many of the improvements in this release, particularly the switch to bootstrap 5, improvements to customisation, and implementation of local search.

## Bootstrap 5

* pkgdown can style your site with Bootstrap 5 (with help from @jayhesselberth,
  @apreshill, @cpsievert). Opt-in by setting `boostrap` version in your
  `_pkgdown.yml`:

    ```yaml
    template:
      bootstrap: 5
    ```

* We reviewed site accessibility and made a number of small improvements:
  (#782, #1553):

    * Default font is larger and links are always underlined.
    * Heading anchors use `aria-hidden` to reduce noise for screenreader users.
    * Navbar dropdowns has improved `aria-labelledby`.
    * The default GitHub/GitLab links gain an `aria-label`; use for other
      icons is now supported, and encouraged in the docs.
    * Syntax highlighting uses a new more
      [accessible colour scheme](https://apreshill.github.io/rmda11y/arrow.html),
      designed by Alison Hill (#1536)
    * A skip link makes it easier to get directly to the page contents (#1827).

* In-line footnotes mean you can read asides next to the text they refer to.

* Articles support tabsets,
  [as in R Markdown](https://bookdown.org/yihui/rmarkdown-cookbook/html-tabs.html).
  (@JamesHWade, #1667).

* Other minor styling improvements:

    * The active item in TOC is indicated with background colour, rather than
      a border.
    * If present, the package logo is shown on all pages near the header.
    * Section anchors now appear on the right (making them usable on mobile
      phones) (#1782).
    * The TOC is scrollable independently of the main content. This makes it
      more useful on long pages with many headings (#1610).
    * The sidebar is shown at the bottom of the page on narrow screens.
    * Function arguments and the reference index (#1822) use definition lists
      (`<dl>`) instead of tables. This gives more room for long argument
      names/lists of function and detailed descriptions, and displays better
      on mobile.
    * Links on the homepage no longer show the full url in the text.
    * The default navbar no longer includes a home icon - this took up
      precious horizontal space and wasn't very useful since there was already
      a link to the home page immediately to its left (#1383).

## Local search

* pkgdown now supports local searching (i.e. searching without an external
  service), and is enabled by default for Bootstrap 5 sites since no set-up is
  needed (#1629, with help from @gustavdelius in #1655 and @dieghernan &
  @GregorDeCillia in #1770).

* pkgdown builds a more exhaustive `sitemap.xml` even for websites built with
  Bootstrap 3. This might change Algolia results if you use Algolia for search
  (#1629).

## Customisation

* New `vignette("customise")` documents all the ways you can customise your
  site, including the new options described below (#1573).

* Sites can be easily themed with either bootswatch themes or by selectively
  overriding the `bslib` variables used to generate the CSS. pkgdown now uses
  scss for its own Bootstrap css tweaks, which means that you can customise
  more of the site from within `_pkgdown.yml`.

* You can pick from a variety of built-in syntax highlighting themes (#1823).
  These control the colours (and background) of code in `<pre>` tags.

* pkgdown can now translate all the text that it generates (#1446): this means
  that if you have a package where the docs are written in another language, you
  can match all the pkgdown UI to provide a seamless experience to non-English
  speakers. Activate the translations by setting the `lang` in `_pkgdown.yml`:

    ```yaml
    lang: fr
    ```

    pkgdown includes translations for:

    * `es`, Spanish, thanks to @edgararuiz-zz, @dieghernan, @rivaquiroga.
    * `de`, German, thanks to @hfrick.
    * `fr`, French, thanks to @romainfrancois, @lionel-, @jplecavalier, and @maelle.
    * `pt`, Portuguese, thanks to @rich-iannone.
    * `tr`, Turkish, thanks to @mine-cetinkaya-rundel.
    * `zh_CN`, simplified Chinese, thanks to @yitao.

    If you're interested in adding translations for your language please file
    an issue and we'll help you get started.

* Template packages can now provide `inst/pkgdown/_pkgdown.yml` which is used
  as a set of defaults for `_pkgdown.yml`. It can be used to (e.g.) provide
  author definitions, select Bootstrap version and define bslib variables,
  and customise the sidebar, footer, navbar, etc. (#1499).

* New `includes` parameters `in-header`, `before-body`, and `after-body`
  make it easy to add arbitrary HTML to every page. Their content will be
  placed at the end of the `<head>` tag, right below the opening `<body>` tag,
  and before the closing tag `</body>` respectively (#1487). They match the
  bookdown options `in_header`, `before_body` and `after_body`.

    Additionally, you can use `before_title`, `before_navbar`, and
    `after_navbar` to add arbitrary HTML into the navbar/page header; they
    will appear to the left of the package name/version, and to the left and
    right of the navigation links respectively (#1882).

* Authors configuration is more flexible (#1516). You can now:

    * Choose the roles used for filtering authors for the sidebar and footer.
    * Choose the text before authors in the footer.
    * Add text before and after the authors list in the sidebar.
    * Add text before and after the authors list of the authors page.

* Sidebar specification is more flexible (#1443, #1488, #1502). You can now:

    * Change the order of sidebar elements.
    * Add custom sidebar sections (with Markdown/HTML `text`).
    * Add a table of contents to the home page.
    * Completely suppress the sidebar.
    * Provide your own HTML for the navbar.

* Footer specification is more flexible (#1502). You can now:

    * Change the placement of elements on the left and right.
    * Add text to the left and right (or even remove/replace default text)

* You can now exclude all default components from the navbar (#1517).

* Expert users can now override layout templates provided by pkgdown or template
  packages by placing template files in `pkgdown/templates` (@gadenbuie, #1897).

## New features

* pkgdown now supports redirects (#1259, @lorenzwalthert). The following yaml
  demonstrates the syntax, with old paths on the left and new paths/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"]
  ```

* Use HTML classes `pkgdown-devel` or `pkgdown-release` to declare that certain
  content should appear only on the devel or release site. Use the class
  `pkgdown-hide` for content that should only appear only on GitHub/CRAN
  (#1299).

* New `pkgdown_sitrep()` function reports whether the site is set up correctly;
  in particularly it currently reports if auto-linking will work (#1478).

## Code

* Styling for errors, warnings, and messages has been tweaked. Messages
  are now displayed the same way as output, and warnings and errors are
  bolded, not coloured. This is part of a suite of changes that aim to
  give package authors greater control over the appearance of messages,
  warnings, and errors.

* Long lines in code output are now wrapped, rather than requiring scrolling.
  This better matches `rmarkdown::html_document()` and what you see in the
  console.

* `build_reference()` now allows linking to topics from other packages (either
  function names e.g. `rlang::is_installed` or topic names e.g.
  `sass::font_face`). (#1664)

* `build_reference()` now runs examples with
  `options(rlang_interactive = FALSE)` (ensuring non-interactive behaviour in
  functions that use `rlang::is_interactive()`), `options(cli.dynamic = FALSE)`,
  `Sys.setenv(RSTUDIO = NA)` and `Sys.setLocale("LC_COLLATE", "C")` (#1693).
  It also runs `pkgdown/pre-reference.R` before and `pkgdown/post-reference.R`
  after examples. These allow you to do any setup or teardown operations you
  might need (#1602).

* A reference index section with `title: internal` is now silently dropped,
  allowing you to suppress warnings about topics that are not listed in the
  index (#1716).

* Code blocks are now highlighted according to their declared language
  (e.g. `yaml`) if the documentation was built with roxygen2 7.1.2 or later
  (#1690, #1692).

* New `pkgdown_print()` allows you to control how your objects are rendered in
  examples. It includes built-in handling for htmlwidgets and "browseable" HTML
  so pkgdown output now more closely resembles what you see in RStudio.
  Added extension points to make HTML widgets (and RGL in particular) work
  in rendered examples (@dmurdoch).

* You can globally set the `width` of code output (in reference and articles)
  with

    ```yaml
    code:
      width: 50
    ```

* Articles now render output styles created by cli/crayon (#1556).

* When copy and pasting code blocks, lines containing output (e.g. `#>`)
  are automatically omitted (#1675).

* Auto-linking improvements:

  * Links to inherited R6 methods now work correctly for both internal
    (#1173, @vandenman) and external (#1476) parent classes.

  * Linking no longer fails if a package contains duplicated Rd aliases.

  * Correctly link to reference pages when the `\name{}` entry doesn't match
    the file name (@dmurdoch, #1586; #1676).

## Articles

* Article subtitle, author and date (specified in the YAML frontmatter) are now
  correctly omitted from the article table of contents in the sidebar
  (@maxheld83, #1428).

* Support for `as_is: true` and non-default output formats for vignettes/
  articles has been somewhat improved. Support is fundamentally limited due to
  the challenges of integrating HTML from output formats that pkgdown doesn't
  know about, but it should be a little more reliable and a little better
  documented (#1757, #1764).

* `build_articles()` no longer fails if you have a directory underneath
  vignettes with a `.Rmd` extension (#1425).

* `build_articles()` now correctly handles links to images in `man/figures`
  (which have the form `../man/figures`) (#1472).

* `build_articles()` again sets the `theme` argument of the document format
  to `NULL` when `as_is: true` but lets users override this via the `theme`
  argument of the output format.

* `build_articles()` and `build_home()` now warn if you have images that
  won't render on the website because they're in unsupported directories
  (#1810). Generally, it's only safe to refer to figures in `man/figures`
  and `vignettes`.

* Articles stored in `vignettes/articles` are moved up one level so that they
  appear in `articles/` on the website. Previously, they would appear in
  `articles/articles`, so `build_redirects()` automatically adds redirects for
  any articles in the `vignettes/articles` directory (@gadenbuie #1911).

## HTML, CSS and JS

* New `template` option `trailing_slash_redirect` that allows adding a script to
  redirect `your-package-url.com` to `your-package-url.com/` (#1439, @cderv,
  @apreshill).

* External links now get the class `external-link`. This makes them easier to
  style with CSS (#881, #1491).

* Duplicated section ids are now de-duplicated; this makes pkgdown work better
  with the documentation of R6 classes.

* Updated CSS styles from pandoc to improve styling of reference lists (#1469).

## Deployment

* `build_site_github_pages()` has been extracted out of `deploy_site_github()`
  to make it easier to decouple building and deployment, and so we can take
  advantage of standard deployment actions (#1756).

* `deploy_to_branch()` now calls `git remote set-branches` with `--add` to avoid
  overwriting the existing `remote.{remote}.fetch` value (@kyleam, #1382).
  It also now cleans out the website directory by default; revert to previous
  behaviour with `clean = FALSE` (#1394).

* `build_reference()` will error if envar `CI` is `true` and there are missing
  topics (@ThierryO, #1378).

* You can override the `auto` development mode detected from the package
  version by setting env var `PKGDOWN_DEV_MODE` to `release` or `devel`.
  This is useful if your package uses a different convention to indicate
  development and release versions (#1081).

## Other minor improvements and bug fixes

* `\special{}` tags with complex contents are rendered correctly (@klmr, #1744).

* `\arguments{}` and `\value{}` do a better job of handling mingled items and
  text (#1479). The contents of `\value{}` are now shown immediately after
  `\arguments{}`.

* The default "branch" for linking to the file sources is `HEAD`, which will
  work regardless of whether your default branch is called "main" or "master".

* Non-ORCID comments in `Authors@R` are now more usable: if such comments
  exist, the sidebar gains a link to the authors page, where they are displayed
  (#1516).

* Citations with and without text versions are better handled, and text
  citations are correctly escaped for HTML (@bastistician, #1507).

* README badges in a single paragraph placed between `<!-- badges: end -->`and
  `<!-- badges: end -->` comments are again detected (#1603).

* The 404 page (default or from `.github/404.md`) is no longer built in the
  development mode (see `?build_site`) as e.g. GitHub pages only uses the
  `404.html` in the site root (#1622).

* All links on the 404 pages (navbar, scripts, CSS) are now absolute if there
  is an URL in the configuration file (#1622).

* The version tooltip showed in the top navbar is now only set if you've
  explicitly set the `development.mode` in `_pkgdown.yml` (#1768).

* All heading (e.g. headings on the reference index page, and the arguments
  heading on the reference pages) now get anchors (#1747).

* Use `autolink_bare_uris` for Pandoc above version 2.0 (@marcosmolla, #1618).

* pkgdown now recognizes GitLab URLs to the source repository and adds the
  corresponding icon to the navbar (#1493). It also supports
  [GitLab subgroups](https://docs.gitlab.com/ee/user/group/subgroups/)
  (@salim-b, #1532).

* Links for GitHub Enterprise and GitLab Enterprise repositories are detected
  by assuming such host address begin with `github.` or `gitlab.`
  (@ijlyttle, #1452).

* The rules drawn by the CLI (as for example, in `build_site()`) are protected
  against very narrow terminal windows (@maxheld83, #1435).

* Google Site Verification (https://support.google.com/webmasters/answer/9008080?hl=en)
  can now be configured for pkgdown sites.

* `build_rmarkdown_format` sets `html_document(anchor_sections = FALSE)`
   to avoid needless dependencies (@atusy, #1426).

* Jira issues in NEWS can be automatically linked by setting your project name
  (s) with  `repo: jira_projects: [...]` and specifying a custom issue URL with
  `repo: url: issue: ...` in `_pkgdown.yml` (@jonkeane, #1466).

* `build_home()` always creates citation information for the authors page,
  using metadata from `DESCRIPTION` when there is no `inst/CITATION` file,
  and links to this from the sidebar (#1904).

* `build_news()` no longer breaks with URLs containing numeric fragments
  (@krassowski, #1456), recognises more styles of release heading (#1437),
  and generate stable IDs using a the combination of the heading slug and
  package number. (@Bisaloo, #1015)

# pkgdown 1.6.1

* The article index (used for autolinking vignettes across packages)
  once again works (#1401).

# pkgdown 1.6.0

## Major changes

* pkgdown now uses the new [downlit](https://downlit.r-lib.org/) package for all
  syntax highlighting and autolinking (in both reference topics and vignettes).
  There should be very little change in behaviour because the code in downlit
  was extracted from pkgdown, but this makes it easier to use pkgdown's nice
  linking/highlighting in more places (#1234).

* pkgdown now uses the `ragg::agg_png()` device to generate example figures.
  This should be a little faster and produce higher quality output. Learn
  more at <https://ragg.r-lib.org> (#1320).

## Minor improvements and bug fixes

### Rd translation

* `\special{}` support inside `\usage{}` added to allow non-standard R usage
  syntax (@klmr, #1345).

* `#ifdef` and `#ifndef` are now supported; the "current" OS is hard coded to
  "unix" to ensure reproducible output regardless of where you build the
  website (#1384).

* Nested `\subsection{}`s now generate appropriate heading levels
  (h3, h4, h5 etc) (#1377), and get anchor links (#1389).

* `\preformatted{}` no longer double escapes its contents (#1311).

### Articles and vignettes

* `build_articles()` no longer sets the `theme` argument of the document format
  to `NULL` when `as_is: true`. This should allow it to work with a wider
  range of output formats including `bookdown::html_vignette2()` and
  friends (@GegznaV, #955, #1352).

* When `build_article()` fails, it gives the complete failure message (#1379).

* Markdown header attributes are now processed in all markdown files (@jonkeane, #1343)

### Auto-linking and syntax highlighting

* The branch used for source linking can be configured by setting
  `repo: branch: branch_name` in `_pkgdown.yml` (@jonkeane, #1355):

    ```yaml
    repo:
      branch: main
    ```

* `autolink_html()` is (soft) deprecated. Please use
  `downlit::downlit_html_path()` instead.

* Highlighting of empty expressions works once more (#1310).

* New `deploy$install_metadata` option in `_pkgdown.yml`. Setting it to
  `true` will store site metadata in the package itself, allowing offline
  access for packages that to autolink to the package's website
  (@mstr3336, #1336).

### Other

* You can now control the background colour of plots with the `figures.bg`
  option (it is transparent by default, and given a white background by
  css). See `?build_reference` for an example.

* HTML is automatically stripped from the page title (#1318).

* Suppressing CRAN dates in news file now actually works.

* All HTTP requests are now retried upon failure (@jameslamb, #1305).

* Setting `clean = TRUE` in `deploy_site_github()` removes old files from the
  deployed site before building a new one (#1297).

# pkgdown 1.5.1

* Syntax highlighting works on Windows once more (#1282).

* pkgdown no longer fails if your `.Rd` files have duplicated `\aliases`
  as were produced by an older version of roxygen2 (#1290).

* Rendering empty `.md` file now returns empty string (#1285).

* `build_articles_index()` is now exported to rapidly rebuild the index (#1281)

* `deploy_site_github()` now accepts a `host` argument to specify alternate
  hosts (e.g., Github enterprise) (@dimagor, #1165) and once again works as
  intended on Travis-CI (@jimhester, #1276).

# pkgdown 1.5.0

## New features

* The articles index page and navbar have been overhauled. There are two
  major new features in this release:

    * The articles index page now displays article `description`s,
      taken from YAML metadata belonging to each article. This lets you provide
      more context about each article and describe why one might want to read
      it (#1227).

    * The articles navbar is now also controlled by the `articles` section
      in `_pkgdown.yml`. The ordering of the sections, and articles within
      them, control the order of the articles in the navbar, and you can
      use the new `navbar` field to control whether or not each section
      appears in the navbar (#1101, #1146).

* The reference index now has two levels of heading hierarchy: `title` and
  `subtitle` (#327).

* Tables of contents in sidebars now use
  [bootstrap-toc](https://afeld.github.io/bootstrap-toc/); this considerably
  improves navigation for long articles and reference pages.

* You can now control the links to source files (in reference pages and
  articles) and issues and users (in the NEWS) with new `repo$url` config
  option (#1238). This makes it easier to use pkgdown with GitHub enterprise,
  packages in subdirectories, and other source hosts (like bitbucket).

    ```yaml
    repo:
      url:
        home: https://github.com/r-lib/pkgdown/
        source: https://github.com/r-lib/pkgdown/blob/main/
        issue: https://github.com/r-lib/pkgdown/issues/
        user: https://github.com/
    ```

    The individual components (e.g. path, issue number, username) are pasted on
    the end of these urls so they should have trailing `/`s.

    You don't need to set these links for GitLab, as pkgdown now detects
    GitLab urls automatically (since they use the same structure as GitHub)
    (#1045).

* There's much richer control over Open Graph and Twitter metadata for the
  whole site and for individual articles. See new `vignette("metadata")` for
  details (@gadenbuie, #936).

* New `deploy_to_branch()` function to build and deploy a site to a branch,
  defaulting to `gh-pages` for use with GitHub Pages. This is used in our
  recommended GitHub action workflow for automatically building and deploying
  pkgdown sites for packages on GitHub (@jimhester, #1221).

* Updated JS libraries: jquery 3.3.1 -> 3.4.1; bootswatch 3.3.7 -> 3.4.0;
  bootstrap 3.3.7 -> bootstrap 3.4.1; docsearch 2.6.1 -> 2.6.3;
  fontawesome 5.11.1 -> 5.12.1; headroom.js 0.9.44 -> 0.11.0;
  clipboard.js 2.0.4 -> 2.0.6 (@jayhesselberth).

## Auto-linking improvements

* Examples and Rmd now use exactly the same syntax highlighting strategy.

* In examples and Rmd, calls of the form `current_package::foo` now get
  a local link (#1262).

* `\preformatted{}` blocks are now highlighted and linked if they parse
  as R code (#1180).

* `library(pkgdown)` is now automatically linked to the reference index for
  "pkgdown" not the documentation for `library()` (#1161).

* `help("topic")` is now automatically linked to the documentation for "topic",
  not to the documentation for `help()` (#1210)

## Minor improvements and bug fixes

### Articles

* `build_home()` no longer uses (unrendered) `README.Rmd` or `index.Rmd` if
  corresponding `.md` files are not found.

* `build_article()` failures now print more information to help you debug
  the problem (#952).

* The name of the vignette mapped to the "Get started" entry in the navbar
  is now more flexible. You can use an article (e.g `articles/{pkgname}`)
  and if your package has a `.` in its name you can replace it with `-` to
  generate a valid article name (e.g. the get started vignette for
  `pack.down` would be `pack-down`) (#1166).

### Deployment

* `deploy_to_branch()` now correctly captures the commit SHA on GitHub Actions
  (@coatless, #1252).

* `deploy_to_branch(github_pages = TRUE)` generates a `.nojekyll` to prevent
  jekyll ever executing (#1242).

* `CNAME` is no longer generated by `init_site()`, but is instead conditionally
  by `deploy_to_branch()` when `github_pages = TRUE`. This is a better a fit
  because the `CNAME` file is only needed by GitHub pages (#969).

* `deploy_site_github()` argument `repo_slug` has been deprecated and is no
  longer needed or used. (@jimhester, #1221)

### News
See additional details in `?build_news`:

* You can optionally suppress the CRAN release dates added to the news
  page (#1118).

* Multi-page news style gets a better yaml specification (the old style
  will continue to work so no need to change existing YAML).

### Reference

* A topic named `index` will not longer clobber the reference index (#1110).

* Topic names/aliases on reference index are now escaped (#1216).

* `build_reference()` gives better warnings if your `_pkgdown.yml` is
  constructed incorrectly (#1025).

* New `has_keyword()` topic selector for `reference`. `has_keyword("datasets")`
  is particularly useful for selecting all data documentation (#760).

* New `lacks_concepts()` can select topics that do not contain any of
  a number of specified concepts. (@mikldk, #1232)

### Home, authors, and citation

* pkgdown now escapes html and linkifies links in comments in author info
  from DESCRIPTION (@maelle, #1204)

* pkgdown now uses the ORCiD logo included in Font Awesome 5.11 instead of
  querying it from members.orcid.org (@bisaloo, #1153)

* badges are now extracted from everything between `<!--badges: start-->`
  and `<!--badges: end-->`. They used to be extracted only if they were
  direct children of the first `<p>` after `<!--badges: start-->`.

* `build_home()` now looks for `pkgdown/index.md` in addition to the top-level
  `index` or `README` files (@nteetor, #1031)

### Navbar

* pkgdown now formats the package version displayed in the navbar the same way
  as it has been specified in the DESCRIPTION file. In particular, version
  separators (e.g. `.` and `-`) are preserved. (#1170, @kevinushey)

* add support for navbar submenus: you can create submenus following the
  convention established in [rstudio/rmarkdown#721](https://github.com/rstudio/rmarkdown/issues/721) (@ijlyttle, @wendtke, #1213)

### Other

* Updated JS libraries: jquery 3.3.1 -> 3.4.1; bootswatch 3.3.7 -> 3.4.0;
  bootstrap 3.3.7 -> bootstrap 3.4.1; docsearch 2.6.1 -> 2.6.3
  (@jayhesselberth).

* Markdown conversion now explicitly allows markdown inside of HTML blocks;
  this was previously accidentally disabled (#1220).

* A timestamp for the last site build is reported in `pkgdown.yml` (#1122).

# pkgdown 1.4.1

* Don't install test package in user library (fixes CRAN failure).

# pkgdown 1.4.0

## New features

* build citation as specified by the `textVersion` argument of `citEntry` in the
  `CITATION` file (#1096, @yiluheihei)

* `build_site()`, `build_reference()` and `build_home()` gain a parameter
  `devel` which controls whether you're in deployment or development mode.
  It generalises and replaces (with deprecation) the existing `document`
  argument.

    Development mode is optimised for rapid iteration and is the default
    for `build_reference()`. It uses `pkgload::load_all()` to load code
    directly from disk in order.

    Deployment mode is slower, but guarantees correct results, and is the
    default for `build_site()`. It installs the package into a temporary
    library, and runs examples/articles in a new process.

* `build_reference()` no longer runs `devtools::document()` (#1079) and
  `build_home()` no longer re-builds `README.Rmd` or `index.Rmd`. This makes
  the scope of responsibility of pkgdown more clear: it now only
  creates/modifies files in `doc/`.

* `build_home()` now strips quotes from `Title` and `Description` fields
  when generating page metadata. Additionally, you can now override the
  defaults via the `title` and `description` fields in the `home` section of
  `_pkgdown.yml` (#957, @maelle).

* `vignette("linking")` describes how pkgdown's automatic linking works, and
  how to ensure that cross-package links point to the right place.

## Bug fixes and minor improvements

### Rd translation

* `\examples{}` rendering has been completely overhauled so it now first
  converts the entire mixed Rd-R block to R prior, and then evaluates the
  whole thing. This considerably improves the fidelity of the translation
  at a small cost of no longer being able to remove `\donttest{}` and
  friends (#1087).

* `\item{}`s in `\describe{}` containing whitespace are translated correctly
  (#1117).

* `\dots` and `\ldots` are translated to `...` instead of the ellipsis,
  since they're often found in code (#1114).

* `\tabular{}` translation handles code better (@mitchelloharawild, #978).

* `\subsection{}` contents are now treated as paragraphs, not inline text
  (#991).

* `\preformatted{}` blocks preserve important whitespace (#951).

### Front end

* Links to online documentation for functions in code chunks are no longer
  displayed when printing (#1135, @bisaloo).

* Updated fontawesome to v5.7.1. fontawesome 5 deprecated the `fa` prefix.
  If you have used custom icons in your navbar, you'll should update them from
  (e.g.) `fa fa-home` to `fas fa-home`. Brands now have a separate prefix so
  `fa fa-github` becomes `fab fa-github` (#953).

* The navbar is now automatically hidden with
  [headroom.js](https://wicky.nillia.ms/headroom.js/).

* The sticky behaviour of the navbar is now implemented in pure CSS instead of
  relying a the 3rd party javascript library (#1016, @bisaloo)

* Favicons are now automatically built from a package logo (#949).

### Linking

* Infix operators (e.g., `%in%` and `%*%`) are now linked to their
  documentation (#1082).

* Function names can now be included in headers without spurious auto-linking
  (#948).

* Links to external documentation now point to [rdrr.io](https://rdrr.io)
  (#998).

### Other

* News page recognises more version specifications (including the
  "(development version)" now used by usethis) (#980).

* Subdirectories are supported for assets (#939, @ijlyttle).

* A default 404 page (`404.html`) is built, unless a custom `.github/404.md`
  is provided (#947).

* `build_article()` now uses the raw vignette title as page `<title>`
  and `og:title` (@maelle, #1037).

* `build_home()` now looks for license files spelled either as LICENSE or
  LICENCE (#972).

* `build_home()` can find badges in paragraph coming after the comment
  `<!-- badges: start -->` (#670, @gaborcsardi, @maelle).

* `build_home()` will add a community section to the sidebar if there is either
  a code of  conduct (`.github/CODE_OF_CONDUCT.md`) or a contributing guide
  (`.github/CONTRIBUTING.md`) (#1044, @maelle).

* `build_reference()` gains a `topics` argument which allows you to re-build
  only specified topics.

* `build_site(new_process = TRUE)` gains a timeout,
  `options(pkgdown.timeout = 10)`, that can be used to prevent stalled
  builds.

* `deploy_site_github(install = FALSE)` makes it possible to opt out of
  installation.

* `dev_mode()` now recognises `0.1.9000` as a development version of a package
  (this is an emerging standard we use for packages with backward incompatible
  changes) (#1101).

# pkgdown 1.3.0

* Restore accidentally deleted `build_logo()` function so that logos
  are once more copied to the website.

* Fix to `pkgdown.css` so page header has correct amount of top margin.

* `content-home.html` template is no longer used when the homepage
  is an `.Rmd` (Reverts #834. Fixes #927, #929)

* `deploy_site_github()` now passes parameters to `build_site()`
  (@noamross, #922), and the documentation gives slightly better advice.

* Correct off-by-one error in navbar highlighting javascript; now no navbar
  is highlighted if none match the current path (#911).

* Tweaking of HTML table classes was fixed (@yonicd, #912)

* Restore accidentally removed `docsearch.css` file.

# pkgdown 1.2.0

## New features

* `deploy_site_github()` can be used from continuous integration systems
  (like travis) to automatically deploy your package website to GitHub Pages.
  See documentation for how to set up details (@jimhester).

* `build_favicon()` creates high resolution favicons from the package logo,
  and saves them in `pkgdown/`. They are created using the
  <https://realfavicongenerator.net/> API, and are better suited for modern web
  usage (e.g. retina display screens, desktop shortcuts, etc.). This also
  removes the dependency on the magick package, making automated deployment
  a little easier (@bisaloo, #883).

* Users with limited internet connectivity can explicitly disable internet
  usage by pkgdown by setting `options(pkgdown.internet = FALSE)` (#774, #877).

## Improvements to Rd translation

* `rd2html()` is now exported to facilitate creation of translation reprexes.

* `\Sexpr{}` conversion supports multiple arguments, eliminating
  `x must be a string or a R connection` errors when using `\doi{}` (#738).

* `\tabular{}` conversion better handles empty cells (#780).

* `\usage{}` now supports qualified functions eliminating
  `Error in fun_info(x) : Unknown call: ::` errors (#795).

* Invalid tags now generate more informative errors (@BarkleyBG, #771, #891)

## Front end

* The default footer now displays the version of pkgdown used to build
  the site (#876).

* All third party resources are now fetched from a single CDN and are
  give a SRI hash (@bisaloo, #893).

* The navbar version now has class "version" so you can more easily control
  its display (#680).

* The default css has been tweaked to ensure that icons are visible on all
  browsers (#852).

## Bug fixes and minor improvements

### Home page

* Can now build sites for older packages that don't have a `Authors@R` field
  (#727).

* Remote urls ending in `.md` are no longer tweaked to end in `.html` (#763).

* Bug report link is only shown if there's a "BugReports" field (#855).

* `content-home.html` template is now used when the homepage is an `.Rmd`
  (@goldingn, #787).

* A link to the source `inst/CITATION` was added to the authors page (#714).

### News

* Uses stricter regular expression when linking to GitHub authors (#902).

### Reference

* Unexported functions and test helpers are no longer loaded (#789).

* Selectors that do not match topics now generate a warning. If none of the
  specified selectors have a match, no topics are selected (#728).

### Articles

* The display depth of vignette tables of contents can be configured by
  setting `toc: depth` in `_pkgdown.yml` (#821):

  ```yaml
  toc:
    depth: 2
  ```

### Overall site

* `init_site()` now creates a CNAME file if one doesn't already exist and the
  site's metadata includes a `url` field.

* `build_site()` loses vestigal `mathjax` parameter. This didn't appear to do
  anything and  no one could remember why it existed (#785).

* `build_site()` now uses colours even if `new_process = TRUE` (@jimhester).

# pkgdown 1.1.0

## New features

* `build_reference()` and `build_site()` get new `document` argument. When
  `TRUE`, the default, will automatically run `devtools::document()` to
  ensure that your documentation is up to date.

* `build_site()` gains a `new_process` argument, which defaults to `TRUE`.
  This will run pkgdown in a separate process, and is recommended practice
  because it improves reproducibility (#647).

* Improved display for icons: icons must be 30px and stored in top-level
  `icons/` directory. They are embedded in a separate column of reference
  index table, instead of being inside a comment (!) (#607).

## Front end

* Added a keyboard shortcut for searching. Press `shift` + `/` (`?`) to move
  focus to the search bar (#642).

* The Algolia logo is correctly shown in the search results (#673).

* Navbar active tab highlighting uses a superior approach (suggested by
  @jcheng5) which should mean that the active page is correctly highlighted
  in all scenarios (#660).

* `pkgdown.js` is better isolated so it should still work even if you
  load html widgets that import a different version of jquery (#655).

## Improvements to Rd translation

* `vignette()` calls that don't link to existing vignettes silently fail
  to link instead of generating an uninformative error messages (#652).
  Automatic linking works for re-exported objects that are not functions
  (@gaborcsardi, #666).

* Empty `\section{}`s are ignored (#656). Previously, empty sections caused
  error `Error in rep(TRUE, length(x) - 1)`.

* `\Sexpr{}` supports `results=text`, `results=Rd` and `results=hide` (#651).

* `\tabular{}` no longer requires a terminal `\cr` (#664, #645).

## Minor bug fixes and improvements

* Add `inst/pkgdown.yml` as a possible site configuration file so that packages
  on CRAN can be built without needing the development version (#662).

* Default navbar template now uses site title, not package name (the package
  name is the default title, so this will not affect most sites) (#654).

* You can suppress indexing by search engines by setting `noindex: true`
  `pkgdown.yml` (#686)

    ```yaml
    template:
      params:
        noindex: true
    ```

* `build_article()` sets `IN_PKGDOWN` env var so `in_pkgdown()` works
  (#650).

* `build_home()`: CITATION files with non-UTF-8 encodings (latin1) work
  correctly, instead of generating an error. For non-UTF-8 locales, ensure you
  have e.g. `Encoding: latin1` in your `DESCRIPTION`; but best practice is to
  re-enode your CITATION file to UTF-8 (#689).

* `build_home()`: Markdown files (e.g., `CODE_OF_CONDUCT.md`) stored in
  `.github/` are copied and linked correctly (#682).

* `build_news()`: Multi-page changelogs (generated from `NEWS.md` with
  `news: one_page: false` in `_pkgdown.yml`) are rendered correctly.

* `build_reference()`: reference index shows infix functions (like `%+%`) as
  `` `%+%` ``, not `` `%+%`() `` on  (#659).

# pkgdown 1.0.0

* Major refactoring of path handling. `build_` functions no longer take
  `path` or `depth` arguments. Instead, set the `destination` directory
  at the top level of `pkgdown.yml`.

* Similarly, `build_news()` no longer takes a `one_page` argument;
  this should now be specified in the `_pkgdown.yml` instead. See the
  documentation for an example.


================================================
FILE: R/build-404.R
================================================
build_404 <- function(pkg = ".") {
  pkg <- as_pkgdown(pkg)

  # if this file exists, it will be handled by build_home_md()
  page_md <- path(pkg$src_path, ".github", "404.md")

  if (!file_exists(page_md)) {
    render_page(
      pkg,
      "title-body",
      data = list(
        pagetitle = tr_("Page not found (404)"),
        body = tr_("Content not found. Please use links in the navbar.")
      ),
      path = "404.html"
    )
    update_html(
      path_abs("404.html", start = pkg$dst_path),
      tweak_link_absolute,
      pkg = pkg
    )
  }

  invisible()
}


================================================
FILE: R/build-article.R
================================================
#' @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(
        '<img src="([^"]+)"',
        sprintf('<img src="\\1" class="%s"', options$fig.class),
        hook_output
      )
    }

    hook_output
  }

  width <- config_pluck_number_whole(pkg, "code.width", default = 80)
  old_pre <- format$pre_knit
  format$pre_knit <- function(...) {
    options(width = width)
    if (is.function(old_pre)) {
      old_pre(...)
    }
  }

  list(format = format, options = NULL)
}

# Generates pandoc template by rendering templates/content-article.html
rmarkdown_template <- function(
  pkg,
  data = list(),
  depth = 1L,
  env = caller_env()
) {
  path <- withr::local_tempfile(
    pattern = "pkgdown-rmd-template-",
    fileext = ".html",
    .local_envir = env
  )
  render_page(pkg, "article", data, path, depth = depth, quiet = TRUE)

  path
}

copy_article_images <- function(built_path, input_path, output_path) {
  ext_src <- rmarkdown::find_external_resources(input_path)

  # temporarily copy the rendered html into the input path directory and scan
  # again for additional external resources that may be been included by R code
  tempfile <- path(path_dir(input_path), "--find-assets.html")
  withr::defer(try(file_delete(tempfile)))
  file_copy(built_path, tempfile)
  ext_post <- rmarkdown::find_external_resources(tempfile)

  ext <- rbind(ext_src, ext_post)
  ext <- ext[!duplicated(ext$path), ]

  # copy web + explicit files beneath vignettes/
  is_child <- path_has_parent(ext$path, ".")
  ext_path <- ext$path[(ext$web | ext$explicit) & is_child]

  src <- path(path_dir(input_path), ext_path)
  dst <- path(path_dir(output_path), ext_path)
  # Make sure destination paths exist before copying files there
  dir_create(unique(path_dir(dst)))
  file_copy(src, dst, overwrite = TRUE)
}

wrap_rmarkdown_error <- function(cnd, input, call = caller_env()) {
  lines <- strsplit(gsub("^\r?\n", "", cnd$stderr), "\r?\n")[[1]]
  lines <- lines[nchar(lines) > 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(), ...)
}


================================================
FILE: R/build-articles.R
================================================
#' Build articles section
#'
#' @description
#' `build_articles()` renders each R Markdown file underneath `vignettes/` and
#' saves it to `articles/`. There are two exceptions:
#'
#' * Files that start with `_` (e.g., `_index.Rmd`) are ignored,
#'   enabling the use of child documents.
#'
#' * Files in `vignettes/tutorials` are handled by [build_tutorials()]
#'
#' Vignettes are rendered using a special document format that reconciles
#' [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 `build_articles()` directly (outside of
#' [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.
#'
#' # Index and navbar
#' You can control the articles index and navbar with a `articles` field in
#' your `_pkgdown.yml`. If you use it, pkgdown will check that all articles
#' are included, and will error if you have missed any.
#'
#' The `articles` field defines a list of sections, each of which
#' can contain four fields:
#'
#' * `title` (required): title of section, which appears as a heading on the
#'   articles index.
#'
#' * `desc` (optional): An optional markdown description displayed underneath
#'   the section title.
#'
#' * `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.
#'
#' * `contents` (required): a list of article names to include in the
#'   section. This can either be names of individual vignettes or a
#'   call to `starts_with()`. The name of a vignette includes its
#'   path under `vignettes` without extension so that the name of the vignette
#'   found at `vignettes/pizza/slice.Rmd` is `pizza/slice`.
#'
#' The title and description of individual vignettes displayed on the index
#' comes from `title` and `description` fields of the YAML header in the Rmds.
#'
#' For example, this yaml might be used for some version of dplyr:
#'
#' ```yaml
#' articles:
#' - title: Main verbs
#'   navbar: ~
#'   contents:
#'   - one-table
#'   - two-table
#'   - rowwise
#'   - colwise
#'
#' - title: Developer
#'   desc: Vignettes aimed at package developers
#'   contents:
#'   - programming
#'   - packages
#' ```
#'
#' Note the use of the `navbar` fields. `navbar: ~` means that the "Main verbs"
#' will appear in the navbar without a heading; the absence of the `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.
#'
#' ## Get started
#' Note that a vignette with the same name as the package (e.g.,
#' `vignettes/pkgdown.Rmd` or `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 `.`, e.g. `pack.down`, use a `-` in the
#' vignette name, e.g. `pack-down.Rmd`.)
#'
#' ## 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 `title: internal` (case sensitive);
#' this section will not be displayed on the index page.
#'
#' ## External articles
#'
#' You can link to arbitrary additional articles by adding an
#' `external-articles` entry to `_pkgdown.yml`. It should contain an array
#' of objects with fields `name`, `title`, `href`, and `description`.
#'
#' ```yaml
#' 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 you've defined a custom articles index, you'll need to include the name
#' in one of the `contents` fields.
#'
#' # 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 `.install_extras`. pkgdown takes a different approach based on
#' [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 `resource_files` field to the yaml metadata, e.g.:
#'
#' ```yaml
#' ---
#' title: My Document
#' resource_files:
#'   - data/mydata.csv
#'   - images/figure.png
#' ---
#' ```
#'
#' Note that you can not use the `fig.path` to change the output directory of
#' generated figures as its default value is a strong assumption of rmarkdown.
#'
#' # 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. <https://www.shinyapps.io>). Then, you
#' can embed the app into your article using an `<iframe>`, e.g.
#' `<iframe src = "https://gallery.shinyapps.io/083-front-page" class="shiny-app">`.
#'
#' See <https://github.com/r-lib/pkgdown/issues/838#issuecomment-430473856> for
#' some hints on how to customise the appearance with CSS.
#'
#' # Output formats
#' By default, pkgdown builds all articles using the
#' [rmarkdown::html_document()] `output` format, ignoring whatever is set in
#' your YAML metadata. This is necessary because pkgdown has to integrate the
#' HTML/CSS/JS from the vignette with the HTML/CSS/JS from rest of the site.
#' Because of the challenges of combining two sources of HTML/CSS/JS, there is
#' limited support for other output formats and you have to opt-in by setting
#' the `as_is` field in your `.Rmd` metadata:
#'
#' ```yaml
#' pkgdown:
#'   as_is: true
#' ```
#'
#' If the output format produces a PDF, you'll also need to specify the
#' `extension` field:
#'
#' ```yaml
#' pkgdown:
#'   as_is: true
#'   extension: pdf
#' ```
#'
#' To work with pkgdown, the output format must accept `template`, `theme`, and
#' `self_contained` arguments, and must work without any additional CSS or
#' JSS files. Note that if you use
#' [`_output.yml`](https://bookdown.org/yihui/rmarkdown/html-document.html#shared-options)
#' or [`_site.yml`](https://rmarkdown.rstudio.com/docs/reference/render_site.html)
#' you'll still need to add `as_is: true` to each individual vignette.
#'
#' Additionally, htmlwidgets do not work when `as_is: true`.
#'
#' # Suppressing vignettes
#' If you want [articles](https://r-pkgs.org/vignettes.html#sec-vignettes-article)
#' that are not vignettes, use `usethis::use_article()` to create it. An articles link will be
#' automatically added to the default navbar if the vignettes directory is
#' present: if you do not want this, you will need to customise the navbar. See
#' [build_site()] details.
#'
#' @inheritSection build_reference Figures
#' @family site components
#'
#' @inheritParams as_pkgdown
#' @param quiet Set to `FALSE` to display output of knitr and
#'   pandoc. This is useful when debugging.
#' @param lazy If `TRUE`, will only re-build article if input file has been
#'   modified more recently than the output file.
#' @param seed Seed used to initialize random number generation in order to
#'   make article output reproducible. An integer scalar or `NULL` for no seed.
#' @param preview If `TRUE`, or `is.na(preview) && interactive()`, will preview
#'   freshly generated section in browser.
#' @export
#' @order 1
build_articles <- function(
  pkg = ".",
  quiet = TRUE,
  lazy = TRUE,
  seed = 1014L,
  override = list(),
  preview = FALSE
) {
  pkg <- section_init(pkg, "articles", override = override)
  check_bool(quiet)
  check_bool(lazy)
  check_number_whole(seed, allow_null = TRUE)

  if (nrow(pkg$vignettes) == 0L) {
    return(invisible())
  }

  cli::cli_rule("Building articles")

  build_articles_index(pkg)
  unwrap_purrr_error(purrr::walk(
    pkg$vignettes$name[pkg$vignettes$type == "rmd"],
    build_article,
    pkg = pkg,
    lazy = lazy,
    seed = seed,
    quiet = quiet
  ))
  build_quarto_articles(pkg, quiet = quiet)

  preview_site(pkg, "articles", preview = preview)
}

# Articles index ----------------------------------------------------------

#' @export
#' @rdname build_articles
#' @order 3
build_articles_index <- function(pkg = ".", override = list()) {
  pkg <- section_init(pkg, "articles", override = override)
  render_page(
    pkg,
    "article-index",
    data = data_articles_index(pkg),
    path = path("articles", "index.html")
  )
  invisible()
}

data_articles_index <- function(pkg = ".", call = caller_env()) {
  pkg <- as_pkgdown(pkg)

  articles <- data_articles(pkg, is_index = TRUE, call = call)
  index <- config_pluck_list(pkg, "articles", call = call) %||%
    default_articles_index(pkg)
  sections <- unwrap_purrr_error(purrr::imap(
    index,
    data_articles_index_section,
    articles = articles,
    pkg = pkg,
    call = call
  ))

  # Check for unlisted vignettes
  all_names <- purrr::map(sections, function(section) {
    purrr::map_chr(section$contents, "name")
  })
  listed <- unique(purrr::list_c(all_names))

  missing <- setdiff(articles$name, listed)
  # Exclude get started vignette or article #2150
  missing <- missing[!article_is_intro(missing, package = pkg$package)]

  if (length(missing) > 0) {
    config_abort(
      pkg,
      "{length(missing)} vignette{?s} missing from index: {.val {missing}}.",
      call = caller_env()
    )
  }

  # Remove internal section after missing vignettes check
  sections <- Filter(function(x) x$title != "internal", sections)

  print_yaml(list(
    pagetitle = tr_("Articles"),
    sections = sections
  ))
}

data_articles <- function(pkg = ".", is_index = FALSE, call = caller_env()) {
  pkg <- as_pkgdown(pkg)

  internal <- tibble::tibble(
    name = pkg$vignettes$name,
    title = pkg$vignettes$title,
    href = pkg$vignettes$file_out,
    description = pkg$vignettes$description,
  )
  if (is_index) {
    internal$href <- path_rel(internal$href, "articles")
  }

  external <- config_pluck_external_articles(pkg, call = call)
  articles <- rbind(internal, external)

  articles$description <- lapply(
    articles$description,
    markdown_text_block,
    pkg = pkg
  )

  # Hack data structure so we can use select_topics()
  articles$alias <- as.list(articles$name)
  articles$internal <- FALSE

  articles
}

config_pluck_external_articles <- function(pkg, call = caller_env()) {
  external <- config_pluck_list(pkg, "external-articles", call = call)
  if (is.null(external)) {
    return(tibble::tibble(
      name = character(),
      title = character(),
      href = character(),
      description = character()
    ))
  }

  for (i in seq_along(external)) {
    config_check_list(
      external[[i]],
      has_names = c("name", "title", "href", "description"),
      error_path = paste0("external-articles[", i, "]"),
      error_pkg = pkg,
      error_call = call
    )
    config_check_string(
      external[[i]]$name,
      error_path = paste0("external-articles[", i, "].name"),
      error_pkg = pkg,
      error_call = call
    )
    config_check_string(
      external[[i]]$title,
      error_path = paste0("external-articles[", i, "].title"),
      error_pkg = pkg,
      error_call = call
    )
    config_check_string(
      external[[i]]$href,
      error_path = paste0("external-articles[", i, "].href"),
      error_pkg = pkg,
      error_call = call
    )
    config_check_string(
      external[[i]]$description,
      error_path = paste0("external-articles[", i, "].description"),
      error_pkg = pkg,
      error_call = call
    )
  }

  tibble::tibble(
    name = purrr::map_chr(external, "name"),
    title = purrr::map_chr(external, "title"),
    href = purrr::map_chr(external, "href"),
    description = purrr::map_chr(external, "description")
  )
}

data_articles_index_section <- function(
  section,
  index,
  articles,
  pkg,
  call = caller_env()
) {
  config_check_list(
    section,
    error_path = paste0("articles[", index, "]"),
    has_names = c("title", "contents"),
    error_pkg = pkg,
    error_call = call
  )
  config_check_string(
    section$title,
    error_path = paste0("articles[", index, "].title"),
    error_pkg = pkg,
    error_call = call
  )
  title <- markdown_text_inline(
    pkg,
    section$title,
    error_path = paste0("articles[", index, "].title"),
    error_call = call
  )

  config_check_string(
    section$desc,
    error_path = paste0("articles[", index, "].desc"),
    error_pkg = pkg,
    error_call = call
  )
  check_contents(
    section$contents,
    index,
    pkg,
    prefix = "articles",
    call = call
  )

  # Match topics against any aliases
  idx <- select_topics(
    section$contents,
    articles,
    error_path = paste0("articles[", index, "].contents"),
    error_pkg = pkg,
    error_call = call
  )
  contents <- articles[idx, , drop = FALSE]

  list(
    title = title,
    desc = markdown_text_block(pkg, section$desc),
    class = section$class,
    contents = purrr::transpose(contents)
  )
}

default_articles_index <- function(pkg = ".") {
  pkg <- as_pkgdown(pkg)

  if (nrow(pkg$vignettes) == 0L) {
    return(NULL)
  }

  print_yaml(list(
    list(
      title = tr_("All vignettes"),
      desc = NULL,
      contents = auto_quote(unname(pkg$vignettes$name))
    )
  ))
}

article_is_intro <- function(name, package) {
  package <- gsub(".", "-", package, fixed = TRUE)
  name %in% c(package, paste0("articles/", package))
}


================================================
FILE: R/build-favicons.R
================================================
#' 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 <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
#' `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")
}


================================================
FILE: R/build-footer.R
================================================
data_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 <a href="%s">pkgdown</a> %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"
  ))
}


================================================
FILE: R/build-github.R
================================================
#' 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
}


================================================
FILE: R/build-home-authors.R
================================================
build_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,
    "<br />\n<small class = 'roles'>",
    x$roles,
    "</small>",
    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("<br/>\n<small>(", linkify(x$comment), ")</small>")
    }
  )
}

orcid_link <- function(orcid) {
  if (is.null(orcid)) {
    return(NULL)
  }

  paste0(
    "<a href='https://orcid.org/",
    orcid,
    "' target='orcid.widget' aria-label='ORCID'>",
    "<span class='fab fa-orcid orcid' aria-hidden='true'></span></a>"
  )
}

ror_link <- function(ror) {
  if (is.null(ror)) {
    return(NULL)
  }

  paste0(
    "<a href='https://ror.org/",
    ror,
    "'>",
    "<img src='https://raw.githubusercontent.com/ror-community/ror-logos/main/ror-icon-rgb.svg' class='ror' alt='ROR'></a>"
  )
}

# 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("<p>", escape_html(text_version), "</p>")
    ),
    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
}


================================================
FILE: R/build-home-community.R
================================================
has_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)
}


================================================
FILE: R/build-home-index.R
================================================
#' @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"),
    '<nav id="toc"></nav>'
  )
}

sidebar_section <- function(heading, bullets, class = make_slug(heading)) {
  if (length(bullets) == 0) {
    return(character())
  }

  paste0(
    "<div class='",
    class,
    "'>\n",
    "<h2 data-toc-skip>",
    heading,
    "</h2>\n",
    "<ul class='list-unstyled'>\n",
    paste0("<li>", bullets, "</li>\n", collapse = ""),
    "</ul>\n",
    "</div>\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)
}


================================================
FILE: R/build-home-license.R
================================================
# 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("<pre>", escape_html(read_file(license_raw)), "</pre>")
      ),
      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("<small>", link, "</small>")
    )
  }

  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("<a href='", url, "'>", abbr, "</a>")

  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
}


================================================
FILE: R/build-home-md.R
================================================
build_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()
}


================================================
FILE: R/build-home.R
================================================
#' Build home section
#'
#' @description
#' `build_home()` function generates pages at the top-level of the site
#' including:
#'
#' * The home page
#' * HTML files from any `.md` files in `./` or `.github/`.
#' * The authors page (from `DESCRIPTION`)
#' * The citation page (from `inst/CITATION`, if present).
#' * The license page
#' * A default 404 page if `.github/404.md` is not found.
#'
#' `build_home_index()` rebuilds just the index page; it's useful for rapidly
#' iterating when experimenting with site styles.
#'
#' # Home page
#'
#' The main content of the home page (`index.html`) is generated from
#' `pkgdown/index.md`, `index.md`, or `README.md`, in that order.
#' Most packages will use `README.md` because that's also displayed by GitHub
#' and CRAN. Use `index.md` if you want your package website to look
#' different to your README, and use `pkgdown/index.md` if you don't want that
#' file to live in your package root directory.
#'
#' If you use `index.Rmd` or `README.Rmd` it's your responsibility to knit
#' the document to create the corresponding `.md`. pkgdown does not do this
#' for you because it only touches files in the `doc/` directory.
#'
#' Extra markdown files in the base directory (e.g. `ROADMAP.md`) or in
#' `.github/` (e.g. `CODE_OF_CONDUCT.md`) are copied by `build_home()` to `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.
#'
#' ## Images and figures
#'
#' If you want to include images in your `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 `man/figures`. If you are generating figures
#' with R Markdown, make sure you set up `fig.path` as followed:
#'
#' ``` r
#' knitr::opts_chunk$set(
#'   fig.path = "man/figures/"
#' )
#' ```
#'
#' This should usually go in a chunk with `include = FALSE`.
#'
#' ```` markdown
#' ```{r chunk-name, include=FALSE}`r ''`
#' knitr::opts_chunk$set(
#'   fig.path = "man/figures/"
#' )
#' ```
#' ````
#'
#' ## Package logo
#'
#' If you have a package logo, you can include it at the top of your README
#' in a level-one heading:
#'
#' ``` markdown
#' # pkgdown <img src="man/figures/logo.png" align="right" />
#' ```
#'
#' [init_site()] will also automatically create a favicon set from your package logo.
#'
#' ## YAML config - title and description
#'
#' By default, the page title and description are extracted automatically from
#' the `Title` and `Description` fields `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 `title` and
#' `description`, thinking about what people might search for:
#'
#' ```yaml
#' 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.
#' ```
#'
#' (Note the use of YAML's `>` i.e. "YAML pipes"; this is a convenient way of
#' writing paragraphs of text.)
#'
#' ## Dev badges
#'
#' pkgdown identifies badges in three ways:
#'
#' -   Any image-containing links between `<!-- badges: start -->` and
#'     `<!-- badges: end -->`, as e.g. created by `usethis::use_readme_md()`
#'     or `usethis::use_readme_rmd()`. There should always be an empty line after
#'     the `<!-- badges: end -->` line. If you divide badges into paragraphs,
#'     make sure to add an empty line before the `<!-- badges: end -->` line.
#'
#' -   Any image-containing links within `<div id="badges"></div>`.
#'
#' -   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: "<img src='https://website.com/name-picture.png' width=72 alt=''>"
#' ```
#'
#'
#' 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)
}


================================================
FILE: R/build-llm-dl.R
================================================
simplify_dls <- function(html) {
  dls <- xml2::xml_find_all(html, ".//dl")
  for (dl in dls) {
    simplify_dl(dl)
  }
  invisible()
}

simplify_dl <- function(dl) {
  children <- xml2::xml_children(dl)

  names <- xml2::xml_name(children)
  if (!is_simple_dl(names)) {
    cli::cli_warn("Skipping this <dl>: not a simple term-definition list")
    return()
  }

  groups <- split(children, (seq_along(children) - 1) %/% 2)

  bullets <- lapply(groups, create_li_from_group)
  ul <- xml2::read_xml("<ul></ul>")
  xml_insert(ul, bullets)

  xml2::xml_replace(dl, ul)
}

# Must have an even number of children that alternate between dt and dd
is_simple_dl <- function(names) {
  if (length(names) %% 2 != 0) {
    return(FALSE)
  }
  odd <- names[seq_along(names) %% 2 == 1]
  even <- names[seq_along(names) %% 2 == 0]

  all(odd == "dt") && all(even == "dd")
}

create_li_from_group <- function(group) {
  dt <- group[[1]]
  dd <- group[[2]]

  if (has_children(dd)) {
    # params case
    para <- xml2::read_xml("<p></p>")
    xml_insert(para, xml2::xml_contents(dt))
    xml2::xml_add_child(para, xml_text_node(": "))

    bullet <- xml2::read_xml("<li></li>")
    xml2::xml_add_child(bullet, para)
  } else {
    # reference index
    bullet <- xml2::read_xml("<li></li>")
    xml_insert(bullet, xml2::xml_contents(dt))
    xml2::xml_add_child(bullet, xml_text_node(": "))
  }
  xml_insert(bullet, xml2::xml_contents(dd))

  bullet
}

has_children <- function(x) length(xml2::xml_children(x)) > 0

xml_text_node <- function(x) {
  span <- xml2::read_xml(paste0("<span>", x, "</span>"))
  xml2::xml_find_first(span, ".//text()")
}


================================================
FILE: R/build-llm.R
================================================
#' 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)

  if (rmarkdown::pandoc_available("2.10.1")) {
    to <- "gfm+definition_lists-raw_html"
  } else {
    to <- "gfm-raw_html"
  }

  rmarkdown::pandoc_convert(
    input = path,
    output = dst_path,
    from = "html",
    to = to,
  )
}

# 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)
  }
}


================================================
FILE: R/build-logo.R
================================================
copy_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))
}


================================================
FILE: R/build-news.R
================================================
#' 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 <h1> or all <h2>.",
      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 <h1> 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
    (?<version>
      (?:\\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(" <small>", date, "</small>")
        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("<p class='text-muted'>", release_date, "</p>")
        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"
}


================================================
FILE: R/build-quarto-articles.R
================================================
build_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)
  }
}


================================================
FILE: R/build-redirects.R
================================================
#' 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
}


================================================
FILE: R/build-reference-index.R
================================================
data_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
    )
  }
}


================================================
FILE: R/build-reference.R
================================================
#' 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 `<h2>`
#'   with optional paragraph description.
#' * A **subtitle** (`subtitle` + `desc`), which generates an row containing an
#'   `<h3>` 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_pat
Download .txt
gitextract_6_cfe080/

├── .Rbuildignore
├── .git-blame-ignore-revs
├── .gitattributes
├── .github/
│   ├── .gitignore
│   ├── 404.md
│   ├── CODEOWNERS
│   ├── CODE_OF_CONDUCT.md
│   ├── CONTRIBUTING.md
│   └── workflows/
│       ├── R-CMD-check.yaml
│       ├── lint.yaml
│       ├── netlify.yaml
│       ├── no-pandoc.yaml
│       ├── pkgdown.yaml
│       ├── pr-commands.yaml
│       ├── site-languages.yml
│       └── test-coverage.yaml
├── .gitignore
├── .lintr.R
├── .vscode/
│   ├── extensions.json
│   └── settings.json
├── DESCRIPTION
├── LICENSE
├── LICENSE.md
├── NAMESPACE
├── NEWS.md
├── R/
│   ├── build-404.R
│   ├── build-article.R
│   ├── build-articles.R
│   ├── build-favicons.R
│   ├── build-footer.R
│   ├── build-github.R
│   ├── build-home-authors.R
│   ├── build-home-community.R
│   ├── build-home-index.R
│   ├── build-home-license.R
│   ├── build-home-md.R
│   ├── build-home.R
│   ├── build-llm-dl.R
│   ├── build-llm.R
│   ├── build-logo.R
│   ├── build-news.R
│   ├── build-quarto-articles.R
│   ├── build-redirects.R
│   ├── build-reference-index.R
│   ├── build-reference.R
│   ├── build-search-docs.R
│   ├── build-tutorials.R
│   ├── build.R
│   ├── check-built.R
│   ├── check.R
│   ├── clean.R
│   ├── config.R
│   ├── context.R
│   ├── deploy-site.R
│   ├── development.R
│   ├── external-deps.R
│   ├── figure.R
│   ├── highlight.R
│   ├── html-build.R
│   ├── import-standalone-obj-type.R
│   ├── import-standalone-types-check.R
│   ├── init.R
│   ├── markdown.R
│   ├── navbar-menu.R
│   ├── navbar.R
│   ├── package.R
│   ├── pkgdown-package.R
│   ├── pkgdown.R
│   ├── pkgdown_print.R
│   ├── preview.R
│   ├── rd-data.R
│   ├── rd-example.R
│   ├── rd-html.R
│   ├── rd.R
│   ├── render.R
│   ├── repo.R
│   ├── template.R
│   ├── templates.R
│   ├── test.R
│   ├── theme.R
│   ├── topics-external.R
│   ├── topics.R
│   ├── tweak-homepage.R
│   ├── tweak-navbar.R
│   ├── tweak-page.R
│   ├── tweak-reference.R
│   ├── tweak-tabset.R
│   ├── tweak-tags.R
│   ├── tweak.R
│   ├── usage.R
│   ├── utils-fs.R
│   ├── utils-io.R
│   ├── utils-pdf.R
│   └── utils.R
├── README.Rmd
├── README.md
├── air.toml
├── codecov.yml
├── cran-comments.md
├── inst/
│   ├── BS3/
│   │   ├── assets/
│   │   │   ├── bootstrap-toc.css
│   │   │   ├── bootstrap-toc.js
│   │   │   ├── docsearch.css
│   │   │   ├── docsearch.js
│   │   │   ├── pkgdown.css
│   │   │   └── pkgdown.js
│   │   └── templates/
│   │       ├── after-body.html
│   │       ├── before-body.html
│   │       ├── config-docsearch.json
│   │       ├── content-article-index.html
│   │       ├── content-article.html
│   │       ├── content-citation-authors.html
│   │       ├── content-home.html
│   │       ├── content-news-index.html
│   │       ├── content-news.html
│   │       ├── content-reference-index.html
│   │       ├── content-reference-topic.html
│   │       ├── content-title-body.html
│   │       ├── content-tutorial-index.html
│   │       ├── content-tutorial.html
│   │       ├── docsearch.html
│   │       ├── footer.html
│   │       ├── head.html
│   │       ├── header.html
│   │       ├── in-header.html
│   │       ├── layout-redirect.html
│   │       ├── layout.html
│   │       └── navbar.html
│   ├── BS5/
│   │   ├── assets/
│   │   │   ├── katex-auto.js
│   │   │   ├── lightswitch.js
│   │   │   ├── pkgdown.js
│   │   │   └── pkgdown.scss
│   │   └── templates/
│   │       ├── after-body.html
│   │       ├── before-body.html
│   │       ├── config-docsearch.json
│   │       ├── content-article-index.html
│   │       ├── content-article.html
│   │       ├── content-authors.html
│   │       ├── content-citation-authors.html
│   │       ├── content-home.html
│   │       ├── content-news-index.html
│   │       ├── content-news.html
│   │       ├── content-quarto.html
│   │       ├── content-reference-index.html
│   │       ├── content-reference-topic.html
│   │       ├── content-title-body.html
│   │       ├── content-tutorial-index.html
│   │       ├── content-tutorial.html
│   │       ├── footer.html
│   │       ├── head.html
│   │       ├── header.html
│   │       ├── in-header.html
│   │       ├── layout-redirect.html
│   │       ├── layout.html
│   │       └── navbar.html
│   ├── highlight-styles/
│   │   ├── a11y-dark.scss
│   │   ├── a11y-light.scss
│   │   ├── arrow-dark.scss
│   │   ├── arrow-light.scss
│   │   ├── atom-one-dark.scss
│   │   ├── atom-one-light.scss
│   │   ├── ayu-dark.scss
│   │   ├── ayu-light.scss
│   │   ├── ayu-mirage.scss
│   │   ├── breeze-dark.scss
│   │   ├── breeze-light.scss
│   │   ├── breezedark.scss
│   │   ├── dracula.scss
│   │   ├── espresso.scss
│   │   ├── github-dark.scss
│   │   ├── github-light.scss
│   │   ├── gruvbox-dark.scss
│   │   ├── gruvbox-light.scss
│   │   ├── haddock.scss
│   │   ├── kate.scss
│   │   ├── monochrome-dark.scss
│   │   ├── monochrome-light.scss
│   │   ├── monochrome.scss
│   │   ├── monokai.scss
│   │   ├── nord.scss
│   │   ├── oblivion.scss
│   │   ├── printing.scss
│   │   ├── pygments.scss
│   │   ├── radical.scss
│   │   ├── solarized-dark.scss
│   │   ├── solarized-light.scss
│   │   ├── solarized.scss
│   │   ├── tango.scss
│   │   ├── vim-dark.scss
│   │   └── zenburn.scss
│   ├── po/
│   │   ├── ca/
│   │   │   └── LC_MESSAGES/
│   │   │       └── R-pkgdown.mo
│   │   ├── de/
│   │   │   └── LC_MESSAGES/
│   │   │       └── R-pkgdown.mo
│   │   ├── dk/
│   │   │   └── LC_MESSAGES/
│   │   │       └── R-pkgdown.mo
│   │   ├── es/
│   │   │   └── LC_MESSAGES/
│   │   │       └── R-pkgdown.mo
│   │   ├── fr/
│   │   │   └── LC_MESSAGES/
│   │   │       └── R-pkgdown.mo
│   │   ├── ja/
│   │   │   └── LC_MESSAGES/
│   │   │       └── R-pkgdown.mo
│   │   ├── ko/
│   │   │   └── LC_MESSAGES/
│   │   │       └── R-pkgdown.mo
│   │   ├── kr/
│   │   │   └── LC_MESSAGES/
│   │   │       └── R-pkgdown.mo
│   │   ├── nl/
│   │   │   └── LC_MESSAGES/
│   │   │       └── R-pkgdown.mo
│   │   ├── pt/
│   │   │   └── LC_MESSAGES/
│   │   │       └── R-pkgdown.mo
│   │   ├── tr/
│   │   │   └── LC_MESSAGES/
│   │   │       └── R-pkgdown.mo
│   │   └── zh_CN/
│   │       └── LC_MESSAGES/
│   │           └── R-pkgdown.mo
│   ├── quarto/
│   │   └── template.html
│   └── rstudio/
│       └── addins.dcf
├── man/
│   ├── as_pkgdown.Rd
│   ├── build_articles.Rd
│   ├── build_favicons.Rd
│   ├── build_home.Rd
│   ├── build_llm_docs.Rd
│   ├── build_news.Rd
│   ├── build_redirects.Rd
│   ├── build_reference.Rd
│   ├── build_search.Rd
│   ├── build_site.Rd
│   ├── build_site_github_pages.Rd
│   ├── build_tutorials.Rd
│   ├── check_pkgdown.Rd
│   ├── clean.Rd
│   ├── deploy_site_github.Rd
│   ├── deploy_to_branch.Rd
│   ├── fig_settings.Rd
│   ├── in_pkgdown.Rd
│   ├── index.Rd
│   ├── init_site.Rd
│   ├── pkgdown-package.Rd
│   ├── pkgdown_print.Rd
│   ├── preview_site.Rd
│   ├── rd2html.Rd
│   ├── render_page.Rd
│   ├── stop_preview.Rd
│   ├── templates.Rd
│   ├── test-crayon.Rd
│   ├── test-dont.Rd
│   ├── test-figures.Rd
│   ├── test-links.Rd
│   ├── test-lists.Rd
│   ├── test-long-lines.Rd
│   ├── test-math-examples.Rd
│   ├── test-output-styles.Rd
│   ├── test-params.Rd
│   ├── test-sexpr-title.Rd
│   ├── test-tables.Rd
│   └── test-verbatim.Rd
├── pkgdown/
│   ├── _pkgdown.yml
│   └── favicon/
│       └── site.webmanifest
├── pkgdown.Rproj
├── po/
│   ├── R-ca.po
│   ├── R-de.po
│   ├── R-dk.po
│   ├── R-es.po
│   ├── R-fr.po
│   ├── R-ja.po
│   ├── R-ko.po
│   ├── R-nl.po
│   ├── R-pkgdown.pot
│   ├── R-pt.po
│   ├── R-tr.po
│   └── R-zh_CN.po
├── revdep/
│   ├── .gitignore
│   ├── README.md
│   ├── cran.md
│   ├── email.yml
│   ├── failures.md
│   └── problems.md
├── tests/
│   ├── testthat/
│   │   ├── .gitignore
│   │   ├── _snaps/
│   │   │   ├── build-article.md
│   │   │   ├── build-articles.md
│   │   │   ├── build-favicons.md
│   │   │   ├── build-footer.md
│   │   │   ├── build-github.md
│   │   │   ├── build-home-authors.md
│   │   │   ├── build-home-community.md
│   │   │   ├── build-home-index.md
│   │   │   ├── build-llm-dl.md
│   │   │   ├── build-llm.md
│   │   │   ├── build-news.md
│   │   │   ├── build-quarto-articles.md
│   │   │   ├── build-redirects.md
│   │   │   ├── build-reference-index.md
│   │   │   ├── build-reference.md
│   │   │   ├── build-search-docs.md
│   │   │   ├── check-built.md
│   │   │   ├── check.md
│   │   │   ├── config.md
│   │   │   ├── development.md
│   │   │   ├── external-deps.md
│   │   │   ├── highlight.md
│   │   │   ├── init.md
│   │   │   ├── markdown.md
│   │   │   ├── navbar-menu.md
│   │   │   ├── navbar.md
│   │   │   ├── not-in-rcmcheck/
│   │   │   │   └── build-article.md
│   │   │   ├── package.md
│   │   │   ├── preview.md
│   │   │   ├── rcmdcheck/
│   │   │   │   └── build-article.md
│   │   │   ├── rd-example.md
│   │   │   ├── rd-html.md
│   │   │   ├── render.md
│   │   │   ├── repo.md
│   │   │   ├── templates.md
│   │   │   ├── theme.md
│   │   │   ├── topics-external.md
│   │   │   ├── topics.md
│   │   │   ├── tweak-homepage.md
│   │   │   ├── tweak-tabset.md
│   │   │   ├── tweak-tags.md
│   │   │   ├── usage.md
│   │   │   └── utils-fs.md
│   │   ├── assets/
│   │   │   ├── -find-assets.html
│   │   │   ├── articles-images/
│   │   │   │   ├── .gitignore
│   │   │   │   ├── DESCRIPTION
│   │   │   │   ├── README.md
│   │   │   │   ├── _pkgdown.yml
│   │   │   │   ├── man/
│   │   │   │   │   └── kitten.Rd
│   │   │   │   ├── man-figures.Rproj
│   │   │   │   └── vignettes/
│   │   │   │       ├── .gitignore
│   │   │   │       └── kitten.Rmd
│   │   │   ├── figure/
│   │   │   │   ├── DESCRIPTION
│   │   │   │   ├── _pkgdown.yml
│   │   │   │   ├── man/
│   │   │   │   │   └── figure.Rd
│   │   │   │   └── vignettes/
│   │   │   │       └── figures.Rmd
│   │   │   ├── llm.html
│   │   │   ├── reference/
│   │   │   │   ├── DESCRIPTION
│   │   │   │   ├── NAMESPACE
│   │   │   │   ├── R/
│   │   │   │   │   └── funs.R
│   │   │   │   ├── _pkgdown.yml
│   │   │   │   └── man/
│   │   │   │       ├── a.Rd
│   │   │   │       ├── b.Rd
│   │   │   │       ├── c.Rd
│   │   │   │       ├── e.Rd
│   │   │   │       ├── f.Rd
│   │   │   │       ├── g.Rd
│   │   │   │       └── help.Rd
│   │   │   ├── reference-fail/
│   │   │   │   ├── DESCRIPTION
│   │   │   │   ├── NAMESPACE
│   │   │   │   ├── R/
│   │   │   │   │   └── f.R
│   │   │   │   └── man/
│   │   │   │       └── f.Rd
│   │   │   ├── reference-html-dep/
│   │   │   │   ├── DESCRIPTION
│   │   │   │   ├── NAMESPACE
│   │   │   │   ├── R/
│   │   │   │   │   └── funs.R
│   │   │   │   ├── _pkgdown.yml
│   │   │   │   └── man/
│   │   │   │       └── a.Rd
│   │   │   ├── reference-language/
│   │   │   │   ├── one/
│   │   │   │   │   └── DESCRIPTION
│   │   │   │   └── two/
│   │   │   │       └── DESCRIPTION
│   │   │   ├── reference-pre-post/
│   │   │   │   ├── DESCRIPTION
│   │   │   │   └── pkgdown/
│   │   │   │       ├── post-reference.R
│   │   │   │       └── pre-reference.R
│   │   │   ├── reference-selector/
│   │   │   │   ├── DESCRIPTION
│   │   │   │   ├── NAMESPACE
│   │   │   │   ├── NEWS.md
│   │   │   │   ├── R/
│   │   │   │   │   └── funs.R
│   │   │   │   ├── _pkgdown.yml
│   │   │   │   └── man/
│   │   │   │       ├── A.Rd
│   │   │   │       └── matches.Rd
│   │   │   ├── sitemaps-schema-0.9.xsd
│   │   │   └── templates-local/
│   │   │       ├── DESCRIPTION
│   │   │       └── pkgdown/
│   │   │           └── templates/
│   │   │               ├── content-article.html
│   │   │               └── footer-article.html
│   │   ├── helper.R
│   │   ├── test-build-article.R
│   │   ├── test-build-articles.R
│   │   ├── test-build-favicons.R
│   │   ├── test-build-footer.R
│   │   ├── test-build-github.R
│   │   ├── test-build-home-authors.R
│   │   ├── test-build-home-community.R
│   │   ├── test-build-home-index.R
│   │   ├── test-build-home-license.R
│   │   ├── test-build-home-md.R
│   │   ├── test-build-home.R
│   │   ├── test-build-llm-dl.R
│   │   ├── test-build-llm.R
│   │   ├── test-build-logo.R
│   │   ├── test-build-news.R
│   │   ├── test-build-quarto-articles.R
│   │   ├── test-build-redirects.R
│   │   ├── test-build-reference-index.R
│   │   ├── test-build-reference.R
│   │   ├── test-build-search-docs.R
│   │   ├── test-build-tutorials.R
│   │   ├── test-build.R
│   │   ├── test-check-built.R
│   │   ├── test-check.R
│   │   ├── test-config.R
│   │   ├── test-deploy-site.R
│   │   ├── test-development.R
│   │   ├── test-external-deps.R
│   │   ├── test-figure.R
│   │   ├── test-highlight.R
│   │   ├── test-html-build.R
│   │   ├── test-init.R
│   │   ├── test-markdown.R
│   │   ├── test-navbar-menu.R
│   │   ├── test-navbar.R
│   │   ├── test-package.R
│   │   ├── test-pkgdown_print.R
│   │   ├── test-preview.R
│   │   ├── test-rd-data.R
│   │   ├── test-rd-example.R
│   │   ├── test-rd-html.R
│   │   ├── test-render.R
│   │   ├── test-repo.R
│   │   ├── test-templates.R
│   │   ├── test-theme.R
│   │   ├── test-topics-external.R
│   │   ├── test-topics.R
│   │   ├── test-tweak-homepage.R
│   │   ├── test-tweak-navbar.R
│   │   ├── test-tweak-page.R
│   │   ├── test-tweak-reference.R
│   │   ├── test-tweak-tabset.R
│   │   ├── test-tweak-tags.R
│   │   ├── test-usage.R
│   │   ├── test-utils-fs.R
│   │   └── test-utils.R
│   └── testthat.R
├── tools/
│   └── syntax-highlight.R
└── vignettes/
    ├── .gitignore
    ├── accessibility.Rmd
    ├── articles/
    │   ├── .gitignore
    │   ├── test-quarto-article.qmd
    │   └── test-rmarkdown-article.Rmd
    ├── customise.Rmd
    ├── how-to-update-released-site.Rmd
    ├── linking.Rmd
    ├── metadata.Rmd
    ├── pkgdown.Rmd
    ├── quarto.qmd
    ├── test/
    │   ├── jss.Rmd
    │   ├── jss.bib
    │   ├── jss.bst
    │   ├── jss.cls
    │   ├── long-toc.Rmd
    │   ├── pdf.Rmd
    │   ├── quarto-features.qmd
    │   ├── rendering.Rmd
    │   ├── short.Rmd
    │   ├── test.txt
    │   └── widgets.Rmd
    └── translations.Rmd
Download .txt
SYMBOL INDEX (8 symbols across 4 files)

FILE: inst/BS3/assets/docsearch.js
  function matchedWords (line 54) | function matchedWords(hit) {
  function updateHitURL (line 73) | function updateHitURL(hit) {

FILE: inst/BS3/assets/pkgdown.js
  function paths (line 42) | function paths(pathname) {
  function prefix_length (line 53) | function prefix_length(needle, haystack) {
  function changeTooltipMessage (line 72) | function changeTooltipMessage(element, msg) {

FILE: inst/BS5/assets/lightswitch.js
  function bsSetupThemeToggle (line 29) | function bsSetupThemeToggle() {

FILE: inst/BS5/assets/pkgdown.js
  function changeTooltipMessage (line 32) | function changeTooltipMessage(element, msg) {
  function searchFuse (line 116) | async function searchFuse(query, callback) {
Condensed preview — 439 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,318K chars).
[
  {
    "path": ".Rbuildignore",
    "chars": 500,
    "preview": "^.*\\.Rproj$\n^\\.Rproj\\.user$\n^\\.travis\\.yml$\n^inst/web$\n^docs$\n^_pkgdown\\.yml$\n^README\\.Rmd$\n^README-.*\\.png$\n^pkgdown$\n^"
  },
  {
    "path": ".git-blame-ignore-revs",
    "chars": 338,
    "preview": "# This file lists revisions of large-scale formatting/style changes so that\n# they can be excluded from git blame result"
  },
  {
    "path": ".gitattributes",
    "chars": 32,
    "preview": "docs/* linguist-generated=false\n"
  },
  {
    "path": ".github/.gitignore",
    "chars": 7,
    "preview": "*.html\n"
  },
  {
    "path": ".github/404.md",
    "chars": 68,
    "preview": "# Page not found (404)\n\nPlease use the links in the navigation bar.\n"
  },
  {
    "path": ".github/CODEOWNERS",
    "chars": 121,
    "preview": "# CODEOWNERS for pkgdown\n# https://www.tidyverse.org/development/understudies\n.github/CODEOWNERS @hadley @jayhesselberth"
  },
  {
    "path": ".github/CODE_OF_CONDUCT.md",
    "chars": 5244,
    "preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participa"
  },
  {
    "path": ".github/CONTRIBUTING.md",
    "chars": 4101,
    "preview": "# Contributing to pkgdown\n\nThis document outlines how to propose a change to pkgdown. For more detailed\ninfo about contr"
  },
  {
    "path": ".github/workflows/R-CMD-check.yaml",
    "chars": 1968,
    "preview": "# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples\n# Need help debugging build failures? Start at"
  },
  {
    "path": ".github/workflows/lint.yaml",
    "chars": 851,
    "preview": "# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples\n# Need help debugging build failures? Start at"
  },
  {
    "path": ".github/workflows/netlify.yaml",
    "chars": 1577,
    "preview": "on:\n  pull_request:\n    branches: [main, master]\n\nname: pkgdown-pr\n\njobs:\n  netlify:\n    runs-on: ubuntu-latest\n    env:"
  },
  {
    "path": ".github/workflows/no-pandoc.yaml",
    "chars": 939,
    "preview": "# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples\n# Need help debugging build failures? Start at"
  },
  {
    "path": ".github/workflows/pkgdown.yaml",
    "chars": 1346,
    "preview": "# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples\n# Need help debugging build failures? Start at"
  },
  {
    "path": ".github/workflows/pr-commands.yaml",
    "chars": 2501,
    "preview": "# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples\n# Need help debugging build failures? Start at"
  },
  {
    "path": ".github/workflows/site-languages.yml",
    "chars": 2611,
    "preview": "on:\n  workflow_dispatch:\n\nname: pkgdown-i18n-netlify\n\njobs:\n  build-and-deploy:\n    runs-on: ubuntu-latest\n    strategy:"
  },
  {
    "path": ".github/workflows/test-coverage.yaml",
    "chars": 1954,
    "preview": "# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples\n# Need help debugging build failures? Start at"
  },
  {
    "path": ".gitignore",
    "chars": 84,
    "preview": ".Rproj.user\n.Rhistory\n.RData\ninst/doc\n*.orig\n.env\n*.tex\ndocs\n\n/.quarto/\n**/.quarto/\n"
  },
  {
    "path": ".lintr.R",
    "chars": 1229,
    "preview": "linters <- list(lintr::undesirable_function_linter(\n  fun = c(\n    # Base messaging\n    \"message\" = \"use cli::cli_inform"
  },
  {
    "path": ".vscode/extensions.json",
    "chars": 62,
    "preview": "{\n    \"recommendations\": [\n        \"Posit.air-vscode\"\n    ]\n}\n"
  },
  {
    "path": ".vscode/settings.json",
    "chars": 114,
    "preview": "{\n    \"[r]\": {\n        \"editor.formatOnSave\": true,\n        \"editor.defaultFormatter\": \"Posit.air-vscode\"\n    }\n}\n"
  },
  {
    "path": "DESCRIPTION",
    "chars": 2202,
    "preview": "Package: pkgdown\nTitle: Make Static HTML Documentation for a Package\nVersion: 2.2.0.9000\nAuthors@R: c(\n    person(\"Hadle"
  },
  {
    "path": "LICENSE",
    "chars": 45,
    "preview": "YEAR: 2025\nCOPYRIGHT HOLDER: pkgdown authors\n"
  },
  {
    "path": "LICENSE.md",
    "chars": 1074,
    "preview": "# MIT License\n\nCopyright (c) 2025 pkgdown authors\n\nPermission is hereby granted, free of charge, to any person obtaining"
  },
  {
    "path": "NAMESPACE",
    "chars": 3976,
    "preview": "# Generated by roxygen2: do not edit by hand\n\nS3method(\"[\",tag)\nS3method(as_data,\"NULL\")\nS3method(as_data,tag_arguments)"
  },
  {
    "path": "NEWS.md",
    "chars": 60833,
    "preview": "# pkgdown (development version)\n\n* When previewing a site, it is now served via a local http server. This enables dynami"
  },
  {
    "path": "R/build-404.R",
    "chars": 574,
    "preview": "build_404 <- function(pkg = \".\") {\n  pkg <- as_pkgdown(pkg)\n\n  # if this file exists, it will be handled by build_home_m"
  },
  {
    "path": "R/build-article.R",
    "chars": 8746,
    "preview": "#' @order 2\n#' @export\n#' @rdname build_articles\n#' @param name Name of article to render. This should be either a path\n"
  },
  {
    "path": "R/build-articles.R",
    "chars": 14117,
    "preview": "#' Build articles section\n#'\n#' @description\n#' `build_articles()` renders each R Markdown file underneath `vignettes/` "
  },
  {
    "path": "R/build-favicons.R",
    "chars": 3754,
    "preview": "#' Initialise favicons from package logo\n#'\n#' @description\n#' This function auto-detects the location of your package l"
  },
  {
    "path": "R/build-footer.R",
    "chars": 1632,
    "preview": "data_footer <- function(pkg = \".\", call = caller_env()) {\n  pkg <- as_pkgdown(pkg)\n\n  config_pluck_list(pkg, \"footer\", c"
  },
  {
    "path": "R/build-github.R",
    "chars": 1646,
    "preview": "#' Build site for GitHub pages\n#'\n#' @description\n#' Designed to be run as part of automated workflows for deploying\n#' "
  },
  {
    "path": "R/build-home-authors.R",
    "chars": 8302,
    "preview": "build_citation_authors <- function(pkg = \".\") {\n  pkg <- as_pkgdown(pkg)\n\n  source <- if (has_citation(pkg$src_path)) {\n"
  },
  {
    "path": "R/build-home-community.R",
    "chars": 946,
    "preview": "has_contributing <- function(path = \".\") {\n  file_exists(path(path, 'CONTRIBUTING.md')) ||\n    file_exists(path(path, '."
  },
  {
    "path": "R/build-home-index.R",
    "chars": 6951,
    "preview": "#' @export\n#' @rdname build_home\nbuild_home_index <- function(pkg = \".\", override = list(), quiet = TRUE) {\n  pkg <- sec"
  },
  {
    "path": "R/build-home-license.R",
    "chars": 2100,
    "preview": "# Renders LICENSE text file into html\nbuild_home_license <- function(pkg) {\n  license_md <- path_first_existing(pkg$src_"
  },
  {
    "path": "R/build-home-md.R",
    "chars": 1503,
    "preview": "build_home_md <- function(pkg) {\n  mds <- package_mds(pkg$src_path, in_dev = pkg$development$in_dev)\n\n  lapply(mds, rend"
  },
  {
    "path": "R/build-home.R",
    "chars": 10619,
    "preview": "#' Build home section\n#'\n#' @description\n#' `build_home()` function generates pages at the top-level of the site\n#' incl"
  },
  {
    "path": "R/build-llm-dl.R",
    "chars": 1634,
    "preview": "simplify_dls <- function(html) {\n  dls <- xml2::xml_find_all(html, \".//dl\")\n  for (dl in dls) {\n    simplify_dl(dl)\n  }\n"
  },
  {
    "path": "R/build-llm.R",
    "chars": 5754,
    "preview": "#' Build docs for LLMs\n#'\n#' @description\n#' `build_llm_docs()` creates an `LLMs.txt` at the root of your site\n#' that c"
  },
  {
    "path": "R/build-logo.R",
    "chars": 785,
    "preview": "copy_logo <- function(pkg = \".\") {\n  pkg <- as_pkgdown(pkg)\n\n  logo_path <- find_logo(pkg$src_path)\n  if (!is.null(logo_"
  },
  {
    "path": "R/build-news.R",
    "chars": 9828,
    "preview": "#' Build news section\n#'\n#' @description\n#' A `NEWS.md` will be broken up into versions using level one (`#`) or\n#' leve"
  },
  {
    "path": "R/build-quarto-articles.R",
    "chars": 5414,
    "preview": "build_quarto_articles <- function(pkg = \".\", article = NULL, quiet = TRUE) {\n  pkg <- as_pkgdown(pkg)\n\n  qmds <- pkg$vig"
  },
  {
    "path": "R/build-redirects.R",
    "chars": 3808,
    "preview": "#' Build redirects\n#'\n#' @description\n#' If you change the structure of your documentation (by renaming vignettes or\n#' "
  },
  {
    "path": "R/build-reference-index.R",
    "chars": 4875,
    "preview": "data_reference_index <- function(pkg = \".\", error_call = caller_env()) {\n  pkg <- as_pkgdown(pkg)\n\n  meta <- config_pluc"
  },
  {
    "path": "R/build-reference.R",
    "chars": 12917,
    "preview": "#' Build reference section\n#'\n#' By default, pkgdown will generate an index that lists all functions in\n#' alphabetical "
  },
  {
    "path": "R/build-search-docs.R",
    "chars": 10387,
    "preview": "build_docsearch_json <- function(pkg = \".\") {\n  pkg <- as_pkgdown(pkg)\n\n  index_name <- config_pluck_string(pkg, \"templa"
  },
  {
    "path": "R/build-tutorials.R",
    "chars": 3857,
    "preview": "#' Build tutorials section\n#'\n#' learnr tutorials must be hosted elsewhere as they require an\n#' R execution engine. Cur"
  },
  {
    "path": "R/build.R",
    "chars": 15653,
    "preview": "#' Build a complete pkgdown website\n#'\n#' @description\n#' `build_site()` is a convenient wrapper around six functions:\n#"
  },
  {
    "path": "R/check-built.R",
    "chars": 1263,
    "preview": "check_built_site <- function(pkg = \".\") {\n  pkg <- as_pkgdown(pkg)\n\n  cli::cli_rule(\"Checking for problems\")\n  index_pat"
  },
  {
    "path": "R/check.R",
    "chars": 3058,
    "preview": "#' Check `_pkgdown.yml`\n#'\n#' @description\n#' This pair of functions checks that your `_pkgdown.yml` is valid without\n#'"
  },
  {
    "path": "R/clean.R",
    "chars": 1781,
    "preview": "#' Clean site\n#'\n#' Delete all files in `docs/` (except for `CNAME`).\n#'\n#' @param quiet If `TRUE`, suppresses a message"
  },
  {
    "path": "R/config.R",
    "chars": 5583,
    "preview": "config_pluck <- function(pkg, path, default = NULL) {\n  check_string(path, allow_empty = FALSE, .internal = TRUE)\n\n  whe"
  },
  {
    "path": "R/context.R",
    "chars": 2521,
    "preview": "section_init <- function(\n  pkg,\n  subdir = NULL,\n  override = list(),\n  .frame = parent.frame()\n) {\n  rstudio_save_all("
  },
  {
    "path": "R/deploy-site.R",
    "chars": 7656,
    "preview": "#' Deploy a pkgdown site on Travis-CI to Github Pages\n#'\n#' @description\n#' `r lifecycle::badge('superseded')`\n#'\n#' `de"
  },
  {
    "path": "R/development.R",
    "chars": 1965,
    "preview": "meta_development <- function(pkg, call = caller_env()) {\n  config_pluck_list(pkg, \"development\", call = call)\n\n  mode <-"
  },
  {
    "path": "R/external-deps.R",
    "chars": 3581,
    "preview": "external_dependencies <- function(pkg, call = caller_env()) {\n  purrr::compact(list(\n    fontawesome::fa_html_dependency"
  },
  {
    "path": "R/figure.R",
    "chars": 4268,
    "preview": "fig_save <- function(\n  plot,\n  name,\n  dev = \"ragg::agg_png\",\n  dpi = 96L,\n  dev.args = list(),\n  fig.ext = \"png\",\n  fi"
  },
  {
    "path": "R/highlight.R",
    "chars": 2134,
    "preview": "# highligh_text() and highlight_examples() are only used for usage\n# and examples, and are specifically excluded in twea"
  },
  {
    "path": "R/html-build.R",
    "chars": 1057,
    "preview": "a <- function(text, href) {\n  ifelse(is.na(href), text, paste0(\"<a href='\", href, \"'>\", text, \"</a>\"))\n}\n\nlink_url <- fu"
  },
  {
    "path": "R/import-standalone-obj-type.R",
    "chars": 8598,
    "preview": "# Standalone file: do not edit by hand\n# Source: https://github.com/r-lib/rlang/blob/HEAD/R/standalone-obj-type.R\n# Gene"
  },
  {
    "path": "R/import-standalone-types-check.R",
    "chars": 10672,
    "preview": "# Standalone file: do not edit by hand\n# Source: https://github.com/r-lib/rlang/blob/HEAD/R/standalone-types-check.R\n# G"
  },
  {
    "path": "R/init.R",
    "chars": 4516,
    "preview": "#' Initialise site infrastructure\n#'\n#' @description\n#' `init_site()`:\n#'\n#' * creates the output directory (`docs/`),\n#"
  },
  {
    "path": "R/markdown.R",
    "chars": 4085,
    "preview": "markdown_text <- function(pkg, text, ...) {\n  if (identical(text, NA_character_) || is.null(text)) {\n    return(NULL)\n  "
  },
  {
    "path": "R/navbar-menu.R",
    "chars": 6859,
    "preview": "# Menu constructors -----------------------------------------------------------\n\n# Helpers for use within pkgdown itself"
  },
  {
    "path": "R/navbar.R",
    "chars": 8033,
    "preview": "data_navbar <- function(pkg = \".\", depth = 0L, call = caller_env()) {\n  pkg <- as_pkgdown(pkg)\n\n  navbar <- config_pluck"
  },
  {
    "path": "R/package.R",
    "chars": 12141,
    "preview": "#' Generate pkgdown data structure\n#'\n#' You will generally not need to use this unless you need a custom site\n#' design"
  },
  {
    "path": "R/pkgdown-package.R",
    "chars": 667,
    "preview": "#' @keywords internal\n\"_PACKAGE\"\n\n## usethis namespace: start\n#' @importFrom utils installed.packages\n#' @import rlang\n#"
  },
  {
    "path": "R/pkgdown.R",
    "chars": 440,
    "preview": "#' Determine if code is executed by pkgdown\n#'\n#' This is occasionally useful when you need different behaviour by\n#' pk"
  },
  {
    "path": "R/pkgdown_print.R",
    "chars": 1336,
    "preview": "#' Print object in pkgdown output\n#'\n#' This lets package authors control how objects are printed just for\n#' pkgdown ex"
  },
  {
    "path": "R/preview.R",
    "chars": 1864,
    "preview": "#' Open site in browser\n#'\n#' `preview_site()` opens your pkgdown site in your browser, served via a\n#' local HTTP serve"
  },
  {
    "path": "R/rd-data.R",
    "chars": 3065,
    "preview": "as_data <- function(x, ...) {\n  UseMethod(\"as_data\")\n}\n\n#' @export\nas_data.NULL <- function(x, ...) {\n  NULL\n}\n\n# Sectio"
  },
  {
    "path": "R/rd-example.R",
    "chars": 5694,
    "preview": "rd2ex <- function(x, ...) {\n  x <- rd_text(paste0(\"\\\\examples{\", x, \"}\"), fragment = FALSE)[[1]]\n  x <- process_conditio"
  },
  {
    "path": "R/rd-html.R",
    "chars": 15871,
    "preview": "as_html <- function(x, ...) {\n  UseMethod(\"as_html\")\n}\n\n# Various types of text ----------------------------------------"
  },
  {
    "path": "R/rd.R",
    "chars": 1536,
    "preview": "rd_text <- function(x, fragment = TRUE) {\n  con <- textConnection(x)\n  on.exit(close(con), add = TRUE)\n\n  set_classes(to"
  },
  {
    "path": "R/render.R",
    "chars": 8358,
    "preview": "#' Render page with template\n#'\n#' Each page is composed of four templates: \"head\", \"header\", \"content\", and\n#' \"footer\""
  },
  {
    "path": "R/repo.R",
    "chars": 3674,
    "preview": "repo_type <- function(pkg) {\n  home <- repo_home(pkg) %||% \"\"\n\n  if (grepl(\"^https?://github\\\\..+/\", home)) {\n    \"githu"
  },
  {
    "path": "R/template.R",
    "chars": 965,
    "preview": "#' Generate YAML templates\n#'\n#' Use these function to generate the default YAML that pkgdown uses for\n#' the different "
  },
  {
    "path": "R/templates.R",
    "chars": 1769,
    "preview": "find_template <- function(type, name, ext = \".html\", pkg = \".\") {\n  pkg <- as_pkgdown(pkg)\n\n  paths <- template_candidat"
  },
  {
    "path": "R/test.R",
    "chars": 6237,
    "preview": "#' Test case: lists\n#'\n#' @noMd\n#' @description\n#'\n#' \\subsection{Bulleted list}{\n#' \\itemize{\n#'   \\item a\n#'   \\item T"
  },
  {
    "path": "R/theme.R",
    "chars": 6541,
    "preview": "build_bslib <- function(pkg = \".\", call = caller_env()) {\n  pkg <- as_pkgdown(pkg)\n  bs_theme <- bs_theme(pkg, call = ca"
  },
  {
    "path": "R/topics-external.R",
    "chars": 1460,
    "preview": "ext_topics <- function(match_strings) {\n  pieces <- strsplit(match_strings, \"::\", fixed = TRUE)\n  pkg <- purrr::map_chr("
  },
  {
    "path": "R/topics.R",
    "chars": 7339,
    "preview": "# @return An integer vector giving selected topics\nselect_topics <- function(\n  match_strings,\n  topics,\n  check = FALSE"
  },
  {
    "path": "R/tweak-homepage.R",
    "chars": 3452,
    "preview": "tweak_homepage_html <- function(\n  html,\n  strip_header = FALSE,\n  sidebar = TRUE,\n  show_badges = TRUE,\n  bs_version = "
  },
  {
    "path": "R/tweak-navbar.R",
    "chars": 2685,
    "preview": "activate_navbar <- function(html, path, pkg = list(bs_version = 5)) {\n  if (pkg$bs_version <= 3) {\n    return()\n  }\n\n  p"
  },
  {
    "path": "R/tweak-page.R",
    "chars": 3558,
    "preview": "# File level tweaks --------------------------------------------\ntweak_page <- function(html, name, pkg = list(bs_versio"
  },
  {
    "path": "R/tweak-reference.R",
    "chars": 3008,
    "preview": "# Syntax highlighting for `\\preformatted{}` blocks in reference topics\ntweak_reference_highlighting <- function(html) {\n"
  },
  {
    "path": "R/tweak-tabset.R",
    "chars": 3473,
    "preview": "# Tabsets tweaking: find Markdown recommended in\n# https://bookdown.org/yihui/rmarkdown-cookbook/html-tabs.html\n# and ht"
  },
  {
    "path": "R/tweak-tags.R",
    "chars": 6426,
    "preview": "tweak_anchors <- function(html) {\n  headings <- xml2::xml_find_all(html, \".//h1|.//h2|.//h3|.//h4|.//h5|.//h6\")\n  # Find"
  },
  {
    "path": "R/tweak.R",
    "chars": 372,
    "preview": "has_class <- function(html, class) {\n  classes <- strsplit(xml2::xml_attr(html, \"class\"), \" \")\n  purrr::map_lgl(classes,"
  },
  {
    "path": "R/usage.R",
    "chars": 7008,
    "preview": "# Reference page ---------------------------------------------------------------\n\n# For testing\nusage2text <- function(x"
  },
  {
    "path": "R/utils-fs.R",
    "chars": 2920,
    "preview": "dir_copy_to <- function(\n  src_dir,\n  dst_dir,\n  src_root,\n  dst_root,\n  src_label = \"\",\n  dst_label = \"\"\n) {\n  check_st"
  },
  {
    "path": "R/utils-io.R",
    "chars": 754,
    "preview": "# Reading -----------------------------------------------------------------\n\nread_file <- function(path) {\n  lines <- re"
  },
  {
    "path": "R/utils-pdf.R",
    "chars": 902,
    "preview": "# Set various env vars (copied from tools::texi2dvi) to ensure that\n# latex can find bib and style files in the right pl"
  },
  {
    "path": "R/utils.R",
    "chars": 5456,
    "preview": "up_path <- function(depth) {\n  paste(rep.int(\"../\", depth), collapse = \"\")\n}\n\ndir_depth <- function(x) {\n  # length(strs"
  },
  {
    "path": "README.Rmd",
    "chars": 3827,
    "preview": "---\noutput: github_document\n---\n\n<!-- README.md is generated from README.Rmd. Please edit that file -->\n\n```{r}\n#| echo:"
  },
  {
    "path": "README.md",
    "chars": 3718,
    "preview": "\n<!-- README.md is generated from README.Rmd. Please edit that file -->\n\n# pkgdown <a href=\"https://pkgdown.r-lib.org\"><"
  },
  {
    "path": "air.toml",
    "chars": 29,
    "preview": "[format]\ntable = [\"tribble\"]\n"
  },
  {
    "path": "codecov.yml",
    "chars": 232,
    "preview": "comment: false\n\ncoverage:\n  status:\n    project:\n      default:\n        target: auto\n        threshold: 1%\n        infor"
  },
  {
    "path": "cran-comments.md",
    "chars": 251,
    "preview": "## R CMD check results\n\n0 errors | 0 warnings | 0 notes\n\n## revdepcheck results\n\nWe checked 165 reverse dependencies, co"
  },
  {
    "path": "inst/BS3/assets/bootstrap-toc.css",
    "chars": 1843,
    "preview": "/*!\n * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/)\n * Copyright 2015 Aidan Feldman\n * Lic"
  },
  {
    "path": "inst/BS3/assets/bootstrap-toc.js",
    "chars": 4764,
    "preview": "/*!\n * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/)\n * Copyright 2015 Aidan Feldman\n * Lic"
  },
  {
    "path": "inst/BS3/assets/docsearch.css",
    "chars": 11758,
    "preview": "/* Docsearch -------------------------------------------------------------- */\n/*\n  Source: https://github.com/algolia/d"
  },
  {
    "path": "inst/BS3/assets/docsearch.js",
    "chars": 2018,
    "preview": "$(function() {\n\n  // register a handler to move the focus to the search bar\n  // upon pressing shift + \"/\" (i.e. \"?\")\n  "
  },
  {
    "path": "inst/BS3/assets/pkgdown.css",
    "chars": 7308,
    "preview": "/* Sticky footer */\n\n/**\n * Basic idea: https://philipwalton.github.io/solved-by-flexbox/demos/sticky-footer/\n * Details"
  },
  {
    "path": "inst/BS3/assets/pkgdown.js",
    "chars": 3248,
    "preview": "/* http://gregfranko.com/blog/jquery-best-practices/ */\n(function($) {\n  $(function() {\n\n    $('.navbar-fixed-top').head"
  },
  {
    "path": "inst/BS3/templates/after-body.html",
    "chars": 43,
    "preview": "{{#includes}}{{{after_body}}}{{/includes}}\n"
  },
  {
    "path": "inst/BS3/templates/before-body.html",
    "chars": 44,
    "preview": "{{#includes}}{{{before_body}}}{{/includes}}\n"
  },
  {
    "path": "inst/BS3/templates/config-docsearch.json",
    "chars": 1970,
    "preview": "{\n  \"index_name\": \"{{index}}\",\n  \"start_urls\": [\n    {\n      \"url\": \"{{url}}/index.html\",\n      \"selectors_key\": \"homepa"
  },
  {
    "path": "inst/BS3/templates/content-article-index.html",
    "chars": 442,
    "preview": "<div class=\"row\">\n  <div class=\"col-md-9 contents\">\n    <div class=\"page-header\">\n      <h1>Articles</h1>\n    </div>\n\n  "
  },
  {
    "path": "inst/BS3/templates/content-article.html",
    "chars": 1437,
    "preview": "{{^as_is}}$for(header-includes)$\n$header-includes$\n$endfor${{/as_is}}\n\n<div class=\"row\">\n  <div class=\"col-md-9 contents"
  },
  {
    "path": "inst/BS3/templates/content-citation-authors.html",
    "chars": 796,
    "preview": "<div class=\"row\">\n  <div class=\"contents col-md-9\">\n    <div class=\"section level2 authors-section\">\n      <div class=\"p"
  },
  {
    "path": "inst/BS3/templates/content-home.html",
    "chars": 202,
    "preview": "<div class=\"row\">\n  <div class=\"contents col-md-9\">\n{{{index}}}\n  </div>\n\n  <div class=\"col-md-3 hidden-xs hidden-sm\" id"
  },
  {
    "path": "inst/BS3/templates/content-news-index.html",
    "chars": 258,
    "preview": "<div class=\"row\">\n  <div class=\"contents col-md-9\">\n    <div class=\"page-header\">\n      <h1>Release notes</h1>\n    </div"
  },
  {
    "path": "inst/BS3/templates/content-news.html",
    "chars": 460,
    "preview": "<div class=\"row\">\n  <div class=\"col-md-9 contents\">\n    <div class=\"page-header\">\n      <h1 data-toc-skip>Changelog <sma"
  },
  {
    "path": "inst/BS3/templates/content-reference-index.html",
    "chars": 1521,
    "preview": "<div class=\"row\">\n  <div class=\"contents col-md-9\">\n    <div class=\"page-header\">\n      <h1>Reference</h1>\n    </div>\n\n "
  },
  {
    "path": "inst/BS3/templates/content-reference-topic.html",
    "chars": 939,
    "preview": "<div class=\"row\">\n  <div class=\"col-md-9 contents\">\n    <div class=\"page-header\">\n    <h1>{{{title}}}</h1>\n    {{#source"
  },
  {
    "path": "inst/BS3/templates/content-title-body.html",
    "chars": 334,
    "preview": "<div class=\"row\">\n  <div class=\"contents col-md-9\">\n    <div class=\"page-header\">\n      <h1>{{pagetitle}}</h1>\n    </div"
  },
  {
    "path": "inst/BS3/templates/content-tutorial-index.html",
    "chars": 244,
    "preview": "<div class=\"row\">\n  <div class=\"contents col-md-9\">\n    <div class=\"page-header\">\n      <h1>Tutorials</h1>\n    </div>\n\n "
  },
  {
    "path": "inst/BS3/templates/content-tutorial.html",
    "chars": 262,
    "preview": "<div class=\"row\">\n  <div class=\"col-md-12\">\n    <div class=\"page-header\">\n      <h1>{{pagetitle}}</h1>\n    </div>\n</div>"
  },
  {
    "path": "inst/BS3/templates/docsearch.html",
    "chars": 618,
    "preview": "{{#yaml}}{{#docsearch}}\n<script src=\"https://cdnjs.cloudflare.com/ajax/libs/docsearch.js/2.6.1/docsearch.min.js\" integri"
  },
  {
    "path": "inst/BS3/templates/footer.html",
    "chars": 157,
    "preview": "{{#footer}}\n<div class=\"copyright\">\n  <p>{{#left}}{{{.}}}{{/left}}</p>\n</div>\n\n<div class=\"pkgdown\">\n  <p>{{#right}}{{{."
  },
  {
    "path": "inst/BS3/templates/head.html",
    "chars": 6049,
    "preview": "<meta charset=\"utf-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device"
  },
  {
    "path": "inst/BS3/templates/header.html",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "inst/BS3/templates/in-header.html",
    "chars": 42,
    "preview": "{{#includes}}{{{in_header}}}{{/includes}}\n"
  },
  {
    "path": "inst/BS3/templates/layout-redirect.html",
    "chars": 181,
    "preview": "<html>\n  <head>\n    <meta http-equiv=\"refresh\" content=\"0;URL={{{url}}}\" />\n    <meta name=\"robots\" content=\"noindex\">\n "
  },
  {
    "path": "inst/BS3/templates/layout.html",
    "chars": 482,
    "preview": "<!-- Generated by pkgdown: do not edit by hand -->\n<!DOCTYPE html>\n<html lang=\"{{{lang}}}\">\n  <head>\n  {{{ head }}}\n  {{"
  },
  {
    "path": "inst/BS3/templates/navbar.html",
    "chars": 1585,
    "preview": "{{#navbar}}\n<div class=\"navbar navbar-{{{type}}} navbar-fixed-top\" role=\"navigation\">\n  <div class=\"container\">\n    <div"
  },
  {
    "path": "inst/BS5/assets/katex-auto.js",
    "chars": 621,
    "preview": "// https://github.com/jgm/pandoc/blob/29fa97ab96b8e2d62d48326e1b949a71dc41f47a/src/Text/Pandoc/Writers/HTML.hs#L332-L345"
  },
  {
    "path": "inst/BS5/assets/lightswitch.js",
    "chars": 2498,
    "preview": "\n/*!\n * Color mode toggler for Bootstrap's docs (https://getbootstrap.com/)\n * Copyright 2011-2023 The Bootstrap Authors"
  },
  {
    "path": "inst/BS5/assets/pkgdown.js",
    "chars": 4961,
    "preview": "/* http://gregfranko.com/blog/jquery-best-practices/ */\n(function ($) {\n  $(function () {\n\n    $('nav.navbar').headroom("
  },
  {
    "path": "inst/BS5/assets/pkgdown.scss",
    "chars": 18260,
    "preview": "/* control page width ====================================================== */\n\n.row>main {\n  // Ensure contents never "
  },
  {
    "path": "inst/BS5/templates/after-body.html",
    "chars": 43,
    "preview": "{{#includes}}{{{after_body}}}{{/includes}}\n"
  },
  {
    "path": "inst/BS5/templates/before-body.html",
    "chars": 44,
    "preview": "{{#includes}}{{{before_body}}}{{/includes}}\n"
  },
  {
    "path": "inst/BS5/templates/config-docsearch.json",
    "chars": 1890,
    "preview": "{\n  \"index_name\": \"{{index}}\",\n  \"start_urls\": [\n    {\n      \"url\": \"{{url}}/index.html\",\n      \"selectors_key\": \"homepa"
  },
  {
    "path": "inst/BS5/templates/content-article-index.html",
    "chars": 704,
    "preview": "<div class=\"row\">\n  <main id=\"main\" class=\"col-md-9\">\n    <div class=\"page-header\">\n      {{#logo}}<img src=\"{{logo.src}"
  },
  {
    "path": "inst/BS5/templates/content-article.html",
    "chars": 1486,
    "preview": "{{^as_is}}$for(header-includes)$\n$header-includes$\n$endfor${{/as_is}}\n\n<div class=\"row\">\n  <main id=\"main\" class=\"col-md"
  },
  {
    "path": "inst/BS5/templates/content-authors.html",
    "chars": 710,
    "preview": "<div class=\"row\">\n  <main id=\"main\" class=\"col-md-9\">\n    <div class=\"page-header\">\n      {{#logo}}<img src=\"{{logo.src}"
  },
  {
    "path": "inst/BS5/templates/content-citation-authors.html",
    "chars": 1223,
    "preview": "<div class=\"row\">\n  <main id=\"main\" class=\"col-md-9\">\n    <div class=\"page-header\">\n      {{#logo}}<img src=\"{{logo.src}"
  },
  {
    "path": "inst/BS5/templates/content-home.html",
    "chars": 156,
    "preview": "<div class=\"row\">\n  <main id=\"main\" class=\"col-md-9\">\n{{{index}}}\n  </main>\n\n  <aside class=\"col-md-3\">\n{{#sidebar}}\n{{{"
  },
  {
    "path": "inst/BS5/templates/content-news-index.html",
    "chars": 543,
    "preview": "<div class=\"row\">\n  <main id=\"main\" class=\"col-md-9\">\n    <div class=\"page-header\">\n      {{#logo}}<img src=\"{{logo.src}"
  },
  {
    "path": "inst/BS5/templates/content-news.html",
    "chars": 495,
    "preview": "<div class=\"row\">\n  <main id=\"main\" class=\"col-md-9\">\n    <div class=\"page-header\">\n      {{#logo}}<img src=\"{{logo.src}"
  },
  {
    "path": "inst/BS5/templates/content-quarto.html",
    "chars": 1011,
    "preview": "<div class=\"row\">\n  <main id=\"main\" class=\"col-md-9\">\n    <div class=\"page-header\">\n      {{#logo}}<img src=\"{{logo.src}"
  },
  {
    "path": "inst/BS5/templates/content-reference-index.html",
    "chars": 1046,
    "preview": "<div class=\"row\">\n  <main id=\"main\" class=\"col-md-9\">\n    <div class=\"page-header\">\n      {{#logo}}<img src=\"{{logo.src}"
  },
  {
    "path": "inst/BS5/templates/content-reference-topic.html",
    "chars": 1166,
    "preview": "<div class=\"row\">\n  <main id=\"main\" class=\"col-md-9\">\n    <div class=\"page-header\">\n      {{#logo}}<img src=\"{{logo.src}"
  },
  {
    "path": "inst/BS5/templates/content-title-body.html",
    "chars": 473,
    "preview": "<div class=\"row\">\n  <main id=\"main\" class=\"col-md-9\">\n    <div class=\"page-header\">\n      {{#logo}}<img src=\"{{logo.src}"
  },
  {
    "path": "inst/BS5/templates/content-tutorial-index.html",
    "chars": 501,
    "preview": "<div class=\"row\">\n  <main id=\"main\" class=\"col-md-9\">\n    <div class=\"page-header\">\n      {{#logo}}<img src=\"{{logo.src}"
  },
  {
    "path": "inst/BS5/templates/content-tutorial.html",
    "chars": 460,
    "preview": "<div class=\"row\">\n  <main id=\"main\" class=\"col-md-12\">\n    <div class=\"page-header\">\n      <h1>{{pagetitle}}</h1>\n    </"
  },
  {
    "path": "inst/BS5/templates/footer.html",
    "chars": 166,
    "preview": "{{#footer}}\n<div class=\"pkgdown-footer-left\">\n  {{#left}}{{{.}}}{{/left}}\n</div>\n\n<div class=\"pkgdown-footer-right\">\n  {"
  },
  {
    "path": "inst/BS5/templates/head.html",
    "chars": 4028,
    "preview": "<meta charset=\"utf-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device"
  },
  {
    "path": "inst/BS5/templates/header.html",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "inst/BS5/templates/in-header.html",
    "chars": 42,
    "preview": "{{#includes}}{{{in_header}}}{{/includes}}\n"
  },
  {
    "path": "inst/BS5/templates/layout-redirect.html",
    "chars": 181,
    "preview": "<html>\n  <head>\n    <meta http-equiv=\"refresh\" content=\"0;URL={{{url}}}\" />\n    <meta name=\"robots\" content=\"noindex\">\n "
  },
  {
    "path": "inst/BS5/templates/layout.html",
    "chars": 479,
    "preview": "<!-- Generated by pkgdown: do not edit by hand -->\n<!DOCTYPE html>\n<html lang=\"{{{lang}}}\">\n  <head>\n  {{{ head }}}\n  {{"
  },
  {
    "path": "inst/BS5/templates/navbar.html",
    "chars": 1265,
    "preview": "{{#navbar}}\n<nav class=\"navbar navbar-expand-lg fixed-top {{#bg}}bg-{{{.}}}{{/bg}}\" {{#type}}data-bs-theme=\"{{{.}}}\"{{/t"
  },
  {
    "path": "inst/highlight-styles/a11y-dark.scss",
    "chars": 1674,
    "preview": "pre {background-color: #2b2b2b;}\npre code         /* Normal         */ {color:#f8f8f2}\npre code span.al /* Alert        "
  },
  {
    "path": "inst/highlight-styles/a11y-light.scss",
    "chars": 1674,
    "preview": "pre {background-color: #fefefe;}\npre code         /* Normal         */ {color:#545454}\npre code span.al /* Alert        "
  },
  {
    "path": "inst/highlight-styles/arrow-dark.scss",
    "chars": 1850,
    "preview": "pre code         /* Normal         */ {color:#f8f8f2}\npre code span.al /* Alert          */ {color:#f07178; background-c"
  },
  {
    "path": "inst/highlight-styles/arrow-light.scss",
    "chars": 1687,
    "preview": "pre {background-color: #f1f3f5;}\npre code         /* Normal         */ {color:#003B4F}\npre code span.al /* Alert        "
  },
  {
    "path": "inst/highlight-styles/atom-one-dark.scss",
    "chars": 1832,
    "preview": "pre code         /* Normal         */ {color:#abb2bf}\npre code span.al /* Alert          */ {color:#95da4c; background-c"
  },
  {
    "path": "inst/highlight-styles/atom-one-light.scss",
    "chars": 1832,
    "preview": "pre code         /* Normal         */ {color:#383a42}\npre code span.al /* Alert          */ {color:#95da4c; background-c"
  },
  {
    "path": "inst/highlight-styles/ayu-dark.scss",
    "chars": 1883,
    "preview": "pre {background-color: #0a0e14;}\npre code         /* Normal         */ {color:#b3b1ad}\npre code span.al /* Alert        "
  },
  {
    "path": "inst/highlight-styles/ayu-light.scss",
    "chars": 1883,
    "preview": "pre {background-color: #fafafa;}\npre code         /* Normal         */ {color:#575f66}\npre code span.al /* Alert        "
  },
  {
    "path": "inst/highlight-styles/ayu-mirage.scss",
    "chars": 1883,
    "preview": "pre {background-color: #1f2430;}\npre code         /* Normal         */ {color:#cbccc6}\npre code span.al /* Alert        "
  },
  {
    "path": "inst/highlight-styles/breeze-dark.scss",
    "chars": 1882,
    "preview": "pre {background-color: #232629;}\npre code         /* Normal         */ {color:#cfcfc2}\npre code span.al /* Alert        "
  },
  {
    "path": "inst/highlight-styles/breeze-light.scss",
    "chars": 1882,
    "preview": "pre {background-color: #ffffff;}\npre code         /* Normal         */ {color:#1f1c1b}\npre code span.al /* Alert        "
  },
  {
    "path": "inst/highlight-styles/breezedark.scss",
    "chars": 1898,
    "preview": "pre {background-color: #232629; color: #cfcfc2;}\npre code         /* Normal         */ {color:#cfcfc2}\npre code span.al "
  },
  {
    "path": "inst/highlight-styles/dracula.scss",
    "chars": 1793,
    "preview": "pre {background-color: #282a36;}\npre code         /* Normal         */ {color:#f8f8f2}\npre code span.al /* Alert        "
  },
  {
    "path": "inst/highlight-styles/espresso.scss",
    "chars": 1665,
    "preview": "pre {background-color: #2a211c; color: #bdae9d;}\npre code span.al /* Alert          */ {color:#ffff00}\npre code span.an "
  },
  {
    "path": "inst/highlight-styles/github-dark.scss",
    "chars": 1773,
    "preview": "pre {background-color: #24292e;}\npre code         /* Normal         */ {color:#e1e4e8}\npre code span.al /* Alert        "
  },
  {
    "path": "inst/highlight-styles/github-light.scss",
    "chars": 1773,
    "preview": "pre {background-color: #ffffff;}\npre code         /* Normal         */ {color:#24292e}\npre code span.al /* Alert        "
  },
  {
    "path": "inst/highlight-styles/gruvbox-dark.scss",
    "chars": 1934,
    "preview": "pre {background-color: #282828;}\npre code         /* Normal         */ {color:#ebdbb2}\npre code span.al /* Alert        "
  },
  {
    "path": "inst/highlight-styles/gruvbox-light.scss",
    "chars": 1934,
    "preview": "pre {background-color: #fbf1c7;}\npre code         /* Normal         */ {color:#3c3836}\npre code span.al /* Alert        "
  },
  {
    "path": "inst/highlight-styles/haddock.scss",
    "chars": 1243,
    "preview": "pre code span.al /* Alert          */ {color:#ff0000}\npre code span.an /* Annotation     */ {color:#008000}\npre code spa"
  },
  {
    "path": "inst/highlight-styles/kate.scss",
    "chars": 1898,
    "preview": "pre {background-color: #ffffff; color: #1f1c1b;}\npre code         /* Normal         */ {color:#1f1c1b}\npre code span.al "
  },
  {
    "path": "inst/highlight-styles/monochrome-dark.scss",
    "chars": 1843,
    "preview": "pre {background-color: #000000; color: #FFFFFF;}\npre code         /* Normal         */ {color:#FFFFFF}\npre code span.al "
  },
  {
    "path": "inst/highlight-styles/monochrome-light.scss",
    "chars": 1843,
    "preview": "pre {background-color: #ffffff; color: #000000;}\npre code         /* Normal         */ {color:#000000}\npre code span.al "
  },
  {
    "path": "inst/highlight-styles/monochrome.scss",
    "chars": 699,
    "preview": "pre code span.al /* Alert         */ {font-weight: bold}\npre code span.an /* Annotation    */ {font-style: italic}\npre c"
  },
  {
    "path": "inst/highlight-styles/monokai.scss",
    "chars": 1793,
    "preview": "pre {background-color: #2e3440;}\npre code         /* Normal         */ {color:#f8f8f2}\npre code span.al /* Alert        "
  },
  {
    "path": "inst/highlight-styles/nord.scss",
    "chars": 1902,
    "preview": "pre {background-color: #2e3440;}\npre code         /* Normal         */ {color:#d8dee9}\npre code span.al /* Alert        "
  },
  {
    "path": "inst/highlight-styles/oblivion.scss",
    "chars": 1901,
    "preview": "pre {background-color: #201f1f;}\npre code         /* Normal         */ {color:#d3d7c1}\npre code span.al /* Alert        "
  },
  {
    "path": "inst/highlight-styles/printing.scss",
    "chars": 1863,
    "preview": "pre {background-color: #ffffff;}\npre code         /* Normal         */ {color:#000000}\npre code span.al /* Alert        "
  },
  {
    "path": "inst/highlight-styles/pygments.scss",
    "chars": 1799,
    "preview": "pre code span.al /* Alert          */ {color:#ff0000; font-weight: bold}\npre code span.an /* Annotation     */ {color:#6"
  },
  {
    "path": "inst/highlight-styles/radical.scss",
    "chars": 1908,
    "preview": "pre code         /* Normal         */ {color:#7c9c9e}\npre code span.al /* Alert          */ {color:#ff427b; background-c"
  },
  {
    "path": "inst/highlight-styles/solarized-dark.scss",
    "chars": 1819,
    "preview": "pre {background-color: #002b36;}\npre code         /* Normal         */ {color:#839496}\npre code span.al /* Alert        "
  },
  {
    "path": "inst/highlight-styles/solarized-light.scss",
    "chars": 1895,
    "preview": "pre {background-color: #fdf6e3;}\npre code         /* Normal         */ {color:#657b83}\npre code span.al /* Alert        "
  },
  {
    "path": "inst/highlight-styles/solarized.scss",
    "chars": 1895,
    "preview": "pre {background-color: #fdf6e3;}\npre code         /* Normal         */ {color:#657b83}\npre code span.al /* Alert        "
  },
  {
    "path": "inst/highlight-styles/tango.scss",
    "chars": 1830,
    "preview": "pre {background-color: #f8f8f8;}\npre code span.al /* Alert          */ {color:#ef2929}\npre code span.an /* Annotation   "
  },
  {
    "path": "inst/highlight-styles/vim-dark.scss",
    "chars": 1901,
    "preview": "pre {background-color: #000000;}\npre code         /* Normal         */ {color:#b2b2b2}\npre code span.al /* Alert        "
  },
  {
    "path": "inst/highlight-styles/zenburn.scss",
    "chars": 1664,
    "preview": "pre {background-color: #303030; color: #cccccc;}\npre code span.al /* Alert          */ {color:#ffcfaf}\npre code span.an "
  },
  {
    "path": "inst/quarto/template.html",
    "chars": 932,
    "preview": "<!-- Based on https://github.com/quarto-dev/quarto-cli/blob/main/src/resources/formats/html/pandoc/template.html -->\n<!D"
  },
  {
    "path": "inst/rstudio/addins.dcf",
    "chars": 107,
    "preview": "Name: Build full site\nDescription: Build website for current package\nBinding: build_site\nInteractive: true\n"
  },
  {
    "path": "man/as_pkgdown.Rd",
    "chars": 535,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/package.R\n\\name{as_pkgdown}\n\\alias{as_pkgd"
  },
  {
    "path": "man/build_articles.Rd",
    "chars": 10412,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/build-articles.R, R/build-article.R\n\\name{"
  },
  {
    "path": "man/build_favicons.Rd",
    "chars": 1069,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/build-favicons.R\n\\name{build_favicons}\n\\al"
  },
  {
    "path": "man/build_home.Rd",
    "chars": 11828,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/build-home.R, R/build-home-index.R\n\\name{b"
  },
  {
    "path": "man/build_llm_docs.Rd",
    "chars": 1069,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/build-llm.R\n\\name{build_llm_docs}\n\\alias{b"
  },
  {
    "path": "man/build_news.Rd",
    "chars": 2890,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/build-news.R\n\\name{build_news}\n\\alias{buil"
  },
  {
    "path": "man/build_redirects.Rd",
    "chars": 1370,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/build-redirects.R\n\\name{build_redirects}\n\\"
  },
  {
    "path": "man/build_reference.Rd",
    "chars": 7131,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/build-reference.R\n\\name{build_reference}\n\\"
  },
  {
    "path": "man/build_search.Rd",
    "chars": 1220,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/build-search-docs.R\n\\name{build_search}\n\\a"
  }
]

// ... and 239 more files (download for full content)

About this extraction

This page contains the full source code of the hadley/pkgdown GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 439 files (1.2 MB), approximately 397.4k tokens, and a symbol index with 8 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!