├── .Rbuildignore ├── .github ├── .gitignore └── workflows │ ├── R-CMD-check.yaml │ └── pkgdown.yaml ├── .gitignore ├── DESCRIPTION ├── LICENSE ├── LICENSE.md ├── NAMESPACE ├── NEWS.md ├── R ├── apple.R ├── general.R ├── geo.R ├── google_scholar.R ├── meta.R ├── metathis-package.R ├── social.R ├── utils-meta.R ├── utils-pipe.R ├── utils.R ├── viewport.R └── write.R ├── README.Rmd ├── README.md ├── cran-comments.md ├── inst └── WORDLIST ├── man-roxygen ├── describe-meta-return.R └── describe-meta.R ├── man ├── figures │ ├── card.png │ ├── card.svg │ ├── logo.png │ └── logo.svg ├── include_meta.Rd ├── meta.Rd ├── meta_apple_itunes_app.Rd ├── meta_apple_web_app.Rd ├── meta_general.Rd ├── meta_geo.Rd ├── meta_google_scholar.Rd ├── meta_name.Rd ├── meta_social.Rd ├── meta_tag.Rd ├── meta_viewport.Rd ├── metathis-package.Rd ├── pipe.Rd └── write_meta.Rd ├── metathis.Rproj ├── pkgdown ├── _pkgdown.yml └── favicon │ ├── apple-touch-icon-120x120.png │ ├── apple-touch-icon-152x152.png │ ├── apple-touch-icon-180x180.png │ ├── apple-touch-icon-60x60.png │ ├── apple-touch-icon-76x76.png │ ├── apple-touch-icon.png │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ └── favicon.ico └── tests ├── testthat.R └── testthat ├── helper.R ├── rmd ├── .gitignore ├── test-metathis.Rmd └── test-not-self-contained.Rmd ├── test-apple.R ├── test-blogdown.R ├── test-general.R ├── test-geo.R ├── test-google_scholar.R ├── test-meta.R ├── test-rmd.R ├── test-social.R ├── test-viewport.R └── test-write.R /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^metathis\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^LICENSE\.md$ 4 | ^README\.Rmd$ 5 | ^man-roxygen$ 6 | ^pkgdown$ 7 | ^tests/manual$ 8 | ^\.travis\.yml$ 9 | ^appveyor\.yml$ 10 | ^tic\.R$ 11 | ^cran-comments\.md$ 12 | ^CRAN-RELEASE$ 13 | ^\.ccache$ 14 | ^\.github$ 15 | ^docs$ 16 | ^CRAN-SUBMISSION$ 17 | -------------------------------------------------------------------------------- /.github/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | -------------------------------------------------------------------------------- /.github/workflows/R-CMD-check.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | schedule: 9 | # * is a special character in YAML so you have to quote this string 10 | - cron: "0 4 * * 1" 11 | 12 | name: R-CMD-check 13 | 14 | jobs: 15 | R-CMD-check: 16 | runs-on: ${{ matrix.config.os }} 17 | 18 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 19 | 20 | strategy: 21 | fail-fast: false 22 | matrix: 23 | config: 24 | - {os: macOS-latest, r: 'release'} 25 | - {os: windows-latest, r: 'release'} 26 | - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} 27 | - {os: ubuntu-latest, r: 'release'} 28 | - {os: ubuntu-latest, r: 'oldrel-1'} 29 | 30 | env: 31 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 32 | R_KEEP_PKG_SOURCE: yes 33 | 34 | steps: 35 | - uses: actions/checkout@v2 36 | 37 | - uses: r-lib/actions/setup-pandoc@v2 38 | 39 | - uses: r-lib/actions/setup-r@v2 40 | with: 41 | r-version: ${{ matrix.config.r }} 42 | http-user-agent: ${{ matrix.config.http-user-agent }} 43 | use-public-rspm: true 44 | 45 | - uses: r-lib/actions/setup-r-dependencies@v2 46 | with: 47 | extra-packages: any::rcmdcheck 48 | needs: check 49 | 50 | - uses: r-lib/actions/check-r-package@v2 51 | with: 52 | upload-snapshots: true 53 | 54 | - name: Update status dashboard 55 | uses: gadenbuie/status/actions/status-update-rcmdcheck@main 56 | with: 57 | github-token-repo-scope: ${{ secrets.GADENBUIE_STATUS }} 58 | status-repo: gadenbuie/status 59 | -------------------------------------------------------------------------------- /.github/workflows/pkgdown.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | tags: 6 | - 'v[0-9]+.[0-9]+.[0-9]+' # build on version tags 7 | - '!v[0-9]+.[0-9]+.[0-9]+.[0-9]+' # but not if version involves a dev component 8 | branches: 9 | - main 10 | pull_request: 11 | branches: 12 | - main 13 | types: 14 | - opened 15 | - reopened 16 | - synchronize 17 | - closed 18 | paths: 19 | - 'man/**' 20 | - 'pkgdown/**' 21 | - 'vignettes/**' 22 | - 'NEWS.md' 23 | - 'README.md' 24 | workflow_dispatch: 25 | 26 | name: pkgdown 27 | 28 | jobs: 29 | pkgdown: 30 | if: ${{ !(github.event_name == 'pull_request' && github.event.action == 'closed') }} 31 | runs-on: ubuntu-latest 32 | 33 | # Only restrict concurrency for non-PR jobs 34 | concurrency: 35 | group: pkgdown-${{ github.event_name != 'pull_request' || github.run_id }} 36 | 37 | env: 38 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 39 | 40 | steps: 41 | - uses: actions/checkout@v2 42 | 43 | - uses: r-lib/actions/setup-pandoc@v2 44 | 45 | - uses: r-lib/actions/setup-r@v2 46 | with: 47 | use-public-rspm: true 48 | 49 | - uses: r-lib/actions/setup-r-dependencies@v2 50 | with: 51 | extra-packages: any::pkgdown, local::. 52 | needs: website 53 | 54 | - name: Build site 55 | shell: Rscript {0} 56 | run: | 57 | pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE) 58 | pkg <- pkgdown::as_pkgdown(".") 59 | 60 | # Report base site URL 61 | cat(sprintf('baseurl=%s', pkg$meta$url), file = Sys.getenv("GITHUB_ENV"), append = TRUE) 62 | 63 | - name: Set site deploy subdirectory 64 | run: | 65 | if [[ -d docs/dev ]]; then 66 | srcdir=docs/dev 67 | targetdir=dev 68 | else 69 | srcdir=docs/ 70 | targetdir=. 71 | fi 72 | if [[ $GITHUB_REF == refs/tags/v* ]]; then 73 | # If event is a version tag event, set targetdir to '' 74 | targetdir=${GITHUB_REF#refs/tags/} 75 | elif [[ $GITHUB_REF == refs/pull/* ]]; then 76 | # If PR, set targetdir to 'preview/pr' 77 | targetdir=preview/pr${{ github.event.pull_request.number }} 78 | fi 79 | echo "Deploying site from $srcdir to $targetdir on gh-pages" 80 | echo "srcdir=$srcdir" >> $GITHUB_ENV 81 | echo "targetdir=$targetdir" >> $GITHUB_ENV 82 | 83 | - name: Deploy to GitHub pages 🚀 84 | uses: JamesIves/github-pages-deploy-action@4.1.4 85 | with: 86 | clean-exclude: | 87 | preview/ 88 | v*/ 89 | dev/ 90 | branch: gh-pages 91 | folder: ${{ env.srcdir }} 92 | target-folder: ${{ env.targetdir }} 93 | 94 | - name: Notify pkgdown deployment 95 | if: github.event_name == 'pull_request' 96 | uses: hasura/comment-progress@v2.2.0 97 | with: 98 | github-token: ${{ secrets.GITHUB_TOKEN }} 99 | repository: ${{ github.repository }} 100 | number: ${{ github.event.number }} 101 | id: pkgdown-deploy 102 | append: false 103 | message: > 104 | :book: ${{ env.baseurl }}/${{ env.targetdir }} 105 | Preview documentation for this PR (at commit ${{ github.event.pull_request.head.sha }}) 106 | 107 | 108 | pkgdown-clean: 109 | if: ${{ github.event_name == 'pull_request' && github.event.action == 'closed' }} 110 | runs-on: ubuntu-latest 111 | 112 | env: 113 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 114 | 115 | steps: 116 | - uses: actions/checkout@v2 117 | with: 118 | ref: "gh-pages" 119 | 120 | - name: Clean up PR Preview 121 | run: | 122 | git config --local user.name "$GITHUB_ACTOR" 123 | git config --local user.email "$GITHUB_ACTOR@users.noreply.github.com" 124 | preview_dir="preview/pr${{ github.event.pull_request.number }}" 125 | if [ -d "$preview_dir" ]; then 126 | git rm -r $preview_dir 127 | git commit -m "Remove $preview_dir (GitHub Actions)" || echo 'No preview to remove' 128 | git push origin || echo 'No preview to remove' 129 | else 130 | echo 'No preview to remove' 131 | fi 132 | 133 | - name: Notify pkgdown cleanup 134 | uses: hasura/comment-progress@v2.2.0 135 | with: 136 | github-token: ${{ secrets.GITHUB_TOKEN }} 137 | repository: ${{ github.repository }} 138 | number: ${{ github.event.number }} 139 | id: pkgdown-deploy 140 | message: | 141 | _:closed_book: Preview documentation for this PR has been cleaned up._ 142 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # ---- Default .gitignore From grkmisc ---- 2 | .Rproj.user 3 | .Rhistory 4 | .RData 5 | .DS_Store 6 | 7 | # Directories that start with _ 8 | _*/ 9 | 10 | ## https://github.com/github/gitignore/blob/master/R.gitignore 11 | # History files 12 | .Rhistory 13 | .Rapp.history 14 | 15 | # Session Data files 16 | .RData 17 | 18 | # Example code in package build process 19 | *-Ex.R 20 | 21 | # Output files from R CMD build 22 | /*.tar.gz 23 | 24 | # Output files from R CMD check 25 | /*.Rcheck/ 26 | 27 | # RStudio files 28 | .Rproj.user/ 29 | 30 | # produced vignettes 31 | vignettes/*.html 32 | vignettes/*.pdf 33 | 34 | # OAuth2 token, see https://github.com/hadley/httr/releases/tag/v0.3 35 | .httr-oauth 36 | 37 | # knitr and R markdown default cache directories 38 | /*_cache/ 39 | /cache/ 40 | 41 | # Temporary files created by R markdown 42 | *.utf8.md 43 | *.knit.md 44 | 45 | # Shiny token, see https://shiny.rstudio.com/articles/shinyapps.html 46 | rsconnect/ 47 | 48 | ## https://github.com/github/gitignore/blob/master/Global/macOS.gitignore 49 | # General 50 | .DS_Store 51 | .AppleDouble 52 | .LSOverride 53 | 54 | # Icon must end with two \r 55 | Icon 56 | 57 | 58 | # Thumbnails 59 | ._* 60 | 61 | # Files that might appear in the root of a volume 62 | .DocumentRevisions-V100 63 | .fseventsd 64 | .Spotlight-V100 65 | .TemporaryItems 66 | .Trashes 67 | .VolumeIcon.icns 68 | .com.apple.timemachine.donotpresent 69 | 70 | # Directories potentially created on remote AFP share 71 | .AppleDB 72 | .AppleDesktop 73 | Network Trash Folder 74 | Temporary Items 75 | .apdisk 76 | tests/manual 77 | docs/ 78 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: metathis 2 | Title: HTML Metadata Tags for 'R Markdown' and 'Shiny' 3 | Version: 1.1.4.9000 4 | Authors@R: 5 | person(given = "Garrick", 6 | family = "Aden-Buie", 7 | role = c("aut", "cre"), 8 | email = "garrick@adenbuie.com", 9 | comment = c(ORCID = "0000-0002-7111-0077")) 10 | Description: Create meta tags for 'R Markdown' HTML documents and 'Shiny' 11 | apps for customized social media cards, for accessibility, and quality 12 | search engine indexing. 'metathis' currently supports HTML documents 13 | created with 'rmarkdown', 'shiny', 'xaringan', 'pagedown', 'bookdown', 14 | and 'flexdashboard'. 15 | License: MIT + file LICENSE 16 | URL: https://pkg.garrickadenbuie.com/metathis/, 17 | https://github.com/gadenbuie/metathis 18 | BugReports: https://github.com/gadenbuie/metathis/issues 19 | Imports: 20 | htmltools, 21 | knitr, 22 | magrittr, 23 | purrr 24 | Suggests: 25 | rmarkdown, 26 | shiny, 27 | testthat (>= 2.1.0) 28 | Config/Needs/website: gadenbuie/grkgdown 29 | Encoding: UTF-8 30 | Roxygen: list(markdown = TRUE) 31 | RoxygenNote: 7.2.3 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2020 2 | COPYRIGHT HOLDER: Garrick Aden-Buie 3 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | Copyright (c) 2019 Garrick Aden-Buie 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | S3method(as.character,meta) 4 | S3method(as_meta,data.frame) 5 | S3method(as_meta,default) 6 | S3method(as_meta,list) 7 | S3method(format,meta) 8 | S3method(knit_print,meta) 9 | S3method(print,meta) 10 | export("%>%") 11 | export(as_meta) 12 | export(include_meta) 13 | export(is_meta) 14 | export(meta) 15 | export(meta_apple_itunes_app) 16 | export(meta_apple_web_app) 17 | export(meta_description) 18 | export(meta_general) 19 | export(meta_geo) 20 | export(meta_google_scholar) 21 | export(meta_name) 22 | export(meta_referrer) 23 | export(meta_robots) 24 | export(meta_social) 25 | export(meta_subject) 26 | export(meta_tag) 27 | export(meta_theme_color) 28 | export(meta_viewport) 29 | export(write_meta) 30 | importFrom(knitr,knit_print) 31 | importFrom(magrittr,"%>%") 32 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # metathis (development version) 4 | 5 | 6 | # metathis 1.1.4 7 | 8 | - Fixed a usage of numeric package version as requested by CRAN. 9 | 10 | - Removed a link in the docs to the now-defunct Twitter Card validator. 11 | 12 | 13 | # metathis 1.1.3 14 | 15 | - Fix S3 method signatures to resolve recent CRAN warnings (#30). 16 | 17 | # metathis 1.1.2 18 | 19 | * Fix link to `` tag docs on MDN (@IndrajeetPatil, #25) 20 | 21 | * Rebuild documentation for CRAN 22 | 23 | # metathis 1.1.1 24 | 25 | - Fixed an issue that caused metathis to fail for versions of rmarkdown <= 2.8 26 | 27 | # metathis 1.1.0 28 | 29 | - Fixed an issue with the Twitter image `` tag (thanks @llrs, #19). 30 | 31 | - Added `meta_google_scholar()` to help create the `` tags expected by 32 | [Google Scholar](https://scholar.google.com/intl/en/scholar/inclusion.html#indexing) (#5). 33 | 34 | - metathis no longer creates an empty folder in the directory where dependencies 35 | sourced via htmltools are saved when using non-stand-alone documents. 36 | 37 | # metathis 1.0.3 38 | 39 | - Fixed an issue with open graph social media `` tags (#10) 40 | 41 | # metathis 1.0.2 42 | 43 | _metathis_ package released! 44 | -------------------------------------------------------------------------------- /R/apple.R: -------------------------------------------------------------------------------- 1 | ## 2 | ## 3 | ## 4 | ## 5 | ## 6 | ## 7 | ## 8 | ## 9 | ## 10 | ## 11 | ## 12 | ## 13 | ## 14 | ## 15 | ## 16 | ## 17 | ## 18 | ## 19 | ## 20 | ## 21 | ## 22 | ## 23 | ## 24 | ## [Configuring Web Applications](https://developer.apple.com/library/content/documentation/AppleApplications/Reference/SafariWebContent/ConfiguringWebApplications/ConfiguringWebApplications.html) 25 | 26 | 27 | #' Apple Web App Meta Tags 28 | #' 29 | #' @template describe-meta 30 | #' @template describe-meta-return 31 | #' @param title Launch Icon Title 32 | #' @param capable Enables standalone (full-screen) mode if TRUE 33 | #' @param status_bar_style Status bar appearance. has no effect unless 34 | #' standalone more is enabled (see `capable`). 35 | #' 36 | #' "If content is set to default, the status bar appears normal. If set to 37 | #' black, the status bar has a black background. If set to black-translucent, 38 | #' the status bar is black and translucent. If set to default or black, the 39 | #' web content is displayed below the status bar. If set to black-translucent, 40 | #' the web content is displayed on the entire screen, partially obscured by 41 | #' the status bar. The default value is default." 42 | #' 43 | #' @references 44 | #' 45 | #' 46 | #' @examples 47 | #' meta() %>% 48 | #' meta_apple_web_app( 49 | #' title = "My Fancy App", 50 | #' capable = TRUE, 51 | #' status_bar_style = "black-translucent" 52 | #' ) 53 | #' @export 54 | meta_apple_web_app <- function( 55 | .meta = meta(), 56 | title = NULL, 57 | capable = NULL, 58 | status_bar_style = c("default", "black", "black-translucent") 59 | ) { 60 | assert_is_meta(.meta) 61 | 62 | apple <- list( 63 | title = title, 64 | capable = capable %??% ifelse(capable[[1]], "yes", "no"), 65 | status_bar_style = status_bar_style %??% match.arg(status_bar_style) 66 | ) 67 | 68 | names(apple) <- paste0("apple-mobile-web-app-", names(apple)) 69 | 70 | meta_apple <- 71 | apple %>% 72 | names_replace_underscore("-") %>% 73 | collapse_single_string() %>% 74 | tag_meta_list() 75 | 76 | append_to_meta(.meta, meta_apple) 77 | } 78 | 79 | #' Apple Smart Banner Meta Tag 80 | #' 81 | #' @template describe-meta 82 | #' @template describe-meta-return 83 | #' @param app_id Apple app ID 84 | #' @param affiliate_id Apple affiliate ID 85 | #' @param ... Additional name=value pairs. 86 | #' 87 | #' @section Example: 88 | #' 89 | #' ``` 90 | #' # 91 | #' 92 | #' ``` 93 | #' 94 | #' @export 95 | meta_apple_itunes_app <- function( 96 | .meta = meta(), 97 | app_id = NULL, 98 | affiliate_id = NULL, 99 | ... 100 | ) { 101 | 102 | assert_is_meta(.meta) 103 | 104 | args <- c( 105 | list(`app-id` = app_id, `affiliate-data` = affiliate_id), 106 | list(...) 107 | ) 108 | args <- purrr::compact(args) 109 | if (!length(args)) { 110 | return(.meta) 111 | } 112 | 113 | content <- args %>% 114 | purrr::imap_chr(~ paste0(.y, "=", .x)) %>% 115 | collapse(",") 116 | 117 | meta_new <- tag_meta(name = "apple-itunes-app", content = content) 118 | 119 | append_to_meta(.meta, list(meta_new)) 120 | } 121 | -------------------------------------------------------------------------------- /R/general.R: -------------------------------------------------------------------------------- 1 | 2 | #' General Metadata Tags 3 | #' 4 | #' Generate metadata tags for general website properties. 5 | #' 6 | #' @template describe-meta 7 | #' @param application_name Name of web application (only should be used if the 8 | #' website is used as an app). 9 | #' @param theme_color Theme Color for Chrome, Firefox OS and Opera, e.g. 10 | #' `"#00589a"`. 11 | #' @param description Short description of the document (limit to 150 12 | #' characters), This content *may* be used as a part of search engine results. 13 | #' @param robots Control the behavior of search engine crawling and indexing, 14 | #' e.g. `"index,follow"`. Valid names are `"index"`, `"noindex"`, `"follow"`, 15 | #' `"nofollow"`. May be a vector or a single string with comma-separated 16 | #' values. 17 | #' 18 | #' See for more information. 19 | #' @param generator Identify the software used to build the document (i.e. - 20 | #' WordPress, Dreamweaver). 21 | #' @param subject Short description of your document's subject. 22 | #' @param rating Gives a general age rating based on the document's content, 23 | #' e.g. `"General"`. 24 | #' @param referrer Allows control over how referrer information is passed, .e.g. 25 | #' `"no-referrer"`. Valid values include `"no-referrer"`, 26 | #' `"no-referrer-when-downgrade"`, `"same-origin"`, `"origin"`, 27 | #' `"strict-origin"`, `"origin-when-cross-origin"`, 28 | #' `"strict-origin-when-cross-origin"`, or `"unsafe-url"`. 29 | #' 30 | #' @template describe-meta-return 31 | #' @examples 32 | #' meta() %>% 33 | #' meta_general( 34 | #' application_name = "Application Name", 35 | #' theme_color = "#4285f4", 36 | #' description = "A description of this page", 37 | #' robots = "index,follow", 38 | #' generator = "R-Shiny", 39 | #' subject = "Awesome R projects", 40 | #' rating = "General", 41 | #' referrer = "no-referrer" 42 | #' ) 43 | #' 44 | #' @export 45 | meta_general <- function( 46 | .meta = meta(), 47 | application_name = NULL, 48 | theme_color = NULL, 49 | description = NULL, 50 | robots = NULL, 51 | generator = NULL, 52 | subject = NULL, 53 | rating = NULL, 54 | referrer = NULL 55 | ) { 56 | assert_is_meta(.meta) 57 | 58 | general <- list( 59 | application_name = application_name, 60 | theme_color = theme_color, 61 | description = description, 62 | robots = robots %??% collapse(robots, ","), 63 | generator = generator, 64 | subject = subject, 65 | rating = rating, 66 | referrer = referrer 67 | ) 68 | 69 | meta_general <- 70 | general %>% 71 | names_replace_underscore("-") %>% 72 | collapse_single_string() %>% 73 | tag_meta_list() 74 | 75 | append_to_meta(.meta, meta_general) 76 | } 77 | 78 | 79 | #' @rdname meta_general 80 | #' @export 81 | meta_description <- function(.meta = meta(), description) { 82 | meta_general(.meta, description = description) 83 | } 84 | 85 | #' @rdname meta_general 86 | #' @export 87 | meta_subject <- function(.meta = meta(), subject) { 88 | meta_general(.meta, subject = subject) 89 | } 90 | 91 | 92 | #' @rdname meta_general 93 | #' @export 94 | meta_referrer <- function(.meta = meta(), referrer) { 95 | meta_general(.meta, referrer = referrer) 96 | } 97 | 98 | #' @rdname meta_general 99 | #' @export 100 | meta_robots <- function(.meta = meta(), robots) { 101 | meta_general(.meta, robots = robots) 102 | } 103 | 104 | #' @rdname meta_general 105 | #' @export 106 | meta_theme_color <- function(.meta = meta(), theme_color) { 107 | meta_general(.meta, theme_color = theme_color) 108 | } 109 | -------------------------------------------------------------------------------- /R/geo.R: -------------------------------------------------------------------------------- 1 | 2 | #' Geotagging Metadata Tags 3 | #' 4 | #' @template describe-meta 5 | #' @param icbm Latitude and longitude of geographic positions specified as 6 | #' `"lat, long"`. Can optionally be a length-two vector, i.e. `c(lat, long)`. 7 | #' @param geo_position Latitude and longitude of geographic positions specified 8 | #' as `"lat;long"`. Can optionally be a length-two vector, i.e. `c(lat, 9 | #' long)`. 10 | #' @param geo_region Name of the geographic region related to the page content, 11 | #' specified using [ISO-3166](https://en.wikipedia.org/wiki/ISO_3166) 12 | #' 2-character country code and 2-character national subdivision. Example: 13 | #' `"US-NY"`. 14 | #' @param geo_placename Name of the geographic place related to the page 15 | #' content. Example: `"Atlanta, Georgia"`. 16 | #' @param ... Additional geotagging metadata keyword and value pairs, such as 17 | #' `geo.country`, `geo.a1`, ..., `geo.a3`, etc. Underscores in the keyword 18 | #' will be converted to periods, so you can also specify `geo_country` in 19 | #' place of `geo.country`. 20 | #' 21 | #' @references 22 | #' [ICBM on Wikipedia](https://en.wikipedia.org/wiki/ICBM_address#Modern_use), 23 | #' [Geotagging on Wikipedia](https://en.wikipedia.org/wiki/Geotagging#HTML_pages) 24 | #' 25 | #' @template describe-meta-return 26 | #' @examples 27 | #' meta() %>% 28 | #' meta_geo( 29 | #' icbm = c(50.167958, -97.133185), 30 | #' geo_position = c(50.167958, -97.133185), 31 | #' geo_placename = "Manitoba, Canada", 32 | #' geo_region = "ca-mb" 33 | #' ) 34 | #' 35 | #' @export 36 | meta_geo <- function( 37 | .meta = meta(), 38 | icbm = NULL, 39 | geo_position = NULL, 40 | geo_region = NULL, 41 | geo_placename = NULL, 42 | ... 43 | ) { 44 | assert_is_meta(.meta) 45 | 46 | geo_values <- list( 47 | ICBM = icbm %??% collapse(icbm), 48 | "geo.position" = geo_position %??% collapse(geo_position, ";"), 49 | "geo.region" = geo_region, 50 | "geo.placename" = geo_placename, 51 | ... 52 | ) 53 | 54 | meta_geo <- 55 | geo_values %>% 56 | names_replace_underscore(".") %>% 57 | collapse_single_string() %>% 58 | tag_meta_list() 59 | 60 | append_to_meta(.meta, meta_geo) 61 | } 62 | -------------------------------------------------------------------------------- /R/google_scholar.R: -------------------------------------------------------------------------------- 1 | #' Add Google Scholar Metadata 2 | #' 3 | #' Add bibliographic metadata to pages in the format expected by Google 4 | #' Scholar. Please reference the 5 | #' [Google Scholar Inclusion](https://scholar.google.com/intl/en/scholar/inclusion.html#indexing) 6 | #' page for the most up-to-date information and instructions. Note that this 7 | #' function adds the `citation_` prefix to all of its arguments; the `title` 8 | #' argument becomes the `citation_title` `` tag. 9 | #' 10 | #' @examples 11 | #' meta_google_scholar( 12 | #' title = c( 13 | #' "The testis isoform of the phosphorylase kinase catalytic subunit (PhK-T)", 14 | #' "plays a critical role in regulation of glycogen mobilization in developing lung" 15 | #' ), 16 | #' author = c( 17 | #' "Liu, Li", 18 | #' "Rannels, Stephen R.", 19 | #' "Falconieri, Mary", 20 | #' "Phillips, Karen S.", 21 | #' "Wolpert, Ellen B.", 22 | #' "Weaver, Timothy E." 23 | #' ), 24 | #' publication_date = "1996/05/17", 25 | #' journal_title = "Journal of Biological Chemistry", 26 | #' volume = 271, 27 | #' issue = 20, 28 | #' firstpage = 11761, 29 | #' lastpage = 11766, 30 | #' pdf_url = "http://www.example.com/content/271/20/11761.full.pdf" 31 | #' ) 32 | #' 33 | #' @template describe-meta 34 | #' @param title The title of the paper. 35 | #' 36 | #' The title tag must contain the title of the paper. Don't use it for the 37 | #' title of the journal or a book in which the paper was published, or for the 38 | #' name of your repository. This tag is required for inclusion in Google 39 | #' Scholar. 40 | #' @param author A vector of author names. 41 | #' 42 | #' The `author` tag, must contain the authors (and only the actual authors) of 43 | #' the paper. Don't use it for the author of the website or for contributors 44 | #' other than authors, e.g., thesis advisors. Author names can be listed 45 | #' either as "Smith, John" or as "John Smith". Put each author name in a 46 | #' separate tag and omit all affiliations, degrees, certifications, etc., from 47 | #' this field. At least one author tag is required for inclusion in Google 48 | #' Scholar. 49 | #' @param publication_date,online_date The date the paper was published in the 50 | #' journal (`publication_date`) or published online (`online_date`). 51 | #' 52 | #' The `publication_date` tag must contain the date of publication, i.e., the 53 | #' date that would normally be cited in references to this paper from other 54 | #' papers. Don't use it for the date of entry into the repository - that 55 | #' should go into `online_date` instead. Provide full dates in the "2010/5/12" 56 | #' format if available; or a year alone otherwise. This tag is required for 57 | #' inclusion in Google Scholar. 58 | #' 59 | #' @param journal_title,conference_title,issn,isbn,volume,issue,firstpage,lastpage 60 | #' For journal and conference papers, provide the remaining bibliographic 61 | #' citation data in the following tags: `journal_title` or `conference_title`, 62 | #' `issn`, `isbn`, `volume`, `issue`, `firstpage`, and `lastpage.` These 63 | #' fields must contain sufficient information to identify a reference to this 64 | #' paper from another document, which is normally all of: (a) journal or 65 | #' conference name, (b) volume and issue numbers, if applicable, and (c) the 66 | #' number of the first page of the paper in the volume (or issue) in question. 67 | #' 68 | #' @param dissertation_institution,technical_report_institution,technical_report_number 69 | #' For theses, dissertations, and technical reports, provide the remaining 70 | #' bibliographic citation data in the following tags: 71 | #' `dissertation_institution`, `technical_report_institution` for the name of 72 | #' the institution and `technical_report_number` for the number of the 73 | #' technical report. As with journal and conference papers, you need to 74 | #' provide sufficient information to recognize a formal citation to this 75 | #' document from another article. 76 | #' 77 | #' @param pdf_url The `` tags normally apply only to the exact page on 78 | #' which they're provided. If this page shows only the abstract of the paper 79 | #' and you have the full text in a separate file, e.g., in the PDF format, 80 | #' please specify the locations of all full text versions using `pdf_url`. The 81 | #' content of the tag is the absolute URL of the PDF file; for security 82 | #' reasons, it must refer to a file in the same subdirectory as the HTML 83 | #' abstract. 84 | #' 85 | #' @template describe-meta-return 86 | #' 87 | #' @references 88 | #' @export 89 | meta_google_scholar <- function( 90 | .meta = meta(), 91 | title, 92 | author, 93 | publication_date, 94 | online_date = NULL, 95 | journal_title = NULL, 96 | conference_title = NULL, 97 | volume = NULL, 98 | issue = NULL, 99 | firstpage = NULL, 100 | lastpage = NULL, 101 | pdf_url = NULL, 102 | issn = NULL, 103 | isbn = NULL, 104 | dissertation_institution = NULL, 105 | technical_report_institution = NULL, 106 | technical_report_number = NULL 107 | ) { 108 | assert_is_meta(.meta) 109 | 110 | assert_valid_google_scholar_date(publication_date) 111 | assert_valid_google_scholar_date(online_date) 112 | 113 | scholar <- list( 114 | title = title, 115 | publication_date = publication_date, 116 | online_date = online_date, 117 | journal_title = journal_title, 118 | conference_title = conference_title, 119 | volume = volume, 120 | issue = issue, 121 | firstpage = firstpage, 122 | lastpage = lastpage, 123 | pdf_url = pdf_url, 124 | issn = issn, 125 | isbn = isbn, 126 | dissertation_institution = dissertation_institution, 127 | technical_report_institution = technical_report_institution, 128 | technical_report_number = technical_report_number 129 | ) 130 | names(scholar) <- paste0("citation_", names(scholar)) 131 | 132 | for (aut in rev(author)) { 133 | scholar <- purrr::prepend(scholar, list(citation_author = aut)) 134 | } 135 | idx_title <- which(names(scholar) == "citation_title") 136 | scholar <- c(scholar[idx_title], scholar[-idx_title]) 137 | 138 | meta_scholar <- 139 | scholar %>% 140 | purrr::compact() %>% 141 | collapse_single_string() %>% 142 | purrr::imap(~ tag_meta(name = .y, content = .x)) %>% 143 | unname() 144 | 145 | append_to_meta(.meta, meta_scholar) 146 | } 147 | 148 | assert_valid_google_scholar_date <- function(x) { 149 | if (is.null(x)) return() 150 | x_name <- deparse(substitute(x)) 151 | x <- as.character(x) 152 | 153 | if (length(x) > 1) { 154 | stop("`", x_name, "` must be a single value.", call. = FALSE) 155 | } 156 | 157 | valid_date_fmt <- "^\\d{4}(/\\d{1,2}/\\d{1,2})?$" 158 | 159 | if (!grepl(valid_date_fmt, x)) { 160 | stop("`", x_name, "` must be in YYYY or YYYY/MM/DD format.", call. = FALSE) 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /R/meta.R: -------------------------------------------------------------------------------- 1 | #' Initialize a List of HTML Metadata Tags 2 | #' 3 | #' Initialize a _metathis_ object (i.e. a list of HTML metadata tags), test if 4 | #' an object is a _metathis_ object, or coerce a list of `meta` tags to be a 5 | #' _metathis_ object. 6 | #' 7 | #' @template describe-meta-return 8 | #' 9 | #' @export 10 | meta <- function() { 11 | as_meta(list()) 12 | } 13 | 14 | #' Include Metadata Tags in HTML Document 15 | #' 16 | #' Use `include_meta()` to explicitly declare the [meta()] tags as an HTML 17 | #' dependency. In general, this is not required when knitting to an HTML 18 | #' document. This function explicitly attaches an [htmltools::htmlDependency()] 19 | #' and may work in some unusual cases. 20 | #' 21 | #' @template describe-meta 22 | #' @return An [htmltools::htmlDependency()] containing the metadata tags to be 23 | #' included in the `` of the HTML document. 24 | #' 25 | #' @family meta_actions 26 | #' 27 | #' @examples 28 | #' meta() %>% 29 | #' meta_name("github-repo" = "gadenbuie/metathis") %>% 30 | #' include_meta() 31 | #' 32 | #' @export 33 | include_meta <- function(.meta) { 34 | assert_is_meta(.meta) 35 | 36 | htmltools::tagList(metaDependency(.meta)) 37 | } 38 | 39 | 40 | #' Create name/content metadata tag pairs 41 | #' 42 | #' Creates metadata tag pairs where the arguments are the name values and their 43 | #' values are content values. 44 | #' 45 | #' @template describe-meta 46 | #' @param ... Name (argument names) and content (argument value) pairs. 47 | #' @examples 48 | #' meta() %>% 49 | #' meta_name("github-repo" = "hadley/r4ds") 50 | #' 51 | #' @template describe-meta-return 52 | #' @export 53 | meta_name <- function(.meta = meta(), ...) { 54 | assert_is_meta(.meta) 55 | 56 | name_meta <- list(...) %>% 57 | collapse_single_string() %>% 58 | tag_meta_list() 59 | 60 | append_to_meta(.meta, name_meta) 61 | } 62 | 63 | #' Create a metadata tag for attribute/value pairs 64 | #' 65 | #' Creates a `` tag for attribute value pairs, where argument names 66 | #' correspond to attribute names. 67 | #' 68 | #' @template describe-meta 69 | #' @param ... Attribute names and values as `attribute = value`. Values must be 70 | #' a single character string. 71 | #' @examples 72 | #' meta() %>% 73 | #' meta_tag( 74 | #' "http-equiv" = "Content-Security-Policy", 75 | #' content = "default-src 'self'" 76 | #' ) 77 | #' 78 | #' @template describe-meta-return 79 | #' @export 80 | meta_tag <- function(.meta = meta(), ...) { 81 | assert_is_meta(.meta) 82 | attrs <- list(...) 83 | 84 | len_gt_1 <- purrr::keep(attrs, ~ length(.) > 1) 85 | if (length(len_gt_1)) { 86 | stop( 87 | "All values must be length 1: '", 88 | paste0(names(len_gt_1), collapse = "', '"), 89 | "'" 90 | ) 91 | } 92 | 93 | append_to_meta(.meta, list(tag_meta(...))) 94 | } 95 | 96 | #' @describeIn meta Test if an objects is a _metathis_ object 97 | #' @examples 98 | #' meta() %>% 99 | #' meta_viewport() %>% 100 | #' is_meta() 101 | #' 102 | #' @export 103 | is_meta <- function(x) { 104 | inherits(x, "meta") 105 | } 106 | 107 | assert_is_meta <- function(x, var = ".meta") { 108 | if (!is_meta(x)) { 109 | stop("`", var, "` must be a meta object from meta() or as_meta()") 110 | } else { 111 | invisible(TRUE) 112 | } 113 | } 114 | 115 | #' @describeIn meta Convert a list of meta tags into a _metathis_ object. 116 | #' 117 | #' @param x A list or metathis object 118 | #' 119 | #' @examples 120 | #' list_of_meta_tags <- list( 121 | #' htmltools::tags$meta(github = "gadenbuie"), 122 | #' htmltools::tags$meta(twitter = "grrrck") 123 | #' ) 124 | #' 125 | #' as_meta(list_of_meta_tags) 126 | #' @export 127 | as_meta <- function(x) UseMethod("as_meta", x) 128 | 129 | #' @export 130 | as_meta.list <- function(x) { 131 | head <- htmltools::tags$head() 132 | head$children <- x 133 | structure(list(head), class = c("meta", "shiny.tag.list", "list")) 134 | } 135 | 136 | #' @export 137 | as_meta.default <- function(x) { 138 | x_class <- paste(class(x), collapse = ", ") 139 | stop( 140 | "I don't know how to convert an object of class '", 141 | x_class, 142 | "' into a list of tags" 143 | ) 144 | } 145 | 146 | #' @export 147 | as_meta.data.frame <- function(x) { 148 | NextMethod() 149 | } 150 | 151 | #' @export 152 | as.character.meta <- function(x, ...) { 153 | x[[1]]$children %>% purrr::map_chr(as.character) 154 | } 155 | 156 | #' @export 157 | format.meta <- function(x, ...) { 158 | collapse(as.character(x), "\n") 159 | } 160 | 161 | #' @export 162 | print.meta <- function(x, ...) { 163 | cat(format(x)) 164 | } 165 | 166 | #' @export 167 | knit_print.meta <- function(x, ...) { 168 | .meta <- x 169 | assert_is_meta(.meta) 170 | 171 | # nocov start 172 | if (!grepl("html", knitr::opts_knit$get("rmarkdown.pandoc.to"))) { 173 | warning( 174 | "knitr output format is not HTML. Use `include_meta()` to ensure ", 175 | "that the tags are properly included in the output ", 176 | "(if possible).", 177 | call. = FALSE 178 | ) 179 | } 180 | 181 | if (guess_blogdown()) { 182 | warning( 183 | "{metathis} can't directly include tags inside blogdown posts ", 184 | "because the mechanism for including tags in the section of a ", 185 | "page depends on the Hugo template. ", 186 | "If you see this message but are not rendering a blogdown post, you can ", 187 | "use metathis::include_meta() to avoid this check. ", 188 | "See ?meta for more information.", 189 | call. = FALSE 190 | ) 191 | return(collapse(.meta, "\n")) 192 | } 193 | #nocov end 194 | 195 | # Thank you: https://github.com/haozhu233/kableExtra/blob/master/R/print.R#L56 196 | knitr::asis_output("", meta = list(metaDependency(.meta))) 197 | } 198 | 199 | append_to_meta <- function(.meta, .list = NULL) { 200 | assert_is_meta(.meta) 201 | .meta[[1]]$children <- append(.meta[[1]]$children, .list) 202 | .meta 203 | } 204 | 205 | prepend_to_meta <- function(.meta, .list = NULL) { 206 | assert_is_meta(.meta) 207 | .meta[[1]]$children <- purrr::prepend(.meta[[1]]$children, .list) 208 | .meta 209 | } 210 | 211 | metaDependency <- function(.meta) { 212 | assert_is_meta(.meta) 213 | 214 | src <- if (has_package_version("rmarkdown", "2.9")) { 215 | c(href = "/") 216 | } else { 217 | system.file(package = "metathis") 218 | } 219 | 220 | htmltools::htmlDependency( 221 | paste0("metathis", "-", random_id()), 222 | version = METATHIS_VERSION, 223 | src = src, 224 | all_files = FALSE, 225 | head = .meta %>% paste() 226 | ) 227 | } 228 | 229 | random_id <- function(n = 6) { 230 | c(letters[1:6], 0:9) %>% 231 | sample(8, replace = TRUE) %>% 232 | collapse("") 233 | } 234 | 235 | guess_blogdown <- function() { 236 | blogdown_root <- find_config(getwd()) 237 | if (is.null(blogdown_root)) return(FALSE) 238 | 239 | # Check for blogdown config files and confirm if they contain "baseURL" 240 | config_files <- dir(blogdown_root, "config[.](yaml|toml|json)", full.names = TRUE) 241 | if (length(config_files)) { 242 | for (config in config_files) { 243 | if (grepl("baseURL", collapse(readLines(config, warn = FALSE)))) { 244 | return(TRUE) 245 | } 246 | } 247 | } 248 | 249 | # Check if config file + "content" + "layouts" + "static" 250 | blogdown_files <- dir(blogdown_root, "content|layouts|static") 251 | if (length(blogdown_files) == 3 && length(config_files)) { 252 | return(TRUE) 253 | } 254 | 255 | FALSE 256 | } 257 | 258 | find_config <- function(path) { 259 | if (length(dir(path, "config[.](yaml|toml|json)"))) { 260 | return(path) 261 | } 262 | 263 | path_up <- normalizePath(file.path(path, "..")) 264 | if (path == path_up) return(NULL) 265 | find_config(path_up) 266 | } 267 | 268 | meta_find_description <- function(.meta) { 269 | # check existing metadata for description 270 | has_description <- has_meta_with_property(.meta, value = "description") 271 | if (!any(has_description)) { 272 | return(NULL) 273 | } 274 | 275 | desc_existing <- .meta[[1]]$children %>% 276 | purrr::keep(has_description) %>% 277 | purrr::map_chr(~ .$attribs$content) %>% 278 | unique() 279 | 280 | if (length(desc_existing) > 1) { 281 | warning( 282 | "Multiple existing descriptions were found, using first for ", 283 | "social cards:\n", 284 | strwrap(desc_existing[1], indent = 4) 285 | ) 286 | } 287 | desc_existing[1] 288 | } 289 | -------------------------------------------------------------------------------- /R/metathis-package.R: -------------------------------------------------------------------------------- 1 | #' @importFrom knitr knit_print 2 | #' @keywords internal 3 | "_PACKAGE" 4 | 5 | METATHIS_VERSION <- "1.1.3" 6 | 7 | # The following block is used by usethis to automatically manage 8 | # roxygen namespace tags. Modify with care! 9 | ## usethis namespace: start 10 | ## usethis namespace: end 11 | NULL 12 | -------------------------------------------------------------------------------- /R/social.R: -------------------------------------------------------------------------------- 1 | 2 | #' Social Media Metadata 3 | #' 4 | #' Generate metadata tags for social media cards. 5 | #' 6 | #' @template describe-meta 7 | #' @param title Content title 8 | #' @param description Content description. If you have already used 9 | #' [meta_general()] to set the content's description, that description will 10 | #' automatically be used. 11 | #' @param url Content URL 12 | #' @param image Image url for card. 13 | #' @param image_alt A description of what's in the image (not a caption) 14 | #' @param image_width The width of the image in pixels 15 | #' @param image_height The height of the image in pixels 16 | #' @param og_site_name The name of the site hosting the content 17 | #' @param og_type Open Graph card type, default is `"website"`. Other common 18 | #' options include `"article"`, `"book"`, or `"profile"`. The full list of 19 | #' valid options can be referenced at 20 | #' @param og_locale The locale these tags are marked up in. Of the format `language_TERRITORY`. Default is `"en_US"`. 21 | #' @param og_author Writers of the article. Multiple authors may be specified in 22 | #' a vector of character strings. 23 | #' @param twitter_card_type One of `"summary"`, `"summary_large_image"`, 24 | #' `"app"`, or `"player"`. 25 | #' @param twitter_creator `@username` for the content creator / author. 26 | #' @param twitter_site `@username`` for the website used in the card footer. 27 | #' `twitter_creator` is used by default. 28 | #' @param facebook_app_id The Facebook app ID. See the 29 | #' [Facebook Open Graph Markup](https://developers.facebook.com/docs/sharing/webmasters#markup) 30 | #' page for more information. 31 | #' @param disable_pinterest If `TRUE`, adds a metadata tag disabling pins from 32 | #' your website. See the 33 | #' [Pinterest help center](https://help.pinterest.com/en/business/article/prevent-saves-to-pinterest-from-your-site) 34 | #' for more information. 35 | #' 36 | #' @references 37 | #' - [Open Graph](https://ogp.me/) 38 | #' - [Google Structured Data Testing Tool](https://search.google.com/structured-data/testing-tool) 39 | #' - [Facebook Sharing Debugger](https://developers.facebook.com/tools/debug/) 40 | #' - [Twitter Card Documentation](https://developer.twitter.com/en/docs/twitter-for-websites/cards/guides/getting-started) 41 | #' 42 | #' @template describe-meta-return 43 | #' @examples 44 | #' meta() %>% 45 | #' meta_social( 46 | #' title = "R for Data Science", 47 | #' description = "This book with teach you how to do data science with R", 48 | #' url = "https://r4ds.had.co.nz", 49 | #' image = "https://r4ds.had.co.nz/cover.png", 50 | #' image_alt = "The cover of the R4DS book", 51 | #' og_type = "book", 52 | #' og_author = c("Garrett Grolemund", "Hadley Wickham"), 53 | #' twitter_card_type = "summary", 54 | #' twitter_creator = "@hadley" 55 | #' ) 56 | #' 57 | #' @export 58 | meta_social <- function( 59 | .meta = meta(), 60 | title = NULL, 61 | url = NULL, 62 | image = NULL, 63 | image_alt = NULL, 64 | image_width = NULL, 65 | image_height = NULL, 66 | description = NULL, 67 | twitter_card_type = c("summary", "summary_large_image", "app", "player"), 68 | twitter_creator = NULL, 69 | twitter_site = twitter_creator, 70 | og_type = "website", 71 | og_locale = "en_US", 72 | og_author = NULL, 73 | og_site_name = NULL, 74 | facebook_app_id = NULL, 75 | disable_pinterest = FALSE 76 | ) { 77 | assert_is_meta(.meta) 78 | twitter_card_type <- match.arg(twitter_card_type) 79 | 80 | description <- description %||% meta_find_description(.meta) 81 | 82 | social <- list( 83 | "twitter:title" = title, 84 | "twitter:description" = description, 85 | "twitter:url" = url, 86 | "twitter:image" = image, 87 | "twitter:image:alt" = image_alt, 88 | "twitter:image:width" = image_width, 89 | "twitter:image:height"= image_height, 90 | "twitter:card" = twitter_card_type, 91 | "twitter:creator" = twitter_creator, 92 | "twitter:site" = twitter_site, 93 | "og:title" = title, 94 | "og:description" = description, 95 | "og:url" = url, 96 | "og:image" = image, 97 | "og:image:alt" = image_alt, 98 | "og:image:width" = image_width, 99 | "og:image:height" = image_height, 100 | "og:type" = og_type, 101 | "og:locale" = og_locale, 102 | "og:site_name" = og_site_name, 103 | "article:author" = og_author %??% as.list(og_author), 104 | "fb:app_id" = facebook_app_id 105 | ) 106 | 107 | meta_social <- 108 | social %>% 109 | duplicate_vector_entries() %>% 110 | collapse_single_string() %>% 111 | purrr::imap(function(content, property) { 112 | if (grepl("^twitter:", property)) { 113 | tag_meta(name = property, content = content) 114 | } else { 115 | tag_meta(property = property, content = content) 116 | } 117 | }) %>% 118 | unname() 119 | 120 | if (disable_pinterest) { 121 | meta_social <- c( 122 | meta_social, 123 | list(tag_meta( 124 | name = "pinterest", 125 | content = "nopin", 126 | description = "Sorry, pins from this website are disabled." 127 | )) 128 | ) 129 | } 130 | 131 | append_to_meta(.meta, meta_social) 132 | } 133 | -------------------------------------------------------------------------------- /R/utils-meta.R: -------------------------------------------------------------------------------- 1 | 2 | `%||%` <- function(x, y) if (is.null(x)) y else x 3 | 4 | `%??%` <- function(x, y) if (!is.null(x)) y 5 | 6 | tag_meta <- function(...) htmltools::tag("meta", list(...)) 7 | 8 | tag_meta_list <- function(.list) { 9 | .list %>% 10 | purrr::imap(~ tag_meta(name = .y, content = .x)) %>% 11 | unname() 12 | } 13 | 14 | collapse_single_string <- function(.list, sep = " ") { 15 | .list %>% 16 | purrr::compact() %>% 17 | vapply(collapse, "", sep = sep) 18 | } 19 | 20 | collapse <- function(x, sep = ", ") { 21 | paste(x, collapse = sep) 22 | } 23 | 24 | names_replace_underscore <- function(.list, replace = "-") { 25 | names(.list) <- gsub("_", replace, names(.list)) 26 | .list 27 | } 28 | 29 | duplicate_vector_entries <- function(.list) { 30 | levels <- purrr::map_dbl(.list, purrr::vec_depth) 31 | 32 | if (!any(levels > 1)) { 33 | return(.list) 34 | } 35 | 36 | new_list <- list() 37 | for (i in seq_along(.list)) { 38 | if (levels[i] < 2) { 39 | new_list[[names(.list)[i]]] <- .list[[i]] 40 | next 41 | } 42 | flattened <- purrr::flatten(.list[i]) 43 | names(flattened) <- rep(names(.list)[i], length(flattened)) 44 | new_list <- c(new_list, flattened) 45 | } 46 | new_list 47 | } 48 | 49 | has_meta_with_property <- function(.meta, property = "name", value) { 50 | has_match <- 51 | .meta[[1]]$children %>% 52 | purrr::map("attribs") %>% 53 | purrr::map_lgl(~ { 54 | !is.null(.x[[property]]) && .x[[property]] == value 55 | }) 56 | 57 | has_match 58 | } 59 | -------------------------------------------------------------------------------- /R/utils-pipe.R: -------------------------------------------------------------------------------- 1 | #' Pipe operator 2 | #' 3 | #' See \code{magrittr::\link[magrittr:pipe]{\%>\%}} for details. 4 | #' 5 | #' @name %>% 6 | #' @rdname pipe 7 | #' @keywords internal 8 | #' @export 9 | #' @importFrom magrittr %>% 10 | #' @usage lhs \%>\% rhs 11 | NULL 12 | -------------------------------------------------------------------------------- /R/utils.R: -------------------------------------------------------------------------------- 1 | # nocov start 2 | has_package_version <- function(package, version) { 3 | pkg_v <- packageVersion(package) 4 | if (is.null(pkg_v)) { 5 | return(FALSE) 6 | } 7 | pkg_v >= package_version(version) 8 | } 9 | 10 | packageVersion <- function(package) { 11 | if (!requireNamespace(package, quietly = TRUE)) { 12 | return(NULL) 13 | } 14 | pkg_v <- read.dcf( 15 | system.file("DESCRIPTION", package = package), 16 | fields = "Version" 17 | ) 18 | package_version(pkg_v[[1]]) 19 | } 20 | # nocov end 21 | -------------------------------------------------------------------------------- /R/viewport.R: -------------------------------------------------------------------------------- 1 | #' Viewport Meta Tag 2 | #' 3 | #' Create or add a viewport meta tag. 4 | #' 5 | #' @references 6 | #' [MDN: Viewport Meta Tag](https://developer.mozilla.org/en-US/docs/Web/HTML/Viewport_meta_tag), 7 | #' 8 | #' @template describe-meta 9 | #' @param width Sets the width of initial viewport. `width` sets `min_width` and 10 | #' `max_width` and may contain two values; for example, the following are 11 | #' equivalent: `"300px 500px"` or `c("300px", "500px")`). The values may be 12 | #' a number with units, a percentage, or `"device-width"`. Pixels are assumed 13 | #' if no units are provided. 14 | #' @param min_width,max_width Minimum and maximum initial viewport width. See 15 | #' `width` for more information. `width` is ignored if `min_width` or 16 | #' `max_width` are set. 17 | #' @param height,min_height,max_height Sets height of initial viewport. Follows 18 | #' the same conventions as `width`, `min_width`, and `max_width`. 19 | #' @param initial_scale Initial scale 20 | #' @param orientation One of `"auto"`, `"portrait"`, `"landscape"`. 21 | #' @param minimum_scale Minimum scale 22 | #' @param maximum_scale Maximum scale 23 | #' @param user_scalable User scalable 24 | #' @param ... Additional name/value pairs 25 | #' 26 | #' @examples 27 | #' meta() %>% 28 | #' meta_viewport() 29 | #' 30 | #' meta() %>% 31 | #' meta_viewport(orientation = NULL) 32 | #' 33 | #' meta() %>% 34 | #' meta_viewport(maximum_scale = 1) 35 | #' 36 | #' @template describe-meta-return 37 | #' @export 38 | meta_viewport <- function( 39 | .meta = meta(), 40 | width = "device-width", 41 | initial_scale = "1", 42 | orientation = c("auto", "portrait", "landscape"), 43 | min_width = NULL, 44 | max_width = NULL, 45 | height = NULL, 46 | min_height = NULL, 47 | max_height = NULL, 48 | minimum_scale = NULL, 49 | maximum_scale = NULL, 50 | user_scalable = NULL, 51 | ... 52 | ) { 53 | 54 | assert_is_meta(.meta) 55 | 56 | has_minmax_width <- purrr::some(list(min_width, max_width), purrr::negate(is.null)) 57 | has_minmax_height <- purrr::some(list(min_height, max_height), purrr::negate(is.null)) 58 | 59 | if (has_minmax_width && !is.null(width)) { 60 | warning("Ignoring `width` because one of `min_width` or `max_width` was provided") 61 | width <- NULL 62 | } 63 | 64 | if (has_minmax_height && !is.null(height)) { 65 | warning("Ignoring `height` because one of `min_height` or `max_height` was provided") 66 | height <- NULL 67 | } 68 | 69 | orientation <- orientation %??% match.arg(orientation) 70 | 71 | content <- c( 72 | width = if (is.null(min_width) && is.null(max_width)) width, 73 | "initial-scale" = initial_scale, 74 | orientation = orientation, 75 | "minimum-scale" = minimum_scale, 76 | "maximum-scale" = maximum_scale, 77 | "user-scalable" = user_scalable, 78 | "min-width" = min_width, 79 | "max-width" = max_width, 80 | height = if (is.null(min_height) && is.null(max_height)) height, 81 | "min-height" = min_height, 82 | "max-height" = max_height, 83 | ... 84 | ) 85 | 86 | content <- paste(names(content), content, sep = "=", collapse = ", ") 87 | 88 | if (!nzchar(content)) { 89 | stop("At least one argument must be provided") 90 | } 91 | 92 | # viewport tag has to come first in list of meta tags 93 | meta_new <- tag_meta(name = "viewport", content = content) 94 | 95 | prepend_to_meta(.meta, list(meta_new)) 96 | } 97 | -------------------------------------------------------------------------------- /R/write.R: -------------------------------------------------------------------------------- 1 | #' Write Metadata Tags to a File 2 | #' 3 | #' Write your metadata tags to an HTML file that can be manually included in 4 | #' your page. 5 | #' 6 | #' @template describe-meta 7 | #' @param path The file to write into, defaults to `"meta.html"`. 8 | #' @inheritParams base::cat 9 | #' 10 | #' @return Returns `.meta` invisibly. 11 | #' 12 | #' @family meta_actions 13 | #' 14 | #' @examples 15 | #' meta_html_snippet <- tempfile("metathis_example", fileext = ".html") 16 | #' 17 | #' meta() %>% 18 | #' meta_name("package" = "metathis") %>% 19 | #' write_meta(meta_html_snippet) 20 | #' 21 | #' readLines(meta_html_snippet, warn = FALSE) 22 | #' 23 | #' @export 24 | write_meta <- function(.meta, path = "meta.html", append = FALSE) { 25 | .meta %>% 26 | as.character() %>% 27 | cat(file = path, sep = "\n", append = append) 28 | 29 | invisible(.meta) 30 | } 31 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: github_document 3 | always_allow_html: yes 4 | --- 5 | 6 | 7 | 8 | ```{r, include = FALSE} 9 | knitr::opts_chunk$set( 10 | collapse = TRUE, 11 | comment = "#>", 12 | fig.path = "man/figures/README-", 13 | out.width = "100%" 14 | ) 15 | ``` 16 | 17 | # metathis 18 | 19 | 20 | [![CRAN status](https://www.r-pkg.org/badges/version/metathis)](https://CRAN.R-project.org/package=metathis) 21 | [![metathis status badge](https://gadenbuie.r-universe.dev/badges/metathis)](https://gadenbuie.r-universe.dev/metathis) 22 | [![Lifecycle: stable](https://img.shields.io/badge/lifecycle-stable-brightgreen.svg)](https://lifecycle.r-lib.org/articles/stages.html) 23 | [![R-CMD-check](https://github.com/gadenbuie/metathis/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/gadenbuie/metathis/actions/workflows/R-CMD-check.yaml) 24 | [![Codecov](https://img.shields.io/codecov/c/github/gadenbuie/metathis)](https://app.codecov.io/github/gadenbuie/metathis) 25 | 26 | 27 | [rmarkdown]: https://rmarkdown.rstudio.com 28 | [blogdown]: https://bookdown.org/yihui/blogdown 29 | [Shiny]: https://shiny.posit.co/ 30 | [r4ds]: https://r4ds.had.co.nz/ 31 | [xaringan]: https://slides.yihui.org/xaringan 32 | [bookdown]: https://bookdown.org/ 33 | [pagedown]: https://github.com/rstudio/pagedown 34 | [htmltools]: https://github.com/rstudio/htmltools 35 | [pkgdown]: https://pkgdown.r-lib.org 36 | 37 | ## Why metathis? 38 | 39 | The goal of **metathis** is to help you add HTML `` tags to your [R Markdown][rmarkdown] and [Shiny] apps. 40 | 41 | HTML `` tags provide browsers and social media with metadata about HTML pages. 42 | Using `` tags will help your users find your articles, Shiny apps, and presentations, and will help you make sure they look great in social media timelines. 43 | 44 | **metathis** makes the process of adding these tags to your R Markdown pages and Shiny apps easier by using the [htmltools] package to add `` tags as a dependency, added directly to the document in an R code chunk or your Shiny app UI rather than requiring you to adjust templates or write additional files. 45 | 46 | If you want great looking social media cards, the [`meta_social()`](http://pkg.garrickadenbuie.com/metathis/reference/meta_social.html) function will help you add everything you need for Twitter, Facebook and other social media sites that support the Open Graph protocol. 47 | 48 | ## Installation 49 | 50 | You can install the latest version of metathis from [CRAN](https://CRAN.R-project.org) with: 51 | 52 | ``` r 53 | # CRAN 54 | install.packages("metathis") 55 | ``` 56 | 57 | And the development version from [Github](https://github.com/gadenbuie/metathis) or [r-universe](https://gadenbuie.r-universe.dev/builds) with: 58 | 59 | ``` r 60 | # r-universe 61 | install.packages("metathis", repos = "https://gadenbuie.r-universe.dev") 62 | 63 | # install.packages("devtools") 64 | devtools::install_github("gadenbuie/metathis@main") 65 | ``` 66 | 67 | ## Works In 68 | 69 | ✅ [R Markdown][rmarkdown] HTML Documents 70 | ✅ [Shiny] Apps 71 | ✅ [xaringan] 72 | ✅ [pagedown] 73 | ✅ [bookdown] 74 | ❌ [blogdown]1 75 | ❌ [pkgdown] 76 | 77 | `` tags can be added to ✅ packages with a standard R chunk 78 | 79 | ````markdown 80 | ```{r, echo=FALSE}`r ''` 81 | meta() %>% 82 | meta_description("My awesome presentation") 83 | ``` 84 | ```` 85 | 86 | For other packages or situations, you can use `include_meta()` to explicitly declare the meta tags as an html dependency or use `write_meta()` to save the `` tags to an `.html` file that can be included via `includes: in_header`. 87 | (In blogdown, consult your blogdown/hugo theme for the correct inclusion method.) 88 | 89 | ````markdown 90 | ```{r blogdown-meta, echo = FALSE}`r ''` 91 | meta() %>% 92 | meta_description("A fantastic blog post") %>% 93 | write_meta("meta.html") 94 | ``` 95 | ```` 96 | 97 | ## Example 98 | 99 | ### In R Markdown 100 | 101 | This is a basic example that re-creates the `` tags for the [R for Data Science][r4ds] book. 102 | 103 | ```{r library} 104 | library(metathis) 105 | ``` 106 | 107 | ```{r example, eval=FALSE} 108 | meta() %>% 109 | meta_description( 110 | "This book will teach you how to do data science with R..." 111 | ) %>% 112 | meta_name("github-repo" = "hadley/r4ds") %>% 113 | meta_viewport() %>% 114 | meta_social( 115 | title = "R for Data Science", 116 | url = "https://r4ds.had.co.nz", 117 | image = "https://r4ds.had.co.nz/cover.png", 118 | image_alt = "The cover of the R4DS book", 119 | og_type = "book", 120 | og_author = c("Garrett Grolemund", "Hadley Wickham"), 121 | twitter_card_type = "summary", 122 | twitter_creator = "@hadley" 123 | ) 124 | ``` 125 | 126 | ```{r example-print, echo=FALSE} 127 | x <- 128 | <> 129 | 130 | print(x) 131 | ``` 132 | 133 | ### In Shiny Apps 134 | 135 | To use `metathis` in Shiny apps, 136 | simply call `meta()` and related tags anywhere inside your page UI, 137 | for example inside `fluidPage()`. 138 | 139 | ```r 140 | ui <- fluidPage( 141 | # Application title 142 | titlePanel("metathis Example"), 143 | 144 | meta() %>% 145 | meta_social( 146 | title = "metathis", 147 | description = " and social media cards for web things in R", 148 | url = "https://pkg.garrickadenbuie.com/metathis", 149 | image = "https://garrickadenbuie.com/apple-touch-icon-114x114.png", 150 | image_alt = "An image for social meda cards", 151 | twitter_creator = "@grrrck", 152 | twitter_card_type = "summary", 153 | twitter_site = "@grrrck" 154 | ) 155 | # ... your UI ... 156 | ) 157 | ``` 158 | 159 | ### In xaringan Slides 160 | 161 | To use `metathis` in [xaringan] slides, 162 | add `meta()` and related tags in a chunk anywhere in your slide's source `.Rmd` file. 163 | This example is from a [presentation on the drake package](https://pkg.garrickadenbuie.com/drake-intro/). 164 | 165 | ````markdown 166 | ```{r meta, echo=FALSE}`r ''` 167 | library(metathis) 168 | meta() %>% 169 | meta_general( 170 | description = "A gentle introduction to reproducible data workflows with the {drake} package.", 171 | generator = "xaringan and remark.js" 172 | ) %>% 173 | meta_name("github-repo" = "gadenbuie/drake-intro") %>% 174 | meta_social( 175 | title = "Reproducible Data Workflows With Drake", 176 | url = "https://pkg.garrickadenbuie.com/drake-intro", 177 | image = "https://pkg.garrickadenbuie.com/drake-intro/assets/images/drake-intro-cover.jpg", 178 | image_alt = "The first slide of the Reproducible Data Workflows with drake presentation, featuring the drake hex logo and neatly ordered row of items on a desk (eraser, pencil, coffee cup, paperclips).", 179 | og_type = "website", 180 | og_author = "Garrick Aden-Buie", 181 | twitter_card_type = "summary_large_image", 182 | twitter_creator = "@grrrck" 183 | ) 184 | ``` 185 | ```` 186 | 187 | 188 | ## Thanks 189 | 190 | Thanks to [Josh Buchea](https://github.com/joshbuchea) for providing an [excellent and indispensable resource](https://github.com/joshbuchea/HEAD) on `` tags and other things that go in the HTML `` tags. 191 | 192 | Thanks also to [Malcolm Barret](https://github.com/malcolmbarrett). 193 | Watching over his shoulder as he developed [ymlthis](https://ymlthis.r-lib.org) made putting this package together so much easier. 194 | 195 | Finally, thanks to the [RStudio team](https://github.com/rstudio) and others who developed [htmltools](https://github.com/rstudio/htmltools) for making HTML in R a breeze. 196 | 197 | ```{r, echo=FALSE, warning=FALSE} 198 | meta() %>% 199 | meta_description( 200 | " and social media cards for web things inR" 201 | ) %>% 202 | meta_name("github-repo" = "gadenbuie/metathis") %>% 203 | meta_social( 204 | title = "{metathis}", 205 | url = "https://pkg.garrickadenbuie.com/metathis", 206 | image = "https://pkg.garrickadenbuie.com/metathis/reference/figures/card.png", 207 | image_alt = "many tags and the name of the R package: ", 208 | og_author = c("Garrick Aden-Buie"), 209 | twitter_card_type = "summary", 210 | twitter_creator = "@grrrck" 211 | ) %>% 212 | include_meta() 213 | ``` 214 | 215 | --- 216 | 217 | ### Notes 218 | 219 | 1. For adding meta tags to blogdown sites, [Socialize your blogdown by Xavier A](https://xvrdm.github.io/2017/10/23/socialize-your-blogdown/) is an excellent resource and you can use metathis to help discover the tags you need while following the instructions in the article. 220 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # metathis 5 | 6 | 7 | 8 | [![CRAN 9 | status](https://www.r-pkg.org/badges/version/metathis)](https://CRAN.R-project.org/package=metathis) 10 | [![metathis status 11 | badge](https://gadenbuie.r-universe.dev/badges/metathis)](https://gadenbuie.r-universe.dev/metathis) 12 | [![Lifecycle: 13 | stable](https://img.shields.io/badge/lifecycle-stable-brightgreen.svg)](https://lifecycle.r-lib.org/articles/stages.html) 14 | [![R-CMD-check](https://github.com/gadenbuie/metathis/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/gadenbuie/metathis/actions/workflows/R-CMD-check.yaml) 15 | [![Codecov](https://img.shields.io/codecov/c/github/gadenbuie/metathis)](https://app.codecov.io/github/gadenbuie/metathis) 16 | 17 | 18 | ## Why metathis? 19 | 20 | The goal of **metathis** is to help you add HTML `` tags to your 21 | [R Markdown](https://rmarkdown.rstudio.com) and 22 | [Shiny](https://shiny.posit.co/) apps. 23 | 24 | HTML `` tags provide browsers and social media with metadata about 25 | HTML pages. Using `` tags will help your users find your articles, 26 | Shiny apps, and presentations, and will help you make sure they look 27 | great in social media timelines. 28 | 29 | **metathis** makes the process of adding these tags to your R Markdown 30 | pages and Shiny apps easier by using the 31 | [htmltools](https://github.com/rstudio/htmltools) package to add 32 | `` tags as a dependency, added directly to the document in an R 33 | code chunk or your Shiny app UI rather than requiring you to adjust 34 | templates or write additional files. 35 | 36 | If you want great looking social media cards, the 37 | [`meta_social()`](http://pkg.garrickadenbuie.com/metathis/reference/meta_social.html) 38 | function will help you add everything you need for Twitter, Facebook and 39 | other social media sites that support the Open Graph protocol. 40 | 41 | ## Installation 42 | 43 | You can install the latest version of metathis from 44 | [CRAN](https://CRAN.R-project.org) with: 45 | 46 | ``` r 47 | # CRAN 48 | install.packages("metathis") 49 | ``` 50 | 51 | And the development version from 52 | [Github](https://github.com/gadenbuie/metathis) or 53 | [r-universe](https://gadenbuie.r-universe.dev/builds) with: 54 | 55 | ``` r 56 | # r-universe 57 | install.packages("metathis", repos = "https://gadenbuie.r-universe.dev") 58 | 59 | # install.packages("devtools") 60 | devtools::install_github("gadenbuie/metathis@main") 61 | ``` 62 | 63 | ## Works In 64 | 65 | ✅ [R Markdown](https://rmarkdown.rstudio.com) HTML Documents 66 | ✅ [Shiny](https://shiny.posit.co/) Apps 67 | ✅ [xaringan](https://slides.yihui.org/xaringan) 68 | ✅ [pagedown](https://github.com/rstudio/pagedown) 69 | ✅ [bookdown](https://bookdown.org/) 70 | ❌ [blogdown](https://bookdown.org/yihui/blogdown)1 71 | ❌ [pkgdown](https://pkgdown.r-lib.org) 72 | 73 | `` tags can be added to ✅ packages with a standard R chunk 74 | 75 | ```` markdown 76 | ```{r, echo=FALSE} 77 | meta() %>% 78 | meta_description("My awesome presentation") 79 | ``` 80 | ```` 81 | 82 | For other packages or situations, you can use `include_meta()` to 83 | explicitly declare the meta tags as an html dependency or use 84 | `write_meta()` to save the `` tags to an `.html` file that can be 85 | included via `includes: in_header`. (In blogdown, consult your 86 | blogdown/hugo theme for the correct inclusion method.) 87 | 88 | ```` markdown 89 | ```{r blogdown-meta, echo = FALSE} 90 | meta() %>% 91 | meta_description("A fantastic blog post") %>% 92 | write_meta("meta.html") 93 | ``` 94 | ```` 95 | 96 | ## Example 97 | 98 | ### In R Markdown 99 | 100 | This is a basic example that re-creates the `` tags for the [R for 101 | Data Science](https://r4ds.had.co.nz/) book. 102 | 103 | ``` r 104 | library(metathis) 105 | ``` 106 | 107 | ``` r 108 | meta() %>% 109 | meta_description( 110 | "This book will teach you how to do data science with R..." 111 | ) %>% 112 | meta_name("github-repo" = "hadley/r4ds") %>% 113 | meta_viewport() %>% 114 | meta_social( 115 | title = "R for Data Science", 116 | url = "https://r4ds.had.co.nz", 117 | image = "https://r4ds.had.co.nz/cover.png", 118 | image_alt = "The cover of the R4DS book", 119 | og_type = "book", 120 | og_author = c("Garrett Grolemund", "Hadley Wickham"), 121 | twitter_card_type = "summary", 122 | twitter_creator = "@hadley" 123 | ) 124 | ``` 125 | 126 | #> 127 | #> 128 | #> 129 | #> 130 | #> 131 | #> 132 | #> 133 | #> 134 | #> 135 | #> 136 | #> 137 | #> 138 | #> 139 | #> 140 | #> 141 | #> 142 | #> 143 | #> 144 | #> 145 | #> 146 | 147 | ### In Shiny Apps 148 | 149 | To use `metathis` in Shiny apps, simply call `meta()` and related tags 150 | anywhere inside your page UI, for example inside `fluidPage()`. 151 | 152 | ``` r 153 | ui <- fluidPage( 154 | # Application title 155 | titlePanel("metathis Example"), 156 | 157 | meta() %>% 158 | meta_social( 159 | title = "metathis", 160 | description = " and social media cards for web things in R", 161 | url = "https://pkg.garrickadenbuie.com/metathis", 162 | image = "https://garrickadenbuie.com/apple-touch-icon-114x114.png", 163 | image_alt = "An image for social meda cards", 164 | twitter_creator = "@grrrck", 165 | twitter_card_type = "summary", 166 | twitter_site = "@grrrck" 167 | ) 168 | # ... your UI ... 169 | ) 170 | ``` 171 | 172 | ### In xaringan Slides 173 | 174 | To use `metathis` in [xaringan](https://slides.yihui.org/xaringan) 175 | slides, add `meta()` and related tags in a chunk anywhere in your 176 | slide’s source `.Rmd` file. This example is from a [presentation on the 177 | drake package](https://pkg.garrickadenbuie.com/drake-intro/). 178 | 179 | ```` markdown 180 | ```{r meta, echo=FALSE} 181 | library(metathis) 182 | meta() %>% 183 | meta_general( 184 | description = "A gentle introduction to reproducible data workflows with the {drake} package.", 185 | generator = "xaringan and remark.js" 186 | ) %>% 187 | meta_name("github-repo" = "gadenbuie/drake-intro") %>% 188 | meta_social( 189 | title = "Reproducible Data Workflows With Drake", 190 | url = "https://pkg.garrickadenbuie.com/drake-intro", 191 | image = "https://pkg.garrickadenbuie.com/drake-intro/assets/images/drake-intro-cover.jpg", 192 | image_alt = "The first slide of the Reproducible Data Workflows with drake presentation, featuring the drake hex logo and neatly ordered row of items on a desk (eraser, pencil, coffee cup, paperclips).", 193 | og_type = "website", 194 | og_author = "Garrick Aden-Buie", 195 | twitter_card_type = "summary_large_image", 196 | twitter_creator = "@grrrck" 197 | ) 198 | ``` 199 | ```` 200 | 201 | ## Thanks 202 | 203 | Thanks to [Josh Buchea](https://github.com/joshbuchea) for providing an 204 | [excellent and indispensable 205 | resource](https://github.com/joshbuchea/HEAD) on `` tags and other 206 | things that go in the HTML `` tags. 207 | 208 | Thanks also to [Malcolm Barret](https://github.com/malcolmbarrett). 209 | Watching over his shoulder as he developed 210 | [ymlthis](https://ymlthis.r-lib.org) made putting this package together 211 | so much easier. 212 | 213 | Finally, thanks to the [RStudio team](https://github.com/rstudio) and 214 | others who developed [htmltools](https://github.com/rstudio/htmltools) 215 | for making HTML in R a breeze. 216 | 217 | ------------------------------------------------------------------------ 218 | 219 | ### Notes 220 | 221 | 1. For adding meta tags to blogdown sites, [Socialize your blogdown by 222 | Xavier 223 | A](https://xvrdm.github.io/2017/10/23/socialize-your-blogdown/) is 224 | an excellent resource and you can use metathis to help discover the 225 | tags you need while following the instructions in the article. 226 | -------------------------------------------------------------------------------- /cran-comments.md: -------------------------------------------------------------------------------- 1 | ## R CMD check results 2 | 3 | 0 errors | 0 warnings | 0 note 4 | 5 | This is a maintenance release to correct 6 | a numeric package version as requested by CRAN. 7 | -------------------------------------------------------------------------------- /inst/WORDLIST: -------------------------------------------------------------------------------- 1 | Barret 2 | blogdown 3 | bookdown 4 | Buchea 5 | Buie 6 | Dreamweaver 7 | flexdashboard 8 | geotagging 9 | Geotagging 10 | Github 11 | htmltools 12 | hugo 13 | Lifecycle 14 | MDN 15 | ORCID 16 | pagedown 17 | Pinterest 18 | pkgdown 19 | rmarkdown 20 | RStudio 21 | scalable 22 | travis 23 | UI 24 | Validator 25 | xaringan 26 | ymlthis 27 | -------------------------------------------------------------------------------- /man-roxygen/describe-meta-return.R: -------------------------------------------------------------------------------- 1 | #' @return A `meta` object, or a set of `` HTML tags inside an HTML 2 | #' `` tag. For use in [rmarkdown::html_document()], [shiny::runApp()], 3 | #' or other HTML locations. 4 | #' 5 | #' @family meta 6 | #' 7 | #' @md 8 | -------------------------------------------------------------------------------- /man-roxygen/describe-meta.R: -------------------------------------------------------------------------------- 1 | #' @param .meta A `meta` object created by [meta()] or [as_meta()], or returned 2 | #' by a `meta_*()` object. 3 | #' 4 | #' @md 5 | -------------------------------------------------------------------------------- /man/figures/card.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gadenbuie/metathis/5fcb4c6320d33e75e94c4f15c4d3d0314f824f17/man/figures/card.png -------------------------------------------------------------------------------- /man/figures/card.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | <meta        ><meta this><meta        ><meta        ><meta        > -------------------------------------------------------------------------------- /man/figures/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gadenbuie/metathis/5fcb4c6320d33e75e94c4f15c4d3d0314f824f17/man/figures/logo.png -------------------------------------------------------------------------------- /man/include_meta.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/meta.R 3 | \name{include_meta} 4 | \alias{include_meta} 5 | \title{Include Metadata Tags in HTML Document} 6 | \usage{ 7 | include_meta(.meta) 8 | } 9 | \arguments{ 10 | \item{.meta}{A \code{meta} object created by \code{\link[=meta]{meta()}} or \code{\link[=as_meta]{as_meta()}}, or returned 11 | by a \verb{meta_*()} object.} 12 | } 13 | \value{ 14 | An \code{\link[htmltools:htmlDependency]{htmltools::htmlDependency()}} containing the metadata tags to be 15 | included in the \verb{} of the HTML document. 16 | } 17 | \description{ 18 | Use \code{include_meta()} to explicitly declare the \code{\link[=meta]{meta()}} tags as an HTML 19 | dependency. In general, this is not required when knitting to an HTML 20 | document. This function explicitly attaches an \code{\link[htmltools:htmlDependency]{htmltools::htmlDependency()}} 21 | and may work in some unusual cases. 22 | } 23 | \examples{ 24 | meta() \%>\% 25 | meta_name("github-repo" = "gadenbuie/metathis") \%>\% 26 | include_meta() 27 | 28 | } 29 | \seealso{ 30 | Other meta_actions: 31 | \code{\link{write_meta}()} 32 | } 33 | \concept{meta_actions} 34 | -------------------------------------------------------------------------------- /man/meta.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/meta.R 3 | \name{meta} 4 | \alias{meta} 5 | \alias{is_meta} 6 | \alias{as_meta} 7 | \title{Initialize a List of HTML Metadata Tags} 8 | \usage{ 9 | meta() 10 | 11 | is_meta(x) 12 | 13 | as_meta(x) 14 | } 15 | \arguments{ 16 | \item{x}{A list or metathis object} 17 | } 18 | \value{ 19 | A \code{meta} object, or a set of \verb{} HTML tags inside an HTML 20 | \verb{} tag. For use in \code{\link[rmarkdown:html_document]{rmarkdown::html_document()}}, \code{\link[shiny:runApp]{shiny::runApp()}}, 21 | or other HTML locations. 22 | } 23 | \description{ 24 | Initialize a \emph{metathis} object (i.e. a list of HTML metadata tags), test if 25 | an object is a \emph{metathis} object, or coerce a list of \code{meta} tags to be a 26 | \emph{metathis} object. 27 | } 28 | \section{Functions}{ 29 | \itemize{ 30 | \item \code{is_meta()}: Test if an objects is a \emph{metathis} object 31 | 32 | \item \code{as_meta()}: Convert a list of meta tags into a \emph{metathis} object. 33 | 34 | }} 35 | \examples{ 36 | meta() \%>\% 37 | meta_viewport() \%>\% 38 | is_meta() 39 | 40 | list_of_meta_tags <- list( 41 | htmltools::tags$meta(github = "gadenbuie"), 42 | htmltools::tags$meta(twitter = "grrrck") 43 | ) 44 | 45 | as_meta(list_of_meta_tags) 46 | } 47 | \seealso{ 48 | Other meta: 49 | \code{\link{meta_apple_itunes_app}()}, 50 | \code{\link{meta_apple_web_app}()}, 51 | \code{\link{meta_general}()}, 52 | \code{\link{meta_geo}()}, 53 | \code{\link{meta_google_scholar}()}, 54 | \code{\link{meta_name}()}, 55 | \code{\link{meta_social}()}, 56 | \code{\link{meta_tag}()}, 57 | \code{\link{meta_viewport}()} 58 | } 59 | \concept{meta} 60 | -------------------------------------------------------------------------------- /man/meta_apple_itunes_app.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/apple.R 3 | \name{meta_apple_itunes_app} 4 | \alias{meta_apple_itunes_app} 5 | \title{Apple Smart Banner Meta Tag} 6 | \usage{ 7 | meta_apple_itunes_app(.meta = meta(), app_id = NULL, affiliate_id = NULL, ...) 8 | } 9 | \arguments{ 10 | \item{.meta}{A \code{meta} object created by \code{\link[=meta]{meta()}} or \code{\link[=as_meta]{as_meta()}}, or returned 11 | by a \verb{meta_*()} object.} 12 | 13 | \item{app_id}{Apple app ID} 14 | 15 | \item{affiliate_id}{Apple affiliate ID} 16 | 17 | \item{...}{Additional name=value pairs.} 18 | } 19 | \value{ 20 | A \code{meta} object, or a set of \verb{} HTML tags inside an HTML 21 | \verb{} tag. For use in \code{\link[rmarkdown:html_document]{rmarkdown::html_document()}}, \code{\link[shiny:runApp]{shiny::runApp()}}, 22 | or other HTML locations. 23 | } 24 | \description{ 25 | Apple Smart Banner Meta Tag 26 | } 27 | \section{Example}{ 28 | 29 | 30 | \if{html}{\out{
}}\preformatted{# 31 | 32 | }\if{html}{\out{
}} 33 | } 34 | 35 | \seealso{ 36 | Other meta: 37 | \code{\link{meta_apple_web_app}()}, 38 | \code{\link{meta_general}()}, 39 | \code{\link{meta_geo}()}, 40 | \code{\link{meta_google_scholar}()}, 41 | \code{\link{meta_name}()}, 42 | \code{\link{meta_social}()}, 43 | \code{\link{meta_tag}()}, 44 | \code{\link{meta_viewport}()}, 45 | \code{\link{meta}()} 46 | } 47 | \concept{meta} 48 | -------------------------------------------------------------------------------- /man/meta_apple_web_app.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/apple.R 3 | \name{meta_apple_web_app} 4 | \alias{meta_apple_web_app} 5 | \title{Apple Web App Meta Tags} 6 | \usage{ 7 | meta_apple_web_app( 8 | .meta = meta(), 9 | title = NULL, 10 | capable = NULL, 11 | status_bar_style = c("default", "black", "black-translucent") 12 | ) 13 | } 14 | \arguments{ 15 | \item{.meta}{A \code{meta} object created by \code{\link[=meta]{meta()}} or \code{\link[=as_meta]{as_meta()}}, or returned 16 | by a \verb{meta_*()} object.} 17 | 18 | \item{title}{Launch Icon Title} 19 | 20 | \item{capable}{Enables standalone (full-screen) mode if TRUE} 21 | 22 | \item{status_bar_style}{Status bar appearance. has no effect unless 23 | standalone more is enabled (see \code{capable}). 24 | 25 | "If content is set to default, the status bar appears normal. If set to 26 | black, the status bar has a black background. If set to black-translucent, 27 | the status bar is black and translucent. If set to default or black, the 28 | web content is displayed below the status bar. If set to black-translucent, 29 | the web content is displayed on the entire screen, partially obscured by 30 | the status bar. The default value is default."} 31 | } 32 | \value{ 33 | A \code{meta} object, or a set of \verb{} HTML tags inside an HTML 34 | \verb{} tag. For use in \code{\link[rmarkdown:html_document]{rmarkdown::html_document()}}, \code{\link[shiny:runApp]{shiny::runApp()}}, 35 | or other HTML locations. 36 | } 37 | \description{ 38 | Apple Web App Meta Tags 39 | } 40 | \examples{ 41 | meta() \%>\% 42 | meta_apple_web_app( 43 | title = "My Fancy App", 44 | capable = TRUE, 45 | status_bar_style = "black-translucent" 46 | ) 47 | } 48 | \references{ 49 | \url{https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariHTMLRef/Articles/MetaTags.html} 50 | } 51 | \seealso{ 52 | Other meta: 53 | \code{\link{meta_apple_itunes_app}()}, 54 | \code{\link{meta_general}()}, 55 | \code{\link{meta_geo}()}, 56 | \code{\link{meta_google_scholar}()}, 57 | \code{\link{meta_name}()}, 58 | \code{\link{meta_social}()}, 59 | \code{\link{meta_tag}()}, 60 | \code{\link{meta_viewport}()}, 61 | \code{\link{meta}()} 62 | } 63 | \concept{meta} 64 | -------------------------------------------------------------------------------- /man/meta_general.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/general.R 3 | \name{meta_general} 4 | \alias{meta_general} 5 | \alias{meta_description} 6 | \alias{meta_subject} 7 | \alias{meta_referrer} 8 | \alias{meta_robots} 9 | \alias{meta_theme_color} 10 | \title{General Metadata Tags} 11 | \usage{ 12 | meta_general( 13 | .meta = meta(), 14 | application_name = NULL, 15 | theme_color = NULL, 16 | description = NULL, 17 | robots = NULL, 18 | generator = NULL, 19 | subject = NULL, 20 | rating = NULL, 21 | referrer = NULL 22 | ) 23 | 24 | meta_description(.meta = meta(), description) 25 | 26 | meta_subject(.meta = meta(), subject) 27 | 28 | meta_referrer(.meta = meta(), referrer) 29 | 30 | meta_robots(.meta = meta(), robots) 31 | 32 | meta_theme_color(.meta = meta(), theme_color) 33 | } 34 | \arguments{ 35 | \item{.meta}{A \code{meta} object created by \code{\link[=meta]{meta()}} or \code{\link[=as_meta]{as_meta()}}, or returned 36 | by a \verb{meta_*()} object.} 37 | 38 | \item{application_name}{Name of web application (only should be used if the 39 | website is used as an app).} 40 | 41 | \item{theme_color}{Theme Color for Chrome, Firefox OS and Opera, e.g. 42 | \code{"#00589a"}.} 43 | 44 | \item{description}{Short description of the document (limit to 150 45 | characters), This content \emph{may} be used as a part of search engine results.} 46 | 47 | \item{robots}{Control the behavior of search engine crawling and indexing, 48 | e.g. \code{"index,follow"}. Valid names are \code{"index"}, \code{"noindex"}, \code{"follow"}, 49 | \code{"nofollow"}. May be a vector or a single string with comma-separated 50 | values. 51 | 52 | See \url{https://www.robotstxt.org/meta.html} for more information.} 53 | 54 | \item{generator}{Identify the software used to build the document (i.e. - 55 | WordPress, Dreamweaver).} 56 | 57 | \item{subject}{Short description of your document's subject.} 58 | 59 | \item{rating}{Gives a general age rating based on the document's content, 60 | e.g. \code{"General"}.} 61 | 62 | \item{referrer}{Allows control over how referrer information is passed, .e.g. 63 | \code{"no-referrer"}. Valid values include \code{"no-referrer"}, 64 | \code{"no-referrer-when-downgrade"}, \code{"same-origin"}, \code{"origin"}, 65 | \code{"strict-origin"}, \code{"origin-when-cross-origin"}, 66 | \code{"strict-origin-when-cross-origin"}, or \code{"unsafe-url"}.} 67 | } 68 | \value{ 69 | A \code{meta} object, or a set of \verb{} HTML tags inside an HTML 70 | \verb{} tag. For use in \code{\link[rmarkdown:html_document]{rmarkdown::html_document()}}, \code{\link[shiny:runApp]{shiny::runApp()}}, 71 | or other HTML locations. 72 | } 73 | \description{ 74 | Generate metadata tags for general website properties. 75 | } 76 | \examples{ 77 | meta() \%>\% 78 | meta_general( 79 | application_name = "Application Name", 80 | theme_color = "#4285f4", 81 | description = "A description of this page", 82 | robots = "index,follow", 83 | generator = "R-Shiny", 84 | subject = "Awesome R projects", 85 | rating = "General", 86 | referrer = "no-referrer" 87 | ) 88 | 89 | } 90 | \seealso{ 91 | Other meta: 92 | \code{\link{meta_apple_itunes_app}()}, 93 | \code{\link{meta_apple_web_app}()}, 94 | \code{\link{meta_geo}()}, 95 | \code{\link{meta_google_scholar}()}, 96 | \code{\link{meta_name}()}, 97 | \code{\link{meta_social}()}, 98 | \code{\link{meta_tag}()}, 99 | \code{\link{meta_viewport}()}, 100 | \code{\link{meta}()} 101 | } 102 | \concept{meta} 103 | -------------------------------------------------------------------------------- /man/meta_geo.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/geo.R 3 | \name{meta_geo} 4 | \alias{meta_geo} 5 | \title{Geotagging Metadata Tags} 6 | \usage{ 7 | meta_geo( 8 | .meta = meta(), 9 | icbm = NULL, 10 | geo_position = NULL, 11 | geo_region = NULL, 12 | geo_placename = NULL, 13 | ... 14 | ) 15 | } 16 | \arguments{ 17 | \item{.meta}{A \code{meta} object created by \code{\link[=meta]{meta()}} or \code{\link[=as_meta]{as_meta()}}, or returned 18 | by a \verb{meta_*()} object.} 19 | 20 | \item{icbm}{Latitude and longitude of geographic positions specified as 21 | \code{"lat, long"}. Can optionally be a length-two vector, i.e. \code{c(lat, long)}.} 22 | 23 | \item{geo_position}{Latitude and longitude of geographic positions specified 24 | as \code{"lat;long"}. Can optionally be a length-two vector, i.e. \code{c(lat, long)}.} 25 | 26 | \item{geo_region}{Name of the geographic region related to the page content, 27 | specified using \href{https://en.wikipedia.org/wiki/ISO_3166}{ISO-3166} 28 | 2-character country code and 2-character national subdivision. Example: 29 | \code{"US-NY"}.} 30 | 31 | \item{geo_placename}{Name of the geographic place related to the page 32 | content. Example: \code{"Atlanta, Georgia"}.} 33 | 34 | \item{...}{Additional geotagging metadata keyword and value pairs, such as 35 | \code{geo.country}, \code{geo.a1}, ..., \code{geo.a3}, etc. Underscores in the keyword 36 | will be converted to periods, so you can also specify \code{geo_country} in 37 | place of \code{geo.country}.} 38 | } 39 | \value{ 40 | A \code{meta} object, or a set of \verb{} HTML tags inside an HTML 41 | \verb{} tag. For use in \code{\link[rmarkdown:html_document]{rmarkdown::html_document()}}, \code{\link[shiny:runApp]{shiny::runApp()}}, 42 | or other HTML locations. 43 | } 44 | \description{ 45 | Geotagging Metadata Tags 46 | } 47 | \examples{ 48 | meta() \%>\% 49 | meta_geo( 50 | icbm = c(50.167958, -97.133185), 51 | geo_position = c(50.167958, -97.133185), 52 | geo_placename = "Manitoba, Canada", 53 | geo_region = "ca-mb" 54 | ) 55 | 56 | } 57 | \references{ 58 | \href{https://en.wikipedia.org/wiki/ICBM_address#Modern_use}{ICBM on Wikipedia}, 59 | \href{https://en.wikipedia.org/wiki/Geotagging#HTML_pages}{Geotagging on Wikipedia} 60 | } 61 | \seealso{ 62 | Other meta: 63 | \code{\link{meta_apple_itunes_app}()}, 64 | \code{\link{meta_apple_web_app}()}, 65 | \code{\link{meta_general}()}, 66 | \code{\link{meta_google_scholar}()}, 67 | \code{\link{meta_name}()}, 68 | \code{\link{meta_social}()}, 69 | \code{\link{meta_tag}()}, 70 | \code{\link{meta_viewport}()}, 71 | \code{\link{meta}()} 72 | } 73 | \concept{meta} 74 | -------------------------------------------------------------------------------- /man/meta_google_scholar.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/google_scholar.R 3 | \name{meta_google_scholar} 4 | \alias{meta_google_scholar} 5 | \title{Add Google Scholar Metadata} 6 | \usage{ 7 | meta_google_scholar( 8 | .meta = meta(), 9 | title, 10 | author, 11 | publication_date, 12 | online_date = NULL, 13 | journal_title = NULL, 14 | conference_title = NULL, 15 | volume = NULL, 16 | issue = NULL, 17 | firstpage = NULL, 18 | lastpage = NULL, 19 | pdf_url = NULL, 20 | issn = NULL, 21 | isbn = NULL, 22 | dissertation_institution = NULL, 23 | technical_report_institution = NULL, 24 | technical_report_number = NULL 25 | ) 26 | } 27 | \arguments{ 28 | \item{.meta}{A \code{meta} object created by \code{\link[=meta]{meta()}} or \code{\link[=as_meta]{as_meta()}}, or returned 29 | by a \verb{meta_*()} object.} 30 | 31 | \item{title}{The title of the paper. 32 | 33 | The title tag must contain the title of the paper. Don't use it for the 34 | title of the journal or a book in which the paper was published, or for the 35 | name of your repository. This tag is required for inclusion in Google 36 | Scholar.} 37 | 38 | \item{author}{A vector of author names. 39 | 40 | The \code{author} tag, must contain the authors (and only the actual authors) of 41 | the paper. Don't use it for the author of the website or for contributors 42 | other than authors, e.g., thesis advisors. Author names can be listed 43 | either as "Smith, John" or as "John Smith". Put each author name in a 44 | separate tag and omit all affiliations, degrees, certifications, etc., from 45 | this field. At least one author tag is required for inclusion in Google 46 | Scholar.} 47 | 48 | \item{publication_date, online_date}{The date the paper was published in the 49 | journal (\code{publication_date}) or published online (\code{online_date}). 50 | 51 | The \code{publication_date} tag must contain the date of publication, i.e., the 52 | date that would normally be cited in references to this paper from other 53 | papers. Don't use it for the date of entry into the repository - that 54 | should go into \code{online_date} instead. Provide full dates in the "2010/5/12" 55 | format if available; or a year alone otherwise. This tag is required for 56 | inclusion in Google Scholar.} 57 | 58 | \item{journal_title, conference_title, issn, isbn, volume, issue, firstpage, lastpage}{For journal and conference papers, provide the remaining bibliographic 59 | citation data in the following tags: \code{journal_title} or \code{conference_title}, 60 | \code{issn}, \code{isbn}, \code{volume}, \code{issue}, \code{firstpage}, and \code{lastpage.} These 61 | fields must contain sufficient information to identify a reference to this 62 | paper from another document, which is normally all of: (a) journal or 63 | conference name, (b) volume and issue numbers, if applicable, and (c) the 64 | number of the first page of the paper in the volume (or issue) in question.} 65 | 66 | \item{pdf_url}{The \verb{} tags normally apply only to the exact page on 67 | which they're provided. If this page shows only the abstract of the paper 68 | and you have the full text in a separate file, e.g., in the PDF format, 69 | please specify the locations of all full text versions using \code{pdf_url}. The 70 | content of the tag is the absolute URL of the PDF file; for security 71 | reasons, it must refer to a file in the same subdirectory as the HTML 72 | abstract.} 73 | 74 | \item{dissertation_institution, technical_report_institution, technical_report_number}{For theses, dissertations, and technical reports, provide the remaining 75 | bibliographic citation data in the following tags: 76 | \code{dissertation_institution}, \code{technical_report_institution} for the name of 77 | the institution and \code{technical_report_number} for the number of the 78 | technical report. As with journal and conference papers, you need to 79 | provide sufficient information to recognize a formal citation to this 80 | document from another article.} 81 | } 82 | \value{ 83 | A \code{meta} object, or a set of \verb{} HTML tags inside an HTML 84 | \verb{} tag. For use in \code{\link[rmarkdown:html_document]{rmarkdown::html_document()}}, \code{\link[shiny:runApp]{shiny::runApp()}}, 85 | or other HTML locations. 86 | } 87 | \description{ 88 | Add bibliographic metadata to pages in the format expected by Google 89 | Scholar. Please reference the 90 | \href{https://scholar.google.com/intl/en/scholar/inclusion.html#indexing}{Google Scholar Inclusion} 91 | page for the most up-to-date information and instructions. Note that this 92 | function adds the \code{citation_} prefix to all of its arguments; the \code{title} 93 | argument becomes the \code{citation_title} \verb{} tag. 94 | } 95 | \examples{ 96 | meta_google_scholar( 97 | title = c( 98 | "The testis isoform of the phosphorylase kinase catalytic subunit (PhK-T)", 99 | "plays a critical role in regulation of glycogen mobilization in developing lung" 100 | ), 101 | author = c( 102 | "Liu, Li", 103 | "Rannels, Stephen R.", 104 | "Falconieri, Mary", 105 | "Phillips, Karen S.", 106 | "Wolpert, Ellen B.", 107 | "Weaver, Timothy E." 108 | ), 109 | publication_date = "1996/05/17", 110 | journal_title = "Journal of Biological Chemistry", 111 | volume = 271, 112 | issue = 20, 113 | firstpage = 11761, 114 | lastpage = 11766, 115 | pdf_url = "http://www.example.com/content/271/20/11761.full.pdf" 116 | ) 117 | 118 | } 119 | \references{ 120 | \url{https://scholar.google.com/intl/en/scholar/inclusion.html#indexing} 121 | } 122 | \seealso{ 123 | Other meta: 124 | \code{\link{meta_apple_itunes_app}()}, 125 | \code{\link{meta_apple_web_app}()}, 126 | \code{\link{meta_general}()}, 127 | \code{\link{meta_geo}()}, 128 | \code{\link{meta_name}()}, 129 | \code{\link{meta_social}()}, 130 | \code{\link{meta_tag}()}, 131 | \code{\link{meta_viewport}()}, 132 | \code{\link{meta}()} 133 | } 134 | \concept{meta} 135 | -------------------------------------------------------------------------------- /man/meta_name.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/meta.R 3 | \name{meta_name} 4 | \alias{meta_name} 5 | \title{Create name/content metadata tag pairs} 6 | \usage{ 7 | meta_name(.meta = meta(), ...) 8 | } 9 | \arguments{ 10 | \item{.meta}{A \code{meta} object created by \code{\link[=meta]{meta()}} or \code{\link[=as_meta]{as_meta()}}, or returned 11 | by a \verb{meta_*()} object.} 12 | 13 | \item{...}{Name (argument names) and content (argument value) pairs.} 14 | } 15 | \value{ 16 | A \code{meta} object, or a set of \verb{} HTML tags inside an HTML 17 | \verb{} tag. For use in \code{\link[rmarkdown:html_document]{rmarkdown::html_document()}}, \code{\link[shiny:runApp]{shiny::runApp()}}, 18 | or other HTML locations. 19 | } 20 | \description{ 21 | Creates metadata tag pairs where the arguments are the name values and their 22 | values are content values. 23 | } 24 | \examples{ 25 | meta() \%>\% 26 | meta_name("github-repo" = "hadley/r4ds") 27 | 28 | } 29 | \seealso{ 30 | Other meta: 31 | \code{\link{meta_apple_itunes_app}()}, 32 | \code{\link{meta_apple_web_app}()}, 33 | \code{\link{meta_general}()}, 34 | \code{\link{meta_geo}()}, 35 | \code{\link{meta_google_scholar}()}, 36 | \code{\link{meta_social}()}, 37 | \code{\link{meta_tag}()}, 38 | \code{\link{meta_viewport}()}, 39 | \code{\link{meta}()} 40 | } 41 | \concept{meta} 42 | -------------------------------------------------------------------------------- /man/meta_social.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/social.R 3 | \name{meta_social} 4 | \alias{meta_social} 5 | \title{Social Media Metadata} 6 | \usage{ 7 | meta_social( 8 | .meta = meta(), 9 | title = NULL, 10 | url = NULL, 11 | image = NULL, 12 | image_alt = NULL, 13 | image_width = NULL, 14 | image_height = NULL, 15 | description = NULL, 16 | twitter_card_type = c("summary", "summary_large_image", "app", "player"), 17 | twitter_creator = NULL, 18 | twitter_site = twitter_creator, 19 | og_type = "website", 20 | og_locale = "en_US", 21 | og_author = NULL, 22 | og_site_name = NULL, 23 | facebook_app_id = NULL, 24 | disable_pinterest = FALSE 25 | ) 26 | } 27 | \arguments{ 28 | \item{.meta}{A \code{meta} object created by \code{\link[=meta]{meta()}} or \code{\link[=as_meta]{as_meta()}}, or returned 29 | by a \verb{meta_*()} object.} 30 | 31 | \item{title}{Content title} 32 | 33 | \item{url}{Content URL} 34 | 35 | \item{image}{Image url for card.} 36 | 37 | \item{image_alt}{A description of what's in the image (not a caption)} 38 | 39 | \item{image_width}{The width of the image in pixels} 40 | 41 | \item{image_height}{The height of the image in pixels} 42 | 43 | \item{description}{Content description. If you have already used 44 | \code{\link[=meta_general]{meta_general()}} to set the content's description, that description will 45 | automatically be used.} 46 | 47 | \item{twitter_card_type}{One of \code{"summary"}, \code{"summary_large_image"}, 48 | \code{"app"}, or \code{"player"}.} 49 | 50 | \item{twitter_creator}{\verb{@username} for the content creator / author.} 51 | 52 | \item{twitter_site}{\verb{@username`` for the website used in the card footer. }twitter_creator` is used by default.} 53 | 54 | \item{og_type}{Open Graph card type, default is \code{"website"}. Other common 55 | options include \code{"article"}, \code{"book"}, or \code{"profile"}. The full list of 56 | valid options can be referenced at \url{https://ogp.me/}} 57 | 58 | \item{og_locale}{The locale these tags are marked up in. Of the format \code{language_TERRITORY}. Default is \code{"en_US"}.} 59 | 60 | \item{og_author}{Writers of the article. Multiple authors may be specified in 61 | a vector of character strings.} 62 | 63 | \item{og_site_name}{The name of the site hosting the content} 64 | 65 | \item{facebook_app_id}{The Facebook app ID. See the 66 | \href{https://developers.facebook.com/docs/sharing/webmasters#markup}{Facebook Open Graph Markup} 67 | page for more information.} 68 | 69 | \item{disable_pinterest}{If \code{TRUE}, adds a metadata tag disabling pins from 70 | your website. See the 71 | \href{https://help.pinterest.com/en/business/article/prevent-saves-to-pinterest-from-your-site}{Pinterest help center} 72 | for more information.} 73 | } 74 | \value{ 75 | A \code{meta} object, or a set of \verb{} HTML tags inside an HTML 76 | \verb{} tag. For use in \code{\link[rmarkdown:html_document]{rmarkdown::html_document()}}, \code{\link[shiny:runApp]{shiny::runApp()}}, 77 | or other HTML locations. 78 | } 79 | \description{ 80 | Generate metadata tags for social media cards. 81 | } 82 | \examples{ 83 | meta() \%>\% 84 | meta_social( 85 | title = "R for Data Science", 86 | description = "This book with teach you how to do data science with R", 87 | url = "https://r4ds.had.co.nz", 88 | image = "https://r4ds.had.co.nz/cover.png", 89 | image_alt = "The cover of the R4DS book", 90 | og_type = "book", 91 | og_author = c("Garrett Grolemund", "Hadley Wickham"), 92 | twitter_card_type = "summary", 93 | twitter_creator = "@hadley" 94 | ) 95 | 96 | } 97 | \references{ 98 | \itemize{ 99 | \item \href{https://ogp.me/}{Open Graph} 100 | \item \href{https://search.google.com/structured-data/testing-tool}{Google Structured Data Testing Tool} 101 | \item \href{https://developers.facebook.com/tools/debug/}{Facebook Sharing Debugger} 102 | \item \href{https://developer.twitter.com/en/docs/twitter-for-websites/cards/guides/getting-started}{Twitter Card Documentation} 103 | } 104 | } 105 | \seealso{ 106 | Other meta: 107 | \code{\link{meta_apple_itunes_app}()}, 108 | \code{\link{meta_apple_web_app}()}, 109 | \code{\link{meta_general}()}, 110 | \code{\link{meta_geo}()}, 111 | \code{\link{meta_google_scholar}()}, 112 | \code{\link{meta_name}()}, 113 | \code{\link{meta_tag}()}, 114 | \code{\link{meta_viewport}()}, 115 | \code{\link{meta}()} 116 | } 117 | \concept{meta} 118 | -------------------------------------------------------------------------------- /man/meta_tag.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/meta.R 3 | \name{meta_tag} 4 | \alias{meta_tag} 5 | \title{Create a metadata tag for attribute/value pairs} 6 | \usage{ 7 | meta_tag(.meta = meta(), ...) 8 | } 9 | \arguments{ 10 | \item{.meta}{A \code{meta} object created by \code{\link[=meta]{meta()}} or \code{\link[=as_meta]{as_meta()}}, or returned 11 | by a \verb{meta_*()} object.} 12 | 13 | \item{...}{Attribute names and values as \code{attribute = value}. Values must be 14 | a single character string.} 15 | } 16 | \value{ 17 | A \code{meta} object, or a set of \verb{} HTML tags inside an HTML 18 | \verb{} tag. For use in \code{\link[rmarkdown:html_document]{rmarkdown::html_document()}}, \code{\link[shiny:runApp]{shiny::runApp()}}, 19 | or other HTML locations. 20 | } 21 | \description{ 22 | Creates a \verb{} tag for attribute value pairs, where argument names 23 | correspond to attribute names. 24 | } 25 | \examples{ 26 | meta() \%>\% 27 | meta_tag( 28 | "http-equiv" = "Content-Security-Policy", 29 | content = "default-src 'self'" 30 | ) 31 | 32 | } 33 | \seealso{ 34 | Other meta: 35 | \code{\link{meta_apple_itunes_app}()}, 36 | \code{\link{meta_apple_web_app}()}, 37 | \code{\link{meta_general}()}, 38 | \code{\link{meta_geo}()}, 39 | \code{\link{meta_google_scholar}()}, 40 | \code{\link{meta_name}()}, 41 | \code{\link{meta_social}()}, 42 | \code{\link{meta_viewport}()}, 43 | \code{\link{meta}()} 44 | } 45 | \concept{meta} 46 | -------------------------------------------------------------------------------- /man/meta_viewport.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/viewport.R 3 | \name{meta_viewport} 4 | \alias{meta_viewport} 5 | \title{Viewport Meta Tag} 6 | \usage{ 7 | meta_viewport( 8 | .meta = meta(), 9 | width = "device-width", 10 | initial_scale = "1", 11 | orientation = c("auto", "portrait", "landscape"), 12 | min_width = NULL, 13 | max_width = NULL, 14 | height = NULL, 15 | min_height = NULL, 16 | max_height = NULL, 17 | minimum_scale = NULL, 18 | maximum_scale = NULL, 19 | user_scalable = NULL, 20 | ... 21 | ) 22 | } 23 | \arguments{ 24 | \item{.meta}{A \code{meta} object created by \code{\link[=meta]{meta()}} or \code{\link[=as_meta]{as_meta()}}, or returned 25 | by a \verb{meta_*()} object.} 26 | 27 | \item{width}{Sets the width of initial viewport. \code{width} sets \code{min_width} and 28 | \code{max_width} and may contain two values; for example, the following are 29 | equivalent: \code{"300px 500px"} or \code{c("300px", "500px")}). The values may be 30 | a number with units, a percentage, or \code{"device-width"}. Pixels are assumed 31 | if no units are provided.} 32 | 33 | \item{initial_scale}{Initial scale} 34 | 35 | \item{orientation}{One of \code{"auto"}, \code{"portrait"}, \code{"landscape"}.} 36 | 37 | \item{min_width, max_width}{Minimum and maximum initial viewport width. See 38 | \code{width} for more information. \code{width} is ignored if \code{min_width} or 39 | \code{max_width} are set.} 40 | 41 | \item{height, min_height, max_height}{Sets height of initial viewport. Follows 42 | the same conventions as \code{width}, \code{min_width}, and \code{max_width}.} 43 | 44 | \item{minimum_scale}{Minimum scale} 45 | 46 | \item{maximum_scale}{Maximum scale} 47 | 48 | \item{user_scalable}{User scalable} 49 | 50 | \item{...}{Additional name/value pairs} 51 | } 52 | \value{ 53 | A \code{meta} object, or a set of \verb{} HTML tags inside an HTML 54 | \verb{} tag. For use in \code{\link[rmarkdown:html_document]{rmarkdown::html_document()}}, \code{\link[shiny:runApp]{shiny::runApp()}}, 55 | or other HTML locations. 56 | } 57 | \description{ 58 | Create or add a viewport meta tag. 59 | } 60 | \examples{ 61 | meta() \%>\% 62 | meta_viewport() 63 | 64 | meta() \%>\% 65 | meta_viewport(orientation = NULL) 66 | 67 | meta() \%>\% 68 | meta_viewport(maximum_scale = 1) 69 | 70 | } 71 | \references{ 72 | \href{https://developer.mozilla.org/en-US/docs/Web/HTML/Viewport_meta_tag}{MDN: Viewport Meta Tag}, 73 | } 74 | \seealso{ 75 | Other meta: 76 | \code{\link{meta_apple_itunes_app}()}, 77 | \code{\link{meta_apple_web_app}()}, 78 | \code{\link{meta_general}()}, 79 | \code{\link{meta_geo}()}, 80 | \code{\link{meta_google_scholar}()}, 81 | \code{\link{meta_name}()}, 82 | \code{\link{meta_social}()}, 83 | \code{\link{meta_tag}()}, 84 | \code{\link{meta}()} 85 | } 86 | \concept{meta} 87 | -------------------------------------------------------------------------------- /man/metathis-package.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/metathis-package.R 3 | \docType{package} 4 | \name{metathis-package} 5 | \alias{metathis} 6 | \alias{metathis-package} 7 | \title{metathis: HTML Metadata Tags for 'R Markdown' and 'Shiny'} 8 | \description{ 9 | \if{html}{\figure{logo.png}{options: style='float: right' alt='logo' width='120'}} 10 | 11 | Create meta tags for 'R Markdown' HTML documents and 'Shiny' apps for customized social media cards, for accessibility, and quality search engine indexing. 'metathis' currently supports HTML documents created with 'rmarkdown', 'shiny', 'xaringan', 'pagedown', 'bookdown', and 'flexdashboard'. 12 | } 13 | \seealso{ 14 | Useful links: 15 | \itemize{ 16 | \item \url{https://pkg.garrickadenbuie.com/metathis/} 17 | \item \url{https://github.com/gadenbuie/metathis} 18 | \item Report bugs at \url{https://github.com/gadenbuie/metathis/issues} 19 | } 20 | 21 | } 22 | \author{ 23 | \strong{Maintainer}: Garrick Aden-Buie \email{garrick@adenbuie.com} (\href{https://orcid.org/0000-0002-7111-0077}{ORCID}) 24 | 25 | } 26 | \keyword{internal} 27 | -------------------------------------------------------------------------------- /man/pipe.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utils-pipe.R 3 | \name{\%>\%} 4 | \alias{\%>\%} 5 | \title{Pipe operator} 6 | \usage{ 7 | lhs \%>\% rhs 8 | } 9 | \description{ 10 | See \code{magrittr::\link[magrittr:pipe]{\%>\%}} for details. 11 | } 12 | \keyword{internal} 13 | -------------------------------------------------------------------------------- /man/write_meta.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/write.R 3 | \name{write_meta} 4 | \alias{write_meta} 5 | \title{Write Metadata Tags to a File} 6 | \usage{ 7 | write_meta(.meta, path = "meta.html", append = FALSE) 8 | } 9 | \arguments{ 10 | \item{.meta}{A \code{meta} object created by \code{\link[=meta]{meta()}} or \code{\link[=as_meta]{as_meta()}}, or returned 11 | by a \verb{meta_*()} object.} 12 | 13 | \item{path}{The file to write into, defaults to \code{"meta.html"}.} 14 | 15 | \item{append}{logical. Only used if the argument \code{file} is the 16 | name of file (and not a connection or \code{"|cmd"}). 17 | If \code{TRUE} output will be appended to 18 | \code{file}; otherwise, it will overwrite the contents of 19 | \code{file}.} 20 | } 21 | \value{ 22 | Returns \code{.meta} invisibly. 23 | } 24 | \description{ 25 | Write your metadata tags to an HTML file that can be manually included in 26 | your page. 27 | } 28 | \examples{ 29 | meta_html_snippet <- tempfile("metathis_example", fileext = ".html") 30 | 31 | meta() \%>\% 32 | meta_name("package" = "metathis") \%>\% 33 | write_meta(meta_html_snippet) 34 | 35 | readLines(meta_html_snippet, warn = FALSE) 36 | 37 | } 38 | \seealso{ 39 | Other meta_actions: 40 | \code{\link{include_meta}()} 41 | } 42 | \concept{meta_actions} 43 | -------------------------------------------------------------------------------- /metathis.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: No 4 | SaveWorkspace: No 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | 15 | AutoAppendNewline: Yes 16 | StripTrailingWhitespace: Yes 17 | 18 | BuildType: Package 19 | PackageUseDevtools: Yes 20 | PackageInstallArgs: --no-multiarch --with-keep.source 21 | PackageRoxygenize: rd,collate,namespace 22 | -------------------------------------------------------------------------------- /pkgdown/_pkgdown.yml: -------------------------------------------------------------------------------- 1 | url: https://pkg.garrickadenbuie.com/metathis/ 2 | 3 | home: 4 | description: > 5 | Easy <meta> tags for social media cards, accessibility and quality search 6 | indexing in R Markdown and Shiny. 7 | 8 | template: 9 | package: grkgdown 10 | opengraph: 11 | image: 12 | src: man/figures/card.png 13 | twitter: 14 | creator: "@grrrck" 15 | card: summary_large_image 16 | 17 | authors: 18 | Garrick Aden-Buie: 19 | href: https://www.garrickadenbuie.com 20 | 21 | navbar: 22 | type: light 23 | structure: 24 | left: 25 | - home 26 | - intro 27 | - reference 28 | - articles 29 | - tutorials 30 | right: 31 | - news 32 | - github 33 | - twitter 34 | - garrick 35 | components: 36 | home: 37 | icon: ~ 38 | text: Overview 39 | href: index.html 40 | reference: 41 | text: Reference 42 | href: reference/index.html 43 | news: 44 | icon: far fa-newspaper fa-lg 45 | href: news/index.html 46 | text: "" 47 | title: "Changelog" 48 | github: 49 | icon: fab fa-github fa-lg 50 | href: https://github.com/gadenbuie/metathis 51 | garrick: 52 | icon: fas fa-home fa-lg 53 | href: https://garrickadenbuie.com 54 | title: Garrick Aden-Buie 55 | twitter: 56 | icon: fab fa-twitter fa-lg 57 | href: https://twitter.com/grrrck 58 | 59 | reference: 60 | - title: Add meta tags 61 | desc: ~ 62 | contents: 63 | - '`meta`' 64 | - '`include_meta`' 65 | - '`write_meta`' 66 | - title: Social media meta tags 67 | desc: ~ 68 | contents: 69 | - '`meta_social`' 70 | - title: Scholarly literature and publications 71 | desc: ~ 72 | contents: 73 | - '`meta_google_scholar`' 74 | - title: General meta tags 75 | desc: ~ 76 | contents: 77 | - '`meta_name`' 78 | - '`meta_tag`' 79 | - '`meta_general`' 80 | - '`meta_viewport`' 81 | - title: Geotagging meta tags 82 | desc: ~ 83 | contents: 84 | - '`meta_geo`' 85 | - title: Apple meta tags 86 | desc: ~ 87 | contents: 88 | - '`meta_apple_web_app`' 89 | - '`meta_apple_itunes_app`' 90 | -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gadenbuie/metathis/5fcb4c6320d33e75e94c4f15c4d3d0314f824f17/pkgdown/favicon/apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gadenbuie/metathis/5fcb4c6320d33e75e94c4f15c4d3d0314f824f17/pkgdown/favicon/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gadenbuie/metathis/5fcb4c6320d33e75e94c4f15c4d3d0314f824f17/pkgdown/favicon/apple-touch-icon-180x180.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gadenbuie/metathis/5fcb4c6320d33e75e94c4f15c4d3d0314f824f17/pkgdown/favicon/apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gadenbuie/metathis/5fcb4c6320d33e75e94c4f15c4d3d0314f824f17/pkgdown/favicon/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /pkgdown/favicon/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gadenbuie/metathis/5fcb4c6320d33e75e94c4f15c4d3d0314f824f17/pkgdown/favicon/apple-touch-icon.png -------------------------------------------------------------------------------- /pkgdown/favicon/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gadenbuie/metathis/5fcb4c6320d33e75e94c4f15c4d3d0314f824f17/pkgdown/favicon/favicon-16x16.png -------------------------------------------------------------------------------- /pkgdown/favicon/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gadenbuie/metathis/5fcb4c6320d33e75e94c4f15c4d3d0314f824f17/pkgdown/favicon/favicon-32x32.png -------------------------------------------------------------------------------- /pkgdown/favicon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gadenbuie/metathis/5fcb4c6320d33e75e94c4f15c4d3d0314f824f17/pkgdown/favicon/favicon.ico -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(metathis) 3 | 4 | test_check("metathis") 5 | -------------------------------------------------------------------------------- /tests/testthat/helper.R: -------------------------------------------------------------------------------- 1 | expect_equal_meta <- function(.meta, expected) { 2 | expect_equal(as.character(.meta), expected) 3 | } 4 | -------------------------------------------------------------------------------- /tests/testthat/rmd/.gitignore: -------------------------------------------------------------------------------- 1 | *html 2 | *_files 3 | -------------------------------------------------------------------------------- /tests/testthat/rmd/test-metathis.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "test-metathis-rmd" 3 | output: html_document_base 4 | --- 5 | 6 | ```{r setup, include=FALSE} 7 | knitr::opts_chunk$set(echo = TRUE) 8 | ``` 9 | 10 | ```{r} 11 | knitr::opts_knit$get("out.format") 12 | knitr::opts_knit$get("rmarkdown.pandoc.to") 13 | ``` 14 | 15 | 16 | ```{r metathis} 17 | library(metathis) 18 | 19 | meta() %>% 20 | meta_tag(method = "KNIT_PRINT") 21 | ``` 22 | 23 | ```{r metathis-2} 24 | meta_tag(method = "knit_print(2)") 25 | ``` 26 | 27 | ```{r} 28 | meta() %>% 29 | meta_tag(method = "INCLUDE_META()") %>% 30 | include_meta() 31 | ``` 32 | -------------------------------------------------------------------------------- /tests/testthat/rmd/test-not-self-contained.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "test-metathis-not-self-contained-rmd" 3 | output: 4 | html_document: 5 | self_contained: no 6 | --- 7 | 8 | ```{r setup, include=FALSE} 9 | knitr::opts_chunk$set(echo = TRUE) 10 | ``` 11 | 12 | ```{r} 13 | knitr::opts_knit$get("out.format") 14 | knitr::opts_knit$get("rmarkdown.pandoc.to") 15 | ``` 16 | 17 | 18 | ```{r metathis} 19 | library(metathis) 20 | 21 | meta() %>% 22 | meta_tag(method = "KNIT_PRINT") 23 | ``` 24 | 25 | ```{r metathis-2} 26 | meta_tag(method = "knit_print(2)") 27 | ``` 28 | 29 | ```{r} 30 | meta() %>% 31 | meta_tag(method = "INCLUDE_META()") %>% 32 | include_meta() 33 | ``` 34 | -------------------------------------------------------------------------------- /tests/testthat/test-apple.R: -------------------------------------------------------------------------------- 1 | test_that("meta_apple_itunes_app()", { 2 | expected <- '' 3 | tested <- meta_apple_itunes_app( 4 | app_id = "APP_ID", 5 | affiliate_id = "AFFILIATE_ID", 6 | `app-argument` = "SOME_TEXT" 7 | ) 8 | 9 | expect_equal(tested %>% paste(), expected) 10 | 11 | expect_equal( 12 | meta_apple_itunes_app(), 13 | meta() 14 | ) 15 | }) 16 | 17 | describe("meta_apple_web_app()", { 18 | it("generally works", { 19 | expected <- c( 20 | '', 21 | '', 22 | '' 23 | ) 24 | 25 | expect_equal_meta( 26 | meta() %>% meta_apple_web_app( 27 | title = "App Title", 28 | capable = TRUE, 29 | status_bar_style = "black" 30 | ), 31 | expected 32 | ) 33 | 34 | expect_equal_meta( 35 | meta() %>% meta_apple_web_app(capable = FALSE, status_bar_style = NULL), 36 | sub("yes", "no", expected[2], fixed = TRUE) 37 | ) 38 | }) 39 | 40 | it('errors when appropriate', { 41 | expect_error(meta_apple_web_app(status_bar_style = "white")) 42 | expect_error(meta_apple_web_app("a")) 43 | }) 44 | }) 45 | -------------------------------------------------------------------------------- /tests/testthat/test-blogdown.R: -------------------------------------------------------------------------------- 1 | with_dir <- function(path, x) { 2 | owd <- setwd(path) 3 | on.exit(setwd(owd)) 4 | eval(substitute(x)) 5 | } 6 | 7 | test_that("blogdown is guessed correctly", { 8 | blogdown_dir <- file.path(tempdir(), "blogdown", "content", "post") 9 | dir.create(blogdown_dir, recursive = TRUE) 10 | on.exit(unlink(file.path(tempdir(), "blogdown"), recursive = TRUE)) 11 | 12 | # setup fake blogdown folder structure 13 | dir.create(file.path(blogdown_dir, "..", "..", "layouts")) 14 | dir.create(file.path(blogdown_dir, "..", "..", "static")) 15 | cat('', file = file.path(blogdown_dir, "..", "..", "config.toml")) 16 | 17 | blogdown_exp <- normalizePath(file.path(tempdir(), "blogdown")) 18 | expect_equal(find_config(blogdown_dir), blogdown_exp) 19 | with_dir(blogdown_dir, expect_true(guess_blogdown())) 20 | 21 | cat('baseURL = "/"', file = file.path(blogdown_dir, "..", "..", "config.toml")) 22 | expect_equal(find_config(blogdown_dir), blogdown_exp) 23 | with_dir(blogdown_dir, expect_true(guess_blogdown())) 24 | 25 | expect_null(find_config(tempdir())) 26 | with_dir(tempdir(), expect_false(guess_blogdown())) 27 | 28 | # create config.toml outside of blogdown, should be detected as non-blogdown 29 | cat("", file = file.path(tempdir(), "config.toml")) 30 | on.exit(unlink(file.path(tempdir(), "config.toml")), add = TRUE) 31 | with_dir(tempdir(), expect_false(guess_blogdown())) 32 | }) 33 | -------------------------------------------------------------------------------- /tests/testthat/test-general.R: -------------------------------------------------------------------------------- 1 | 2 | test_that("meta_description()", { 3 | expect_equal_meta( 4 | meta() %>% meta_description("A cool app"), 5 | '' 6 | ) 7 | }) 8 | 9 | 10 | test_that("meta_subject()", { 11 | expect_equal_meta( 12 | meta() %>% meta_subject("hot topics"), 13 | '' 14 | ) 15 | }) 16 | 17 | test_that("meta_referrer()", { 18 | expect_equal_meta( 19 | meta() %>% meta_referrer("no-referrer"), 20 | '' 21 | ) 22 | }) 23 | 24 | test_that("meta_robots()", { 25 | expect_equal_meta( 26 | meta() %>% meta_robots("nofollow"), 27 | '' 28 | ) 29 | expect_equal_meta( 30 | meta() %>% meta_robots(c("index", "follow")), 31 | '' 32 | ) 33 | }) 34 | 35 | test_that("meta_theme_color()", { 36 | expect_equal_meta( 37 | meta() %>% meta_theme_color("#123456"), 38 | '' 39 | ) 40 | }) 41 | 42 | test_that("meta_general() errors appropriately", { 43 | expect_error(meta_general(1)) 44 | }) 45 | -------------------------------------------------------------------------------- /tests/testthat/test-geo.R: -------------------------------------------------------------------------------- 1 | test_that("meta_geo()", { 2 | exp_geo <- c( 3 | '', 4 | '', 5 | '', 6 | '' 7 | ) 8 | 9 | expect_equal_meta( 10 | meta() %>% 11 | meta_geo( 12 | icbm = c(50.167958, -97.133185), 13 | geo_position = c(50.167958, -97.133185), 14 | geo_placename = "Manitoba, Canada", 15 | geo_region = "ca-mb" 16 | ), 17 | exp_geo 18 | ) 19 | 20 | expect_equal( 21 | meta_geo(icbm = c(50.167958, -97.133185)), 22 | meta_geo(icbm = "50.167958, -97.133185") 23 | ) 24 | 25 | expect_equal( 26 | meta_geo(geo_position = c(50.167958, -97.133185)), 27 | meta_geo(geo_position = "50.167958;-97.133185") 28 | ) 29 | 30 | }) 31 | -------------------------------------------------------------------------------- /tests/testthat/test-google_scholar.R: -------------------------------------------------------------------------------- 1 | test_that("meta_google_scholar()", { 2 | expected <- ' 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | ' 16 | 17 | meta <- meta_google_scholar( 18 | title = c( 19 | "The testis isoform of the phosphorylase kinase catalytic subunit (PhK-T)", 20 | "plays a critical role in regulation of glycogen mobilization in developing lung" 21 | ), 22 | author = c( 23 | "Liu, Li", 24 | "Rannels, Stephen R.", 25 | "Falconieri, Mary", 26 | "Phillips, Karen S.", 27 | "Wolpert, Ellen B.", 28 | "Weaver, Timothy E." 29 | ), 30 | publication_date = "1996/05/17", 31 | journal_title = "Journal of Biological Chemistry", 32 | volume = 271, 33 | issue = 20, 34 | firstpage = 11761, 35 | lastpage = 11766, 36 | pdf_url = "http://www.example.com/content/271/20/11761.full.pdf" 37 | ) 38 | 39 | meta_chr <- gsub("/>", ">", format(meta)) 40 | expect_equal(meta_chr, expected) 41 | }) 42 | 43 | test_that("meta_google_scholar() catches common errors", { 44 | expect_error(meta_google_scholar(title = "foo")) 45 | expect_error( 46 | meta_google_scholar(title = "a", author = "b", publication_date = "2019-01-01"), 47 | "publication_date" 48 | ) 49 | expect_error( 50 | meta_google_scholar(title = "a", author = "b", publication_date = c(1999, 2000)), 51 | "publication_date" 52 | ) 53 | expect_error( 54 | meta_google_scholar(title = "a", author = "b", publication_date = 2000, online_date = "1/1/2021"), 55 | "online_date" 56 | ) 57 | }) 58 | -------------------------------------------------------------------------------- /tests/testthat/test-meta.R: -------------------------------------------------------------------------------- 1 | test_that("test-meta", expect_true(TRUE)) 2 | 3 | describe("meta class", { 4 | 5 | it("has class meta", { 6 | expect_s3_class(meta(), "meta") 7 | expect_s3_class(meta(), "shiny.tag.list") 8 | }) 9 | 10 | it("is_meta()", { 11 | expect_true(meta() %>% is_meta()) 12 | expect_false(list() %>% is_meta()) 13 | }) 14 | 15 | it("assert_is_meta", { 16 | expect_true(assert_is_meta(meta())) 17 | expect_error(asser_is_meta(list())) 18 | }) 19 | 20 | it("as_meta()", { 21 | list(name = "theme-color") %>% 22 | as_meta() %>% 23 | expect_s3_class("meta") 24 | 25 | expect_error(as_meta(3), "numeric") 26 | expect_error(data.frame(a = 1, b = 2) %>% as_meta(), "data.frame") 27 | }) 28 | 29 | it("print.meta", { 30 | expect_equal(capture.output(print(meta_tag(a = "a"))), '') 31 | }) 32 | }) 33 | 34 | describe("meta_name()", { 35 | it("creates tags with name/content pairs", { 36 | exp <- '' 37 | expect_equal_meta(meta_name("github-repo" = "hadley/r4ds"), exp) 38 | 39 | exp2 <- c( 40 | "", 41 | "" 42 | ) 43 | expect_equal_meta(meta_name("A" = "a", "B" = "b"), exp2) 44 | }) 45 | 46 | it("concatenates if length(content) > 1", { 47 | exp <- '' 48 | expect_equal_meta(meta_name(value = c("a", "b")), exp) 49 | }) 50 | }) 51 | 52 | describe("meta_tag()", { 53 | it("creates tags with attribute = value pairs", { 54 | exp <- '' 55 | expect_equal_meta(meta_tag(A = "a", B = "b"), exp) 56 | }) 57 | 58 | it("errors if length(value) > 1", { 59 | expect_error(meta_tag(A = c('a', 'b'))) 60 | }) 61 | }) 62 | 63 | describe("meta_find_description()", { 64 | it("finds existing description", { 65 | expect_equal( 66 | meta() %>% meta_description("found me!") %>% meta_find_description(), 67 | "found me!" 68 | ) 69 | }) 70 | 71 | it("returns NULL if no description", { 72 | expect_null(meta() %>% meta_find_description()) 73 | 74 | expect_null(meta() %>% meta_tag(a = '1') %>% meta_find_description()) 75 | }) 76 | 77 | }) 78 | -------------------------------------------------------------------------------- /tests/testthat/test-rmd.R: -------------------------------------------------------------------------------- 1 | test_that("knit_print() and include_meta() work in Rmd", { 2 | skip_if_not(rmarkdown::pandoc_available("1.12.3")) 3 | 4 | temp_html <- tempfile("metathis-rmd", fileext = ".html") 5 | test_rmd <- test_path("rmd", "test-metathis.Rmd") 6 | rmarkdown::render(test_rmd, output_file = temp_html, quiet = TRUE) 7 | out <- readLines(temp_html) 8 | 9 | has_string <- function(str, n = 1L) { 10 | sum(grepl(str, out, fixed = TRUE)) == n 11 | } 12 | 13 | expect_true(has_string('')) 14 | expect_true(has_string('')) 15 | expect_true(has_string('')) 16 | }) 17 | 18 | test_that("Doesn't create empty directory for non self-contained RMarkdown", { 19 | skip_if_not(rmarkdown::pandoc_available("1.12.3")) 20 | 21 | temp_dir <- tempfile("metathis-rmd") 22 | dir.create(temp_dir) 23 | on.exit(unlink(temp_dir)) 24 | 25 | test_rmd_src <- test_path("rmd", "test-not-self-contained.Rmd") 26 | test_rmd <- file.path(temp_dir, "test.Rmd") 27 | file.copy(test_rmd_src, test_rmd) 28 | expect_silent(rmarkdown::render(test_rmd, quiet = TRUE)) 29 | out <- readLines(file.path(temp_dir, "test.html")) 30 | 31 | has_string <- function(str, n = 1L) { 32 | sum(grepl(str, out, fixed = FALSE)) == n 33 | } 34 | 35 | skip_if_not(has_package_version("rmarkdown", "2.9")) 36 | expect_true(has_string('')) 37 | expect_true(has_string('')) 38 | expect_true(has_string('')) 39 | 40 | out_files <- dir(file.path(temp_dir, "test_files")) 41 | expect_false(any(grepl("^metathis", out_files))) 42 | }) 43 | -------------------------------------------------------------------------------- /tests/testthat/test-social.R: -------------------------------------------------------------------------------- 1 | test_that("meta_social()", expect_true(TRUE)) 2 | 3 | describe("meta_social()", { 4 | it("finds description if already set", { 5 | .meta <- meta() %>% 6 | meta_description("test description") %>% 7 | meta_social( 8 | twitter_card_type = NULL, 9 | og_type = NULL, 10 | og_locale = NULL 11 | ) 12 | 13 | expect_true(sum(grepl("description", paste(.meta))) == 3) 14 | }) 15 | 16 | it("uses first description if already set", { 17 | expect_warning( 18 | .meta <- meta() %>% 19 | meta_description("abcdefg123456") %>% 20 | meta_description("not used for social") %>% 21 | meta_social( 22 | twitter_card_type = NULL, 23 | og_type = NULL, 24 | og_locale = NULL 25 | ) 26 | ) 27 | 28 | expect_true(sum(grepl("abcdefg123456", paste(.meta))) == 3) 29 | }) 30 | 31 | it("disables pinterest", { 32 | .meta <- meta() %>% 33 | meta_social(disable_pinterest = TRUE) 34 | 35 | expect_true( 36 | any(grepl("pinterest.+nopin", paste(.meta))) 37 | ) 38 | }) 39 | 40 | it("duplicates vector entries", { 41 | .meta <- meta() %>% 42 | meta_social( 43 | og_author = c("Apple", "Banana") 44 | ) %>% 45 | paste() 46 | 47 | expect_true(sum(grepl("article:author", .meta)) == 2) 48 | expect_true(sum(grepl("Apple", .meta)) == 1) 49 | expect_true(sum(grepl("Banana", .meta)) == 1) 50 | }) 51 | 52 | it("uses property for og: tags", { 53 | x <- meta_social( 54 | title = "R for Data Science", 55 | description = "This book with teach you how to do data science with R", 56 | url = "https://r4ds.had.co.nz", 57 | image = "https://r4ds.had.co.nz/cover.png", 58 | image_alt = "The cover of the R4DS book", 59 | og_type = "book", 60 | og_author = c("Garrett Grolemund", "Hadley Wickham"), 61 | twitter_card_type = "summary", 62 | twitter_creator = "@hadley" 63 | ) %>% 64 | as.character() 65 | 66 | x_og <- grep("og:", x, value = TRUE) 67 | expect_equal(sum(grepl("property=\"og:", x_og)), length(x_og)) 68 | }) 69 | }) 70 | -------------------------------------------------------------------------------- /tests/testthat/test-viewport.R: -------------------------------------------------------------------------------- 1 | # test_that() 2 | 3 | describe("meta_viewport()", { 4 | default_viewport <- '' 5 | it("creates a viewport meta tag", { 6 | expect_equal_meta(meta_viewport(), default_viewport) 7 | }) 8 | 9 | it("always comes first", { 10 | expect_equal_meta( 11 | meta() %>% 12 | meta_general(description = "defined first") %>% 13 | meta_viewport(), 14 | c( 15 | default_viewport, 16 | '' 17 | ) 18 | ) 19 | }) 20 | 21 | it("errors if everything is NULL", { 22 | expect_error(meta_viewport(meta(), NULL, NULL, NULL)) 23 | }) 24 | 25 | it("warns if too many width or height arguments are set", { 26 | expect_warning(meta_viewport(width = "100px", min_width = "100px")) 27 | expect_warning(meta_viewport(width = "100px", max_width = "100px")) 28 | expect_warning(meta_viewport(height = "100px", min_height = "100px")) 29 | expect_warning(meta_viewport(height = "100px", max_height = "100px")) 30 | }) 31 | }) 32 | -------------------------------------------------------------------------------- /tests/testthat/test-write.R: -------------------------------------------------------------------------------- 1 | describe("write_meta()", { 2 | 3 | it("writes to a file", { 4 | meta <- meta_tag(method = "test") %>% meta_viewport() 5 | tmp <- tempfile(fileext = ".html") 6 | write_meta(meta, tmp) 7 | expect_equal(readLines(tmp), as.character(meta)) 8 | }) 9 | 10 | it("appends to a file", { 11 | tmp <- tempfile(fileext = ".html") 12 | meta1 <- meta_tag(method = "first") %>% write_meta(tmp) 13 | meta2 <- meta_tag(method = "second") %>% write_meta(tmp, append = TRUE) 14 | expect_equal( 15 | readLines(tmp), 16 | c(as.character(meta1), as.character(meta2)) 17 | ) 18 | }) 19 | 20 | }) 21 | --------------------------------------------------------------------------------