[
  {
    "path": ".Rbuildignore",
    "content": "^hugodown\\.Rproj$\n^\\.Rproj\\.user$\n^LICENSE\\.md$\n^codecov\\.yml$\n^\\.github$\n^_pkgdown\\.yml$\n^docs$\n^pkgdown$\n"
  },
  {
    "path": ".gitattributes",
    "content": "*.Rmd text eol=lf\n"
  },
  {
    "path": ".github/.gitignore",
    "content": "*.html\n"
  },
  {
    "path": ".github/workflows/R-CMD-check.yaml",
    "content": "# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples\n# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help\n#\n# NOTE: This workflow is overkill for most R packages and\n# check-standard.yaml is likely a better choice.\n# usethis::use_github_action(\"check-standard\") will install it.\non:\n  push:\n    branches: [main, master]\n  pull_request:\n    branches: [main, master]\n\nname: R-CMD-check\n\njobs:\n  R-CMD-check:\n    runs-on: ${{ matrix.config.os }}\n\n    name: ${{ matrix.config.os }} (${{ matrix.config.r }})\n\n    strategy:\n      fail-fast: false\n      matrix:\n        config:\n          - {os: macOS-latest,   r: 'release'}\n\n          - {os: windows-latest, r: 'release'}\n          # Use 3.6 to trigger usage of RTools35\n          - {os: windows-latest, r: '3.6'}\n\n          - {os: ubuntu-latest,   r: 'devel', http-user-agent: 'release'}\n          - {os: ubuntu-latest,   r: 'release'}\n          - {os: ubuntu-latest,   r: 'oldrel-1'}\n          - {os: ubuntu-latest,   r: 'oldrel-2'}\n          - {os: ubuntu-latest,   r: 'oldrel-3'}\n          - {os: ubuntu-latest,   r: 'oldrel-4'}\n\n    env:\n      GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}\n      R_KEEP_PKG_SOURCE: yes\n\n    steps:\n      - uses: actions/checkout@v2\n\n      - uses: r-lib/actions/setup-pandoc@v2\n\n      - uses: r-lib/actions/setup-r@v2\n        with:\n          r-version: ${{ matrix.config.r }}\n          http-user-agent: ${{ matrix.config.http-user-agent }}\n          use-public-rspm: true\n\n      - uses: r-lib/actions/setup-r-dependencies@v2\n        with:\n          extra-packages: any::rcmdcheck\n          needs: check\n\n      - uses: r-lib/actions/check-r-package@v2\n        with:\n          upload-snapshots: true\n"
  },
  {
    "path": ".github/workflows/pkgdown.yaml",
    "content": "# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples\n# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help\non:\n  push:\n    branches: [main, master]\n  pull_request:\n    branches: [main, master]\n  release:\n    types: [published]\n  workflow_dispatch:\n\nname: pkgdown\n\njobs:\n  pkgdown:\n    runs-on: ubuntu-latest\n    # Only restrict concurrency for non-PR jobs\n    concurrency:\n      group: pkgdown-${{ github.event_name != 'pull_request' || github.run_id }}\n    env:\n      GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}\n    steps:\n      - uses: actions/checkout@v2\n\n      - uses: r-lib/actions/setup-pandoc@v2\n\n      - uses: r-lib/actions/setup-r@v2\n        with:\n          use-public-rspm: true\n\n      - uses: r-lib/actions/setup-r-dependencies@v2\n        with:\n          extra-packages: any::pkgdown, local::.\n          needs: website\n\n      - name: Build site\n        run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE)\n        shell: Rscript {0}\n\n      - name: Deploy to GitHub pages 🚀\n        if: github.event_name != 'pull_request'\n        uses: JamesIves/github-pages-deploy-action@4.1.4\n        with:\n          clean: false\n          branch: gh-pages\n          folder: docs\n"
  },
  {
    "path": ".github/workflows/pr-commands.yaml",
    "content": "# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples\n# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help\non:\n  issue_comment:\n    types: [created]\n\nname: Commands\n\njobs:\n  document:\n    if: ${{ github.event.issue.pull_request && (github.event.comment.author_association == 'MEMBER' || github.event.comment.author_association == 'OWNER') && startsWith(github.event.comment.body, '/document') }}\n    name: document\n    runs-on: ubuntu-latest\n    env:\n      GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}\n    steps:\n      - uses: actions/checkout@v2\n\n      - uses: r-lib/actions/pr-fetch@v2\n        with:\n          repo-token: ${{ secrets.GITHUB_TOKEN }}\n\n      - uses: r-lib/actions/setup-r@v2\n        with:\n          use-public-rspm: true\n\n      - uses: r-lib/actions/setup-r-dependencies@v2\n        with:\n          extra-packages: any::roxygen2\n          needs: pr-document\n\n      - name: Document\n        run: roxygen2::roxygenise()\n        shell: Rscript {0}\n\n      - name: commit\n        run: |\n          git config --local user.name \"$GITHUB_ACTOR\"\n          git config --local user.email \"$GITHUB_ACTOR@users.noreply.github.com\"\n          git add man/\\* NAMESPACE\n          git commit -m 'Document'\n\n      - uses: r-lib/actions/pr-push@v2\n        with:\n          repo-token: ${{ secrets.GITHUB_TOKEN }}\n\n  style:\n    if: ${{ github.event.issue.pull_request && (github.event.comment.author_association == 'MEMBER' || github.event.comment.author_association == 'OWNER') && startsWith(github.event.comment.body, '/style') }}\n    name: style\n    runs-on: ubuntu-latest\n    env:\n      GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}\n    steps:\n      - uses: actions/checkout@v2\n\n      - uses: r-lib/actions/pr-fetch@v2\n        with:\n          repo-token: ${{ secrets.GITHUB_TOKEN }}\n\n      - uses: r-lib/actions/setup-r@v2\n\n      - name: Install dependencies\n        run: install.packages(\"styler\")\n        shell: Rscript {0}\n\n      - name: Style\n        run: styler::style_pkg()\n        shell: Rscript {0}\n\n      - name: commit\n        run: |\n          git config --local user.name \"$GITHUB_ACTOR\"\n          git config --local user.email \"$GITHUB_ACTOR@users.noreply.github.com\"\n          git add \\*.R\n          git commit -m 'Style'\n\n      - uses: r-lib/actions/pr-push@v2\n        with:\n          repo-token: ${{ secrets.GITHUB_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/test-coverage.yaml",
    "content": "# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples\n# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help\non:\n  push:\n    branches: [main, master]\n  pull_request:\n    branches: [main, master]\n\nname: test-coverage\n\njobs:\n  test-coverage:\n    runs-on: ubuntu-latest\n    env:\n      GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}\n\n    steps:\n      - uses: actions/checkout@v2\n\n      - uses: r-lib/actions/setup-r@v2\n        with:\n          use-public-rspm: true\n\n      - uses: r-lib/actions/setup-r-dependencies@v2\n        with:\n          extra-packages: any::covr\n          needs: coverage\n\n      - name: Test coverage\n        run: covr::codecov(quiet = FALSE)\n        shell: Rscript {0}\n"
  },
  {
    "path": ".gitignore",
    "content": ".Rproj.user\n.Rhistory\n.RData\ndocs\ninst/doc\n"
  },
  {
    "path": "DESCRIPTION",
    "content": "Package: hugodown\nTitle: Make websites with hugo and RMarkdown\nVersion: 0.0.0.9000\nAuthors@R: c(\n    person(\"Hadley\", \"Wickham\", , \"hadley@rstudio.com\", role = c(\"aut\", \"cre\")),\n    person(\"RStudio\", role = \"cph\")\n  )\nDescription: hugodown is a minimal version of blogdown that only supports\n    hugo, and more clearly delineates the roles of RMarkdown (turning .Rmd\n    into .md) and hugo (turning .md into .html).\nLicense: MIT + file LICENSE\nURL: https://github.com/r-lib/hugodown\nBugReports: https://github.com/r-lib/hugodown/issues\nImports: \n    brio,\n    curl,\n    digest,\n    downlit,\n    evaluate,\n    fs,\n    later,\n    processx,\n    rappdirs,\n    RcppTOML,\n    rlang,\n    rmarkdown,\n    usethis (>= 1.6.0),\n    whisker,\n    whoami,\n    withr,\n    xml2,\n    yaml\nSuggests: \n    covr,\n    DiagrammeR,\n    gh,\n    htmltools,\n    knitr,\n    magick,\n    rstudioapi,\n    testthat (>= 3.0.0)\nVignetteBuilder: \n    knitr\nConfig/testthat/edition: 3\nEncoding: UTF-8\nLazyData: true\nRoxygen: list(markdown = TRUE)\nRoxygenNote: 7.2.1\n"
  },
  {
    "path": "LICENSE",
    "content": "YEAR: 2020\nCOPYRIGHT HOLDER: RStudio\n"
  },
  {
    "path": "LICENSE.md",
    "content": "# MIT License\n\nCopyright (c) 2020 RStudio\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "NAMESPACE",
    "content": "# Generated by roxygen2: do not edit by hand\n\nexport(create_site_academic)\nexport(embed_gist)\nexport(embed_instagram)\nexport(embed_tweet)\nexport(embed_vimeo)\nexport(embed_youtube)\nexport(hugo_browse)\nexport(hugo_build)\nexport(hugo_document)\nexport(hugo_install)\nexport(hugo_locate)\nexport(hugo_start)\nexport(hugo_stop)\nexport(hugo_version)\nexport(md_document)\nexport(shortcode)\nexport(site_outdated)\nexport(tidy_show_meta)\nexport(use_netlify_toml)\nexport(use_post)\nexport(use_tidy_post)\nexport(use_tidy_thumbnails)\nimport(fs)\nimport(rlang)\n"
  },
  {
    "path": "R/hugo-install.R",
    "content": "#' Install specified version of hugo\n#'\n#' Downloads binary from hugo releases, and installs in system wide cache.\n#'\n#' @param version String giving version (e.g. \"0.69.0\"). If omitted will\n#'   default to latest release.\n#' @param os Operating system, one of \"Linux\", \"Windows\", \"macOS\". Defaults\n#'   to current operating system.\n#' @param arch Architecture\n#' @param extended Installed hugo-extended which also includes SCSS etc?\n#' @export\n#' @examples\n#' \\dontrun{\n#' hugo_install()\n#' }\nhugo_install <- function(version = NULL, os = hugo_os(), arch = \"64bit\", extended = TRUE) {\n  if (!is_installed(\"gh\")) {\n    abort(\"`gh` package required to install Hugo from GitHub\")\n  }\n\n  message(\"Finding release\")\n  release <- hugo_release(version, os, arch, extended)\n\n  home <- hugo_home(release$version, os, arch, extended)\n  if (file.exists(home)) {\n    message(\"hugo \" , release$version, \" already installed\")\n    hugo_default_inc(release$version)\n    return(invisible())\n  }\n\n  message(\"Downloading \", path_file(release$url), \"...\")\n  temp <- curl::curl_download(release$url, tempfile())\n\n  message(\"Installing to \", path_dir(home), \"...\")\n  switch(path_ext(release$url),\n    \"gz\" = utils::untar(temp, exdir = home, tar = \"internal\"),\n    \"zip\" = utils::unzip(temp, exdir = home)\n  )\n  hugo_default_inc(release$version)\n\n  invisible()\n}\n\nhugo_default_inc <- function(version) {\n  cur <- hugo_default_get()\n  if (is.na(cur) || version > cur) {\n    hugo_default_set(version)\n  }\n}\nhugo_default_path <- function() {\n  path(rappdirs::user_cache_dir(\"hugodown\"), \"VERSION\")\n}\nhugo_default_get <- function() {\n  if (!file_exists(hugo_default_path())) {\n    NA\n  } else {\n    package_version(brio::read_lines(hugo_default_path())[[1]])\n  }\n}\nhugo_default_set <- function(version) {\n  path <- hugo_default_path()\n  if (is.na(version)) {\n    if (file_exists(path)) {\n      file_delete(path)\n    }\n  } else {\n    brio::write_lines(version, path)\n  }\n}\n\nhugo_installed <- function() {\n  path_file(dir_ls(rappdirs::user_cache_dir(\"hugodown\")))\n}\n\nhugo_home <- function(version, os = hugo_os(), arch = \"64bit\", extended = TRUE) {\n  cache_dir <- rappdirs::user_cache_dir(\"hugodown\")\n  dir_create(cache_dir)\n\n  hugo <- paste0(\n    \"hugo\", if (extended) \"_extended\", \"_\",\n    version, \"_\",\n    os, \"_\", arch\n  )\n  path(cache_dir, hugo)\n}\n\nhugo_release <- function(version = NULL, os = hugo_os(), arch = \"64bit\", extended = TRUE) {\n\n  json <- hugo_releases()\n  if (is.null(version)) {\n    i <- 1\n    version <- sub(\"^v\", \"\", json[[1]]$tag_name)\n  } else {\n    versions <- vapply(json, \"[[\", \"tag_name\", FUN.VALUE = character(1))\n    versions <- sub(\"^v\", \"\", versions)\n\n    i <- which(versions == version)\n    if (length(i) != 1) {\n      abort(paste0(\"Can't find version '\", version, '\"'))\n    }\n  }\n\n  assets <- json[[i]]$assets\n  names <- vapply(assets, \"[[\", \"name\", FUN.VALUE = character(1))\n\n  asset_name <- hugo_asset_name(version, os, arch, extended)\n  asset_i <- which(asset_name == names)\n  if (length(asset_i) != 1) {\n    abort(paste0(\"Can't find release asset with name '\", asset_name, \"'\"))\n  }\n\n  list(version = version, url = assets[[asset_i]]$browser_download_url)\n}\n\nhugo_releases <- function() {\n  if (env_has(hugodown, \"hugo_releases\")) {\n    env_get(hugodown, \"hugo_releases\")\n  } else {\n    json <- gh::gh(\n      \"GET /repos/:owner/:repo/releases\",\n      owner = \"gohugoio\",\n      repo = \"hugo\",\n      .limit = if (is.null(version)) 1 else Inf,\n      .progress = FALSE\n    )\n    env_poke(hugodown, \"hugo_releases\", json)\n    json\n  }\n}\n\nhugo_asset_name <- function(\n                            version,\n                            os = c(\"Linux\", \"Windows\", \"macOS\"),\n                            arch = \"64bit\",\n                            extended = TRUE) {\n\n  os <- arg_match(os)\n  ext <- switch(os, Windows = \".zip\", macOS = , Linux = \".tar.gz\")\n\n  paste0(\n    \"hugo\", if (extended) \"_extended\", \"_\",\n    version, \"_\",\n    os, \"-\", arch, ext\n  )\n}\n\nhugo_os <- function() {\n  sysname <- tolower(Sys.info()[[\"sysname\"]])\n  switch(sysname,\n    darwin = \"macOS\",\n    linux = \"Linux\",\n    windows = \"Windows\",\n    abort(\"Unknown operating system; please set `os`\")\n  )\n}\n"
  },
  {
    "path": "R/hugo-server.R",
    "content": "#' Manage the hugo server\n#'\n#' @section Hugo version:\n#' hugodown will attempt to automatically use the correct version of hugo for\n#' your site (prompting you to call [hugo_install()] if needed). It looks in\n#' two places:\n#'\n#' * If `_hugodown.yaml` is present, it looks for the `hugo_version` key.\n#' * If `netlify.toml` is present, it looks in\n#'   `context$production$environment$HUGO_VERSION`\n#'\n#' This means if you already use netlify, hugodown will automatically match\n#' the version of hugo that you're using for deployment.\n#'\n#' @description\n#' `hugo_start()` starts a hugo server that will automatically re-generate\n#' the site whenever the input changes. You only need to execute this once\n#' per session; it continues to run in the background as you work on the site.\n#' For large sites the hugo server can be slow to start; if it takes longer\n#' than 30 seconds `hugo_start()` throws an error.\n#'\n#' `hugo_stop()` kills the server. This happens automatically when you exit\n#' R so you shouldn't normally need to run this.\n#'\n#' `hugo_browse()` opens the site in the RStudio viewer or your web browser.\n#' @export\n#' @param site Path to hugo site.\n#' @param auto_navigate Automatically navigate to the most recently changed\n#'   page?\n#' @param browse Automatically preview the site after the server starts?\n#' @param render_to_disk Render site to disk? The default is to serve the\n#'   site from memory, but rendering to disk can be helpful for debugging.\n#' @param port Port to run server on. For advanced use only.\nhugo_start <- function(site = \".\",\n                         auto_navigate = TRUE,\n                         browse = TRUE,\n                         render_to_disk = FALSE,\n                         port = 1313) {\n  path <- site_root(site)\n  hugo_stop()\n\n  if (port_active(port)) {\n    abort(\"`hugo` already launched elsewhere.\")\n  }\n\n  message(\"Starting server on port \", port)\n  args <- c(\n    \"server\",\n    \"--port\", port,\n    \"--buildDrafts\",\n    \"--buildFuture\",\n    if (auto_navigate) \"--navigateToChanged\",\n    if (render_to_disk) \"--renderToDisk\"\n  )\n  ps <- hugo_run_bg(path, args, stdout = \"|\", stderr = \"2>&1\")\n  if (!ps$is_alive()) {\n    abort(ps$read_error())\n  }\n\n  # Swallow initial text\n  init <- \"\"\n  now <- proc.time()[[3]]\n  ok <- FALSE\n\n  while (proc.time()[[3]] - now < 30) {\n    ps$poll_io(250)\n    init <- paste0(init, ps$read_output())\n\n    if (grepl(\"Ctrl+C\", init, fixed = TRUE)) {\n      ok <- TRUE\n      break\n    }\n  }\n\n  if (!ok) {\n    ps$kill()\n    cat(init)\n    abort(\"Failed to start Hugo\")\n  }\n\n  # Ensure output pipe doesn't get swamped\n  poll_process <- function() {\n    if (!ps$is_alive()) {\n      return()\n    }\n\n    out <- ps$read_output()\n    if (!identical(out, \"\")) {\n      cat(out)\n    }\n\n    later::later(delay = 1, poll_process)\n  }\n  poll_process()\n\n  hugodown$server <- ps\n  if (browse) {\n    hugo_browse()\n  }\n\n  invisible(ps)\n}\n\n#' @rdname hugo_start\n#' @export\nhugo_stop <- function() {\n  if (!hugo_running()) {\n    return(invisible())\n  }\n\n  hugodown$server$interrupt()\n  hugodown$server$poll_io(500)\n  hugodown$server$kill()\n  env_unbind(hugodown, \"server\")\n  invisible()\n}\n\n#' @rdname hugo_start\n#' @export\nhugo_browse <- function() {\n  if (is_installed(\"rstudioapi\") && rstudioapi::hasFun(\"viewer\")) {\n    rstudioapi::viewer(\"http://localhost:1313\")\n  } else {\n    utils::browseURL(\"http://localhost:1313\")\n  }\n}\n\nhugo_running <- function() {\n  env_has(hugodown, \"server\") && hugodown$server$is_alive()\n}\n\nport_active <- function(port) {\n  tryCatch({\n    suppressWarnings(con <- socketConnection(\"127.0.0.1\", port, timeout = 1))\n    close(con)\n    TRUE\n  }, error = function(e) FALSE)\n}\n\n\n#' Build site\n#'\n#' Build static html into specified directory. Useful for debugging and some\n#' deployment scenarios\n#'\n#' @inheritParams hugo_start\n#' @param dest Destination directory. If `NULL`, the default, will build\n#'   in `{site}/public`\n#' @param build_drafts,build_future Should drafts and future posts be included\n#'   in the built site?\n#' @param clean Remove files in `public/` that don't exist in the source.\n#' @param base_url `<string>` Optionally override the `baseURL` setting from\n#'   hugo config.\n#' @param relative_urls `<bool>` Optionally the override the `relativeURL`\n#'   setting from hugo config.\n#' @export\nhugo_build <- function(site = \".\",\n                       dest = NULL,\n                       build_drafts = FALSE,\n                       build_future = FALSE,\n                       clean = FALSE,\n                       base_url = NULL,\n                       relative_urls = NULL\n                       ) {\n  path <- site_root(site)\n  dest <- dest %||% path(path, \"public\")\n\n  args <- c(\n    \"--destination\", dest,\n    if (build_drafts) \"--buildDrafts\",\n    if (build_future) \"--buildFuture\",\n    if (clean) \"--cleanDestinationDir\"\n  )\n\n  config <- c(\n    character(),\n    baseUrl = if (!is.null(base_url)) base_url,\n    relativeURLs = if (!is.null(relative_urls)) tolower(relative_urls)\n  )\n\n  hugo_run(path, args, config)\n  invisible()\n}\n"
  },
  {
    "path": "R/hugo-version.R",
    "content": "#' Find hugo version needed for current site\n#'\n#' @description\n#' Hugo changes rapidly, so it's important to pin your site to a specific\n#' version and then deliberately update when needed. This function reports\n#' which of hugo your site correctly uses.\n#'\n#' The primary location of this information is the `hugo_version` field\n#' in `hugodown.yaml`. If that doesn't exist, we also look in `netlify.toml`.\n#'\n#' @seealso [hugo_install()] to install any version of hugo.\n#' @inheritParams hugo_start\n#' @export\nhugo_version <- function(site = \".\") {\n  site <- site_root(site)\n\n  config <- site_config(site)\n  if (!is.null(config$hugo_version)) {\n    return(config$hugo_version)\n  }\n\n  netlify <- path(site, \"netlify.toml\")\n  if (file_exists(netlify)) {\n    toml <- RcppTOML::parseTOML(netlify)\n    # First look in production\n    version <- toml$context$production$environment$HUGO_VERSION\n    if (!is.null(version)) {\n      return(version)\n    }\n\n    # Then in all\n    version <- toml$build$environment$HUGO_VERSION\n    if (!is.null(version)) {\n      return(version)\n    }\n  }\n\n  warn(\"Couldn't find hugo version declaration; falling back to latest install\")\n  hugo_default_get()\n}\n"
  },
  {
    "path": "R/hugo.R",
    "content": "#' Locates a specific Hugo installation\n#'\n#' @param version The Hugo version to be located\n#'\n#' @return Returns the path to the Hugo installation, or an error if no\n#' Hugo install is found\n#' @export\nhugo_locate <- function(version = hugo_default_get()) {\n  path <- hugo_home(version)\n  if (!file_exists(path)) {\n    abort(c(\n      paste0(\"hugo \", version, \" not installed\"),\n      i = paste0(\"Do you need to call `hugodown::hugo_install('\", version, \"')`?\")\n    ))\n  }\n\n  path <- first_path(c(\n    path(path, \"hugo\"),\n    path(path, \"hugo\", ext = \"exe\")\n  ))\n  path_real(path)\n}\n\nhugo_run <- function(site, args, config = NULL, ...) {\n  if (length(config) > 0) {\n    names(config) <- paste0(\"HUGO_\", toupper(names(config)))\n  }\n\n  path <- site_root(site)\n  hugo <- hugo_locate(hugo_version(path))\n  processx::run(hugo, args, wd = path, env = config, ...)\n}\n\nhugo_run_bg <- function(site, args, ...) {\n  path <- site_root(site)\n  hugo <- hugo_locate(hugo_version(path))\n  processx::process$new(hugo, args, wd = path, ...)\n}\n\nhugo_config <- function(site = \".\", override = NULL) {\n  result <- hugo_run(site, \"config\", config = override)\n  if (result$status != 0) {\n    abort(paste0(\"Error running hugo config: \", result$stderr))\n  }\n\n  lines <- strsplit(result$stdout, \"\\n\", fixed = TRUE)[[1]]\n  vars <- regexec(\"^([A-Za-z0-9_]+)\\\\s*=\\\\s*([^\\n]+)$\", lines)\n  matches <- regmatches(lines, vars)\n\n  config <- lapply(matches, `[[`, 3)\n  names(config) <- lapply(matches, `[[`, 2)\n  config\n}\n\nhugo_config_str <- function(config, key) {\n  value <- config[[tolower(key)]]\n  sub(\"^\\\"?(.*?)\\\"?$\", \"\\\\1\", value)\n}\n\nhugo_config_bool <- function(config, key) {\n  value <- config[[tolower(key)]]\n  value == \"true\"\n}\n\nhugo_config_int <- function(config, key) {\n  value <- config[[tolower(key)]]\n  as.integer(value)\n}\n\n"
  },
  {
    "path": "R/hugodown-package.R",
    "content": "#' @keywords internal\n#' @import rlang\n#' @import fs\n\"_PACKAGE\"\n\nhugodown <- new_environment()\n\n# The following block is used by usethis to automatically manage\n# roxygen namespace tags. Modify with care!\n## usethis namespace: start\n## usethis namespace: end\nNULL\n"
  },
  {
    "path": "R/md-document.R",
    "content": "#' An Rmd output format that produces Hugo-flavoured markdown\n#'\n#' This RMarkdown output format is designed to generate markdown that is\n#' maximally compatible with Hugo. It intelligently generates a preview so\n#' that you see something useful when Hugo isn't running, but it doesn't\n#' get in the way of hugo's full-site preview when it is.\n#'\n#' @section Syntax highlighting:\n#'\n#' `md_document()` uses a hybrid system for syntax highlighting.\n#' For R code it uses [downlit](http://github.com/r-lib/downlit). For\n#' other languages, it relies on Chroma, the syntax highlighter built into\n#' hugo.\n#'\n#' @export\n#' @inheritParams rmarkdown::md_document\n#' @param fig_width Figure width (in inches).\n#' @param fig_asp Figure aspect ratio, defaults to the golden ratio.\n#' @param tidyverse_style Use tidyverse knitr conventions? This sets\n#'   `collapse = TRUE`, `comment = \"#>`, `fig.align = \"center\"`, and\n#'   `out.width = \"700px\"`.\nmd_document <- function(fig_width = 7,\n                        fig_asp = 0.618,\n                        fig_retina = 2,\n                        tidyverse_style = TRUE\n                        ) {\n\n  knitr <- rmarkdown::knitr_options_html(\n    fig_height = NULL,\n    fig_width = fig_width,\n    fig_retina = fig_retina,\n    keep_md = FALSE\n  )\n  knitr$opts_chunk$fig.asp <- fig_asp\n  knitr$opts_chunk$fig.path <- \"figs/\"\n  # Ensure knitr doesn't turn HTML widgets into pngs\n  knitr$opts_chunk$screenshot.force <- FALSE\n\n  knitr$knit_hooks <- knit_hooks()\n\n  if (tidyverse_style) {\n    knitr$opts_chunk$collapse <- TRUE\n    knitr$opts_chunk$comment <- \"#>\"\n    knitr$opts_chunk$fig.align <- \"center\"\n    knitr$opts_chunk$out.width <- \"700px\"\n  }\n\n  pandoc <- rmarkdown::pandoc_options(\n    to = goldmark_format(),\n    from = paste0(rmarkdown::rmarkdown_format(), \"+emoji\"),\n    args = \"--wrap=none\",\n    ext = \".md\"\n  )\n\n  input_rmd <- NULL\n  old_options <- NULL\n  old_env <- NULL\n\n  pre_knit <- function(input, ...) {\n    input_rmd <<- input\n    old_options <<- options(\n      cli.unicode = TRUE,\n      cli.num_colors = 8L,\n      cli.dynamic = FALSE,\n      crayon.enabled = TRUE\n    )\n    old_env <- set_envvar(c(RSTUDIO = 0))\n  }\n  on_exit <- function(...) {\n    options(old_options)\n    set_envvar(old_env)\n  }\n\n  hack_always_allow_html <- function(...) {\n    # This truly awful hack ensures that rmarkdown doesn't tell us we're\n    # producing HTML widgets\n    render_env <- env_parent(parent.frame())\n    render_env$front_matter$always_allow_html <- TRUE\n    NULL\n  }\n\n  knit_meta <- NULL\n  output_dir <- NULL\n  preprocess <- function(metadata, input_file, runtime, knit_meta, files_dir, output_dir) {\n    knit_meta <<- knit_meta\n    output_dir <<- output_dir\n    NULL\n  }\n\n  postprocess <- function(metadata, input_file, output_file, clean, verbose) {\n    old_yaml <- extract_yaml(brio::read_lines(input_file))\n\n    new_yaml <- list(rmd_hash = rmd_hash(input_rmd))\n    if (length(knit_meta) > 0) {\n      if (!is_installed(\"htmltools\")) {\n        abort(\"htmltools package required for posts that include HTML widgets\")\n      }\n\n      # Capture dependencies, remove duplicates, save to directory, and render\n      deps <- htmltools::resolveDependencies(knit_meta)\n      local <- lapply(deps, htmltools::copyDependencyToDir, outputDir = output_dir)\n      local <- lapply(local, htmltools::makeDependencyRelative, output_dir)\n      deps <- strsplit(htmltools::renderDependencies(local), \"\\n\")[[1]]\n      new_yaml$html_dependencies <- deps\n    }\n\n    body <- brio::read_file(output_file)\n\n    output_lines <- c(\n      \"---\", old_yaml, yaml::as.yaml(new_yaml), \"---\",\n      \"\",\n      link_inline(body)\n    )\n    brio::write_lines(output_lines, output_file)\n\n    # If server not running, and RStudio is rendering the doc, generate\n    # a standalone HTML file for preview\n    if (!port_active(1313) && !is.na(preview_dir())) {\n      output_html <- \"preview.html\"\n      rmarkdown::pandoc_convert(\n        input = output_file,\n        output = output_html,\n        to = \"html\",\n        options = preview_pandoc_args()\n      )\n      output_file <- file_move(output_html, preview_path())\n    } else {\n      output_file <- tempdir()\n    }\n\n    output_file\n  }\n\n  rmarkdown::output_format(\n    knitr = knitr,\n    pandoc = pandoc,\n    pre_processor = preprocess,\n    post_processor = postprocess,\n    pre_knit = pre_knit,\n    post_knit = hack_always_allow_html,\n    on_exit = on_exit\n  )\n}\n\ngoldmark_format <- function() {\n  paste(\n    \"markdown_strict\",\n    # https://github.com/rstudio/rstudio/blob/master/src/gwt/panmirror/src/editor/src/api/pandoc_format.ts#L344-L356\n    \"all_symbols_escapable\",\n    \"backtick_code_blocks\",\n    \"fenced_code_blocks\",\n    \"space_in_atx_header\",\n    \"intraword_underscores\",\n    \"lists_without_preceding_blankline\",\n    \"shortcut_reference_links\",\n    # https://github.com/rstudio/rstudio/blob/master/src/gwt/panmirror/src/editor/src/api/pandoc_format.ts#L380-L392\n    \"pipe_tables\",\n    \"strikeout\",\n    \"autolink_bare_uris\",\n    \"task_lists\",\n    \"definition_lists\",\n    \"footnotes\",\n    \"smart\",\n    \"tex_math_dollars\",\n    # custom\n    \"native_divs\",\n    \"emoji\",\n    sep = \"+\"\n  )\n}\n\npreview_pandoc_args <- function() {\n  template_path <- path_package(\n    \"rmarkdown/templates/github_document/resources/preview.html\",\n    package = \"rmarkdown\"\n  )\n  css_path <- path_package(\n    \"rmarkdown/templates/github_document/resources/github.css\",\n    package = \"rmarkdown\"\n  )\n\n  args <- c(\n    \"--standalone\",\n    \"--self-contained\",\n    \"--highlight-style\", \"pygments\",\n    \"--template\", template_path,\n    \"--email-obfuscation\", \"none\",\n    \"--variable\", paste0(\"github-markdown-css:\", css_path),\n    \"--metadata\", \"pagetitle=PREVIEW\"\n  )\n}\n\npreview_dir <- function() {\n  Sys.getenv(\"RMARKDOWN_PREVIEW_DIR\", unset = NA)\n}\npreview_path <- function() {\n  file_temp(\"preview-\", preview_dir(), ext = \"html\")\n}\n\nextract_yaml <- function(lines) {\n  delim <- grep(\"^---\\\\s*$\", lines)\n  if (length(delim) < 2) {\n    return(character())\n  }\n\n  lines[(delim[[1]] + 1):(delim[[2]] - 1)]\n}\n\n\n# knitr hooks -------------------------------------------------------------\n\nknit_hooks <- function() {\n  in_code <- FALSE\n  needs_code <- function(val, x, before = TRUE) {\n    if (val == in_code) {\n      return(x)\n    }\n\n    in_code <<- val\n    if (val) {\n      html <- \"<pre class='chroma'><code class='language-r' data-lang='r'>\"\n      ws <- \"\"\n    } else {\n      html <- \"</code></pre>\"\n\n      # move trailing newline after code\n      if (grepl(\"\\n$\", x)) {\n        x <- gsub(\"\\n$\", \"\", x)\n        ws <- \"\\n\"\n      } else {\n        ws <- \"\"\n      }\n    }\n\n    if (before) {\n      paste0(html, x, ws)\n    } else {\n      paste0(x, html, ws)\n    }\n  }\n\n  hook_output <- function(type, x, options) {\n    if (options$results == \"asis\") {\n      needs_code(FALSE, x)\n    } else {\n      x <- paste0(x, \"\\n\", collapse = \"\")\n      x <- highlight_if_possible(x, options$engine)\n      needs_code(TRUE, x)\n    }\n  }\n  hook_source <- function(x, options) {\n    x <- paste0(x, \"\\n\", collapse = \"\")\n    x <- highlight_if_possible(x, options$engine)\n    x <- paste0(x, \"\\n\")\n    needs_code(TRUE, x)\n  }\n  hook_plot <- function(x, options) {\n    # Repair damage done by pretending to be latex\n    if (grepl(\"linewidth\", options$out.width)) {\n      width <- as.numeric(gsub(\"\\\\\\\\linewidth\", \"\", options$out.width))\n      options$out.width <- paste0(width * 100, \"%\")\n    }\n\n    x <- knitr::hook_plot_md(x, options)\n    needs_code(FALSE, x)\n  }\n\n  hook_chunk <- function(x, options, ...) {\n    x <- needs_code(FALSE, x, before = FALSE) # reset for next chunk\n    x <- paste0(\"<div class='highlight'>\", x, \"</div>\")\n    indent(x, options$indent)\n  }\n\n  evaluate <- function(input, ...) {\n    # Setting output format to latex ensures that asis outputs are still\n    # passed to hook_output\n    Encoding(input) <- \"UTF-8\"\n    knitr::opts_knit$set(out.format = \"latex\")\n    evaluate::evaluate(input, ...)\n  }\n\n  list(\n    chunk   = hook_chunk,\n    evaluate = evaluate,\n    source  = hook_source,\n    plot    = hook_plot,\n    output  = function(x, opts) hook_output(\"output\", x, opts),\n    warning = function(x, opts) hook_output(\"warning\", x, opts),\n    error   = function(x, opts) hook_output(\"error\", x, opts),\n    message = function(x, opts) hook_output(\"message\", x, opts)\n  )\n}\n\n# if x is not valid R code, downlit::highlight will return NA\n# In this case, we return x without highlighting.\nhighlight_if_possible <- function(x, engine) {\n  if (engine != \"R\") {\n    x\n  } else {\n    out <- downlit::highlight(x, pre_class = NULL)\n    # replace curly operator with HTML entities\n    # otherwise Hugo will treat it as a shortcode\n    out <- gsub(\"\\\\{\", \"&#123;\", out)\n    out <- gsub(\"\\\\}\", \"&#125;\", out)\n    if (is.na(out)) {\n      x\n    } else {\n      out\n    }\n  }\n}\n\n\nindent <- function(x, indent) {\n  if (is.null(indent)) {\n    return(x)\n  }\n  paste0(indent, gsub(\"\\n\", paste0(\"\\n\", indent), x))\n}\n\n# inline code -------------------------------------------------------------\n\nlink_inline <- function(x) {\n  regexps <- c(\n    \"\\\\[[^\\\\]]+\\\\]\\\\([^\\\\)]*\\\\)\" , # link\n    \"(?m)^\\\\s*#{1,}.*$\", # heading\n    \"(?s)<pre.*?</pre>\" # code block\n  )\n  danger <- paste0(\"(\", regexps, \")\", collapse = \"|\")\n\n  protect_code <- function(x) gsub(\"`\", \"\\u241E\", x)\n  restore_code <- function(x) gsub(\"\\u241E\", \"`\", x)\n\n  x <- str_replace(x, danger, protect_code)\n  x <- str_replace(x, \"(?<!``)`([^`]+)`\", function(match) {\n    code <- gsub(\"^`|`$\", \"\", match)\n    href <- vapply(code, downlit::autolink_url, character(1))\n    ifelse(is.na(href), match, paste0(\"[\", match, \"](\", href, \")\"))\n  })\n  x <- str_replace(x, danger, restore_code)\n  x\n}\n\nstr_replace <- function(x, pattern, fun, ...) {\n  loc <- gregexpr(pattern, x, perl = TRUE)\n  matches <- regmatches(x, loc)\n  out <- lapply(matches, fun, ...)\n\n  regmatches(x, loc) <- out\n  x\n}\n\n#' Deprecated: please use `md_document()`\n#' @export\n#' @keywords internal\nhugo_document <- md_document\n"
  },
  {
    "path": "R/netlify.R",
    "content": "#' Create `netlify.toml`\n#'\n#' This helper creates a basic `netlify.toml` file, automatically setting the\n#' hugo version to match your blog. This is needed when publishing your site\n#' with [netlify](https://www.netlify.com); see `vignette(\"deploy\")` for more\n#' details.\n#'\n#' @export\n#' @inheritParams use_post\nuse_netlify_toml <- function(site = \".\") {\n  site <- site_root(site)\n\n  usethis::ui_done(\"Writing netlify.toml\")\n  whisker_template(\n    path_package(\"hugodown\", \"templates\", \"netlify.toml\"),\n    path(site, \"netlify.toml\"),\n    list(hugo_version = hugo_version(site))\n  )\n}\n"
  },
  {
    "path": "R/post.R",
    "content": "#' Create a new post\n#'\n#' Post creation takes advantage of Hugo's\n#' [archetypes](https://gohugo.io/content-management/archetypes/) or templates,\n#' with an extension for `.Rmd` files. `use_post()` first calls `hugo new`\n#' (which will apply go templating to `.md` files in the archetype),\n#' and then uses [whisker](https://github.com/edwindj/whisker) to template\n#' any `.Rmd` files.\n#'\n#'\n#' @param path Directory to create, like `blog/2020-my-favourite-package`.\n#' @param kind Kind of archetype of use; usually automatically derived\n#'   from the base directory of `path`.\n#' @param data Any additional data to be used when templating `.Rmd` files.\n#'\n#'   The default data includes:\n#'   * `date`: today's date (in YYYY-MM-DD format).\n#'   * `author`: [whoami::fullname()].\n#'   * `slug`: taken from the file name of `path`.\n#' @param site Path to the hugo site.\n#' @param open Open file for interactive editing?\n#' @export\nuse_post <- function(path, kind = NULL, data = list(), site = \".\", open = is_interactive()) {\n  site <- site_root(site)\n\n  tld <- path_dir(path)\n  if (!dir_exists(path(site, \"content\", tld))) {\n    abort(paste0(\"Can't find '\", tld, \"' directory in 'content/'\"))\n  }\n\n  dest <- path(site, \"content\", path)\n  if (file_exists(dest)) {\n    abort(paste0(\"`path` already exists\"))\n  }\n\n  args <- c(\n    \"new\", path,\n    if (!is.null(kind)) c(\"--kind\", kind)\n  )\n  hugo_run(site, args)\n\n\n  # Not a bundle\n  if (!file_exists(dest)) {\n    return()\n  }\n\n  rmds <- dir_ls(dest, glob = \"*.Rmd\")\n  defaults <- list(\n    slug = path_file(path),\n    title = unslug(path_file(path)),\n    author = whoami::fullname(\"Your name\"),\n    date = strftime(Sys.Date(), \"%Y-%m-%d\")\n  )\n  data <- utils::modifyList(defaults, data)\n\n  lapply(rmds, function(path) whisker_template(path, path, data))\n\n  index <- dir_ls(dest, pattern = \"index\")\n  usethis::edit_file(index, open = open)\n\n  invisible(dest)\n}\n\nwhisker_template <- function(in_path, out_path, data) {\n  file <- brio::read_file(in_path)\n  out <- whisker::whisker.render(file, data)\n  brio::write_lines(out, out_path)\n}\n"
  },
  {
    "path": "R/shortcode.R",
    "content": "#' Generate a hugo shortcode\n#'\n#' @description\n#' Generate a hugo shortcode with appropriate pandoc markup to preserve it as\n#' is when embedded in an R markdown document.\n#'\n#' Generally, I don't recommend calling this function directly; instead\n#' use it inside a function with the same name as the shortcode you want to\n#' wrap. See [embed_gist()] and friends for examples\n#'\n#' @param .name Name of the shortcode\n#' @param ... Arguments to the shortcode, supplied either by name or\n#'   position depending on the shortcode. By default, strings will\n#'   automatically be quoted with single quotes. Suppress this quoting\n#'   by wrapping the argument in `I()`.\n#' @param .contents Contents of the shortcode for paired shortcodes.\n#' @param .output Is the output of the shortcode html or markdown? This\n#'   controls whether the shortcode uses `<>` or `%`.\n#' @param .inline Is the shortcode designed to be used inline or in its own\n#'   paragraph? Controls whether the shortcode is wrapped in a block or inline\n#'   [raw attribute](https://pandoc.org/MANUAL.html#extension-raw_attribute).\n#' @export\n#' @examples\n#' pkg <- function(name) {\n#'   shortcode(\"pkg\", name, .inline = TRUE)\n#' }\n#' pkg(\"hugodown\")\nshortcode <- function(.name, ..., .contents = NULL, .output = c(\"html\", \"md\"), .inline = FALSE) {\n  call <- paste0(c(.name, shortcode_args(...)), collapse = \" \")\n  wrap <- switch(arg_match(.output),\n    html = function(x) paste0(\"{{< \", x, \" >}}\"),\n    md = function(x) paste0(\"{{% \", x, \" %}}\"),\n  )\n\n  if (is.null(.contents)) {\n    out <- wrap(call)\n  } else {\n    out <- paste0(wrap(call), .contents, wrap(paste0(\"/\", .name)))\n  }\n\n  if (.inline) {\n    paste0(\"`\", out, \"`{=html}\")\n  } else {\n    paste0(\"```{=html}\\n\", out, \"\\n```\\n\")\n  }\n}\n\nshortcode_args <- function(...) {\n  args <- list2(...)\n  args <- args[!vapply(args, is.null, logical(1))]\n\n  if (length(args) == 0) {\n    return(NULL)\n  }\n\n  names <- names2(args)\n\n  as_value <- function(x) {\n    if (is.character(x) && !inherits(x, \"AsIs\")) {\n      encodeString(x, quote = \"'\")\n    } else {\n      format(x)\n    }\n  }\n  values <- vapply(args, as_value, character(1))\n  equals <- ifelse(names == \"\", \"\", \"=\")\n\n  paste0(names, equals, values, collapse = \" \")\n}\n\n\n#' Generate hugo shortcodes to embed various types of media\n#'\n#' @description\n#' These are wrappers that make it easy to generate\n#' [hugo shortcodes](https://gohugo.io/content-management/shortcodes/) that\n#' make it easy to embed various types of media into your pages. You use from\n#' inline R code like:\n#'\n#' ```\n#' This tweet announced the release of hugo 0.24:\n#'\n#' `R embed_tweet(\"877500564405444608\")`\n#' ```\n#'\n#' @param username GitHub/Twitter user name\n#' @param id A string giving the object id. You'll usually find this by\n#'  inspecting the URL:\n#'  * gist: `https://gist.github.com/spf13/7896402` -> `7896402`\n#'  * instagram: `https://www.instagram.com/p/BWNjjyYFxVx/` -> `BWNjjyYFxVx`\n#'  * twitter: `https://twitter.com/spf13/status/877500564405444608` -> `877500564405444608`\n#'  * vimeo: `https://vimeo.com/channels/staffpicks/146022717` -> `146022717`\n#'  * youtube: `https://www.youtube.com/watch?v=w7Ft2ymGmfc` -> `w7Ft2ymGmfc`\n#' @param filename Pick single file from multiple file gist\n#' @export\nembed_gist <- function(username, id, filename = NULL) {\n  shortcode(\"gist\", username, id, filename)\n}\n#' @param caption Show instagram caption?\n#' @export\n#' @rdname embed_gist\nembed_instagram <- function(id, caption = TRUE) {\n  stopifnot(is.character(id))\n  shortcode(\"instagram\", I(id), if (!caption) I(\"hidecaption\"))\n}\n#' @export\n#' @rdname embed_gist\nembed_tweet <- function(id, username = NULL) {\n  stopifnot(is.character(id))\n  shortcode(\"tweet\", username = username, id = id)\n}\n#' @export\n#' @rdname embed_gist\nembed_vimeo <- function(id) {\n  stopifnot(is.character(id))\n  shortcode(\"vimeo\", I(id))\n}\n#' @param autoplay Automatically play youtube video?\n#' @export\n#' @rdname embed_gist\nembed_youtube <- function(id, autoplay = FALSE) {\n  stopifnot(is.character(id))\n\n  if (autoplay) {\n    shortcode(\"youtube\", id = I(id), autoplay = \"true\")\n  } else {\n    shortcode(\"youtube\", id = id)\n  }\n}\n"
  },
  {
    "path": "R/site-academic.R",
    "content": "#' Create a hugo academic site\n#'\n#' @description\n#' Create a hugo academic 4.8.0 site, configured to work well with hugodown.\n#' In particular, it ensures that the following features important for R\n#' users work correctly:\n#'\n#' * Syntax highlighting (turns off default js highlighting, renables\n#'   default chroma, and sets up styles in `assets/chroma.css`).\n#'\n#' * Math\n#'\n#' * HTML widgets\n#'\n#' * Default post archetype is tweaked to create `.Rmd`\n#' @param path Path to create site\n#' @param open Open new site after creation?\n#' @param rstudio Create RStudio project?\n#' @export\ncreate_site_academic <- function(\n                                 path = \".\",\n                                 open = is_interactive(),\n                                 rstudio = rstudioapi::isAvailable()) {\n  # Use most recent version that release was tested with\n  # https://sourcethemes.com/academic/updates/v4.8.0/#breaking-changes\n  hugo_locate(\"0.66.0\")\n\n  dir_create(path)\n  usethis::ui_silence(old <- usethis::proj_set(path, force = TRUE))\n  on.exit(usethis::ui_silence(usethis::proj_set(old)))\n\n  use_rstudio_website_proj(path)\n\n  usethis::ui_done(\"Downloading academic theme\")\n  theme_dir <- academic_download(\"4.8.0\")\n\n  usethis::ui_done(\"Copying site components\")\n  dir_copy_contents(path(theme_dir, \"exampleSite\"), path)\n\n  usethis::ui_done(\"Installing academic theme\")\n  academic_install(path, theme_dir)\n\n  usethis::ui_done(\"Patching theme for hugodown compatibility\")\n  academic_patch(path)\n\n  if (open) {\n    usethis::proj_activate(path)\n  }\n  invisible(path)\n}\n\nacademic_download <- function(version = \"4.8.0\") {\n  zip <- curl::curl_download(\n    paste0(\"https://github.com/wowchemy/wowchemy-hugo-modules/archive/v\", version, \".zip\"),\n    file_temp(\"hugodown\")\n  )\n  exdir <- file_temp(\"hugodown\")\n  utils::unzip(zip, exdir = exdir)\n  path(exdir, paste0(\"wowchemy-hugo-modules-\", version))\n}\n\nacademic_install <- function(path, theme_dir) {\n  theme_path <- dir_create(path(path, \"themes\", \"academic\"))\n  dir_copy_contents(theme_dir, theme_path)\n  dir_delete(path(theme_path, \"exampleSite\"))\n}\n\n# Patch existing theme ----------------------------------------------------\n\nacademic_patch <- function(path) {\n  config_path <- file_move(path(path, \"config\", \"_default\", \"config.toml\"), path)\n  academic_patch_config(config_path)\n  academic_patch_params(path(path, \"config\", \"_default\", \"params.toml\"))\n  academic_write_hugodown(path)\n\n  # Create Rmd post archetype\n  # Must modify template because site archetype is _unioned_ with template\n  post_archetype <- path(path, \"themes\", \"academic\", \"archetypes\", \"post\")\n  file_move(path(post_archetype, \"index.md\"), path(post_archetype, \"index.Rmd\"))\n  academic_patch_post_archetype(path(post_archetype, \"index.Rmd\"))\n\n  # Patch <head>\n  academic_write_custom_head(path)\n\n  usethis::use_git_ignore(c(\"resources\", \"public\"))\n  file_copy(path_package(\"hugodown\", \"academic\", \"README.md\"), path)\n  file_copy(path_package(\"hugodown\", \"academic\", \"index.Rmd\"), path)\n}\n\nacademic_patch_config <- function(path) {\n  lines <- brio::read_lines(path)\n\n  # Ignore knitr intermediates\n  knitr_ignore <- \"ignoreFiles = ['\\\\.Rmd$', '_files$', '_cache$', '\\\\.knit\\\\.md$', '\\\\.utf8\\\\.md$']\"\n  lines <- line_replace(lines, \"^ignoreFiles\", knitr_ignore)\n\n  # Use goldmark syntax higlighting (change in params.toml suppresses highlight.js)\n  lines <- line_replace(lines, \"    codeFences = false\", \"    codeFences = true\")\n\n  # Use highlight classes\n  lines <- line_insert_after(lines, \"^ignoreFiles\", \"pygmentsUseClasses = true\")\n\n  brio::write_lines(lines, path)\n}\n\nacademic_patch_params <- function(path) {\n  lines <- brio::read_lines(path)\n\n  # Turn math on & js highlighting off\n  lines <- line_replace(lines, \"math = false\", \"math = true\")\n  lines <- line_replace(lines, \"highlight = true\", \"highlight = false\")\n\n  brio::write_lines(lines, path)\n}\n\nacademic_write_hugodown <- function(path) {\n  opts <- list(\n    hugo_version = \"0.66.0\"\n  )\n  yaml::write_yaml(opts, path(path, \"_hugodown.yaml\"))\n}\n\nacademic_patch_post_archetype <- function(path) {\n  lines <- brio::read_lines(path)\n  lines <- c(lines[1],\n    \"output: hugodown::md_document\",\n    lines[-1]\n  )\n  lines <- line_replace(lines,\n    'title: \"{{ replace .Name \"-\" \" \" | title }}',\n    'title: \"{{ title }}\"',\n    fixed = TRUE\n  )\n  lines <- line_replace(lines, 'date: {{ .Date }}', 'date: {{ date }}', fixed = TRUE)\n  lines <- line_replace(lines, 'lastmod: {{ .Date }}', 'lastmod: {{ date }}', fixed = TRUE)\n\n  brio::write_lines(lines, path)\n}\n\nacademic_write_custom_head <- function(path) {\n  # hugo gen chromastyles --style=github > inst/academic/highlight-light.css\n  # hugo gen chromastyles --style=dracula > inst/academic/highlight-dark.css\n\n  dir_create(path(path, \"static\", \"css\"))\n  file_copy(path_package(\"hugodown\", \"academic\", \"highlight-light.css\"), path(path, \"static\", \"css\"))\n  file_copy(path_package(\"hugodown\", \"academic\", \"highlight-dark.css\"), path(path, \"static\", \"css\"))\n\n  head <- path(path, \"layouts\", \"partials\", \"custom_head.html\")\n  dir_create(path_dir(head))\n\n  brio::write_lines(c(\n    \"<link rel='stylesheet' href='{{ \\\"css/highlight-light.css\\\" | relURL }}' title='hl-light'>\",\n    \"<link rel='stylesheet' href='{{ \\\"css/highlight-dark.css\\\" | relURL }}' title='hl-dark' disabled>\",\n    \"{{ range .Params.html_dependencies }}\",\n    \"  {{ . | safeHTML }}\",\n    \"{{ end }}\"\n  ), head)\n}\n\n# Helpers -----------------------------------------------------------------\n\nline_find <- function(x, pattern, fixed = FALSE) {\n  ignore <- grep(pattern, x, fixed = fixed)\n  if (length(ignore) != 1) {\n    abort(paste0(\"Found \", length(ignore), \" matching lines\"))\n  }\n  ignore\n}\nline_replace <- function(x, pattern, replacement, fixed = FALSE) {\n  x[line_find(x, pattern, fixed = fixed)] <- replacement\n  x\n}\nline_insert_after <- function(x, pattern, lines) {\n  n <- length(x)\n  i <- line_find(x, pattern)\n  c(x[1:i], lines, x[(i + 1):n])\n}\n\ndir_copy_contents <- function(path, new_path) {\n  for (path in dir_ls(path)) {\n    if (is_file(path)) {\n      file_copy(path, path(new_path, path_file(path)))\n    } else {\n      dir_copy(path, path(new_path, path_file(path)))\n    }\n  }\n}\n\n# Replace after https://github.com/r-lib/usethis/issues/1153\nuse_rstudio_website_proj <- function(path) {\n  project_name <- path_file(path_abs(path))\n  rproj_file <- paste0(project_name, \".Rproj\")\n  new <- usethis::use_template(\"template.Rproj\",\n    rproj_file,\n    package = \"hugodown\"\n  )\n  usethis::use_git_ignore(\".Rproj.user\")\n}\n"
  },
  {
    "path": "R/site.R",
    "content": "site_root <- function(path = \".\") {\n  path <- as.character(path_abs(path))\n\n  while (!identical(path, path_dir(path))) {\n    if (file_exists(path(path, \"config.yaml\"))) {\n      return(path)\n    }\n    if (file_exists(path(path, \"config.yml\"))) {\n      return(path)\n    }\n    if (file_exists(path(path, \"config.toml\"))) {\n      return(path)\n    }\n    path <- path_dir(path)\n  }\n\n  abort(\"Can't find 'config.yml' or 'config.toml'\")\n}\n\nsite_config <- function(path = \".\") {\n  site <- site_root(path)\n  site_yaml <- path(site, \"_hugodown.yaml\")\n\n  if (!file_exists(site_yaml)) {\n    NULL\n  } else {\n    yaml::read_yaml(site_yaml)\n  }\n}\n\n#' Find `.Rmd`s that need to be re-rendered.\n#'\n#' [md_document()] adds a hash of the input `.Rmd` in the YAML metdata of\n#' the `.md` file that it creates. This provides a reliable way to determine\n#' whether or not a `.Rmd` has been changed since the last time the `.md`\n#' was rendered.\n#'\n#' @param site Path to hugo site.\n#' @export\nsite_outdated <- function(site = \".\") {\n  site <- site_root(site)\n\n  rmd <- dir_ls(path(site, \"content\"), recurse = TRUE, regexp = \"\\\\.Rmd$\")\n  rmd <- rmd[vapply(rmd, rmd_needs_render, logical(1))]\n  rmd\n}\n\nrmd_needs_render <- function(path) {\n  # Has .html, so must've been rendered by blogdown\n  if (file_exists(path_ext_set(path, \"html\"))) {\n    return(FALSE)\n  }\n\n  md_path <- path_ext_set(path, \"md\")\n  if (!file_exists(md_path)) {\n    return(TRUE)\n  }\n\n  yaml <- rmarkdown::yaml_front_matter(md_path)\n  hash <- yaml$rmd_hash\n  if (is.null(hash)) {\n    return(FALSE)\n  }\n\n  hash != rmd_hash(path)\n}\n\nrmd_hash <- function(path) {\n  digest::digest(path, file = TRUE, algo = \"xxhash64\")\n}\n\nhugodown_site <- function(input = \".\", output_format = NULL) {\n  # read config and output directory\n  config <- hugo_config(input)\n  output_dir <- hugo_config_str(config, \"publishdir\")\n\n  list(\n    # name for site (used as default name for publishing)\n    name = hugo_config_str(config, \"title\"),\n\n    # output directory (e.g. \"public\")\n    output_dir = output_dir,\n\n    # render_site callback\n    render = function(input_file, output_format, envir, quiet, ...) {\n\n      # Render the entire site\n      if (is.null(input_file)) {\n\n        # render outdated rmds\n        lapply(site_outdated(input), function(rmd) {\n          cat(\"Rendering modified Rmd:\", fs::path_rel(rmd, input), \"\\n\")\n          rmarkdown::render(\n            input = rmd,\n            output_format = output_format,\n            envir = envir,\n            quiet = quiet,\n            ...\n          )\n        })\n\n        # build with relative urls so that the site is deployable anywhere\n        hugo_build(input, relative_urls = TRUE)\n\n        if (!quiet) {\n          cat(\"Hugo site built:\", file.path(input, output_dir))\n        }\n\n        # render just a single file (this hook is for doing incremental\n        # renders of the site based on a \"Knit\" in the IDE). Since\n        # hugodown already handles this well w/ just delegate here to\n        # rmarkdown::render.\n      } else {\n        rmarkdown::render(\n          input = input_file,\n          output_format = output_format,\n          envir = envir,\n          quiet = quiet,\n          ...\n        )\n      }\n    },\n\n    # relative path to outputs that require cleaning\n    clean = function() {\n      files <- output_dir\n      files[file.exists(file.path(input, files))]\n    }\n  )\n}\n"
  },
  {
    "path": "R/test-fixtures.R",
    "content": "local_file <- function(path, env = parent.frame()) {\n  tmp <- dir_create(file_temp())\n  withr::defer(dir_delete(tmp), envir = env)\n\n  file_copy(path, tmp)\n}\n\nlocal_render <- function(path, env = parent.frame()) {\n  tmp_path <- local_file(path, env = env)\n  rmarkdown::render(tmp_path, quiet = TRUE)\n  out_path <- path_ext_set(tmp_path, \"md\")\n\n  lines <- brio::read_lines(out_path)\n  xml <- paste(\"<html>\", paste0(lines[-(1:5)], collapse = \"\\n\"), \"</html>\")\n\n  list(\n    src = path,\n    dst = out_path,\n    dir = path_dir(out_path),\n    lines = lines,\n    xml = xml2::read_html(xml)\n  )\n}\n\nlocal_dir <- function(path, env = parent.frame()) {\n  tmp <- file_temp(\"hugodown-\")\n  withr::defer(dir_delete(tmp), envir = env)\n\n  dir_copy(path, tmp)\n}\n\nskip_if_no_hugo <- function() {\n  if (is.na(hugo_default_get())) {\n    testthat::skip(\"hugo not installed\")\n  }\n  if (hugo_default_get() < \"0.72\") {\n    testthat::skip(\"need at least hugo 0.72\")\n  }\n}\n"
  },
  {
    "path": "R/tidy.R",
    "content": "#' Various helpers for tidyverse.org and similar sites\n#'\n#' * `use_tidy_post()` makes a new post\n#' * `use_tidy_thumbnails()` resizes thumbnails to the correct size\n#' * `tidy_show_meta()` prints tags and categories used by existing posts.\n#'\n#' @export\n#' @param slug File name of new post. Year and month will be automatically\n#'   appended.\n#' @inheritParams use_post\nuse_tidy_post <- function(slug, site = \".\", open = is_interactive()) {\n  check_slug(slug)\n\n  post_slug <- paste0(\"blog/\", tolower(slug))\n  data <- list(\n    pleased = tidy_pleased()\n  )\n  pieces <- strsplit(slug, \"-\")[[1]]\n  if (is_installed(pieces[[1]])) {\n    data$package <- pieces[[1]]\n    data$version <- utils::packageVersion(pieces[[1]])\n  }\n\n  use_post(post_slug, data = data, site = site, open = open)\n}\n\n#' @rdname use_tidy_post\n#' @export\n#' @param path Path to blog post\nuse_tidy_thumbnails <- function(path = NULL) {\n  if (!is_installed(\"magick\")) {\n    abort(\"Need to install magick package\")\n  }\n\n  path <- path %||% path_dir(active_file())\n\n  path_sq <- path(path, \"thumbnail-sq.jpg\")\n  if (!file_exists(path_sq)) {\n    abort(\"Can't find 'thumbnail-sq.jpg'\")\n  }\n  path_wd <- path(path, \"thumbnail-wd.jpg\")\n  if (!file_exists(path_wd)) {\n    abort(\"Can't find 'thumbnail-wd.jpg'\")\n  }\n\n  thumb_sq <- magick::image_read(path_sq)\n  thumb_wd <- magick::image_read(path_wd)\n\n  info_sq <- magick::image_info(thumb_sq)\n  info_wd <- magick::image_info(thumb_wd)\n\n  if (info_sq$width != info_sq$height) {\n    abort(\"'thumbnail-sq.jpg' is not square\")\n  }\n  if (info_wd$width / (info_wd$height / 200) < 1000) {\n    abort(\"'thumbnail-wd.jpg' is too narrow; must be >5 wider than tall\")\n  }\n\n  magick::image_write(magick::image_scale(thumb_sq, \"300x300\"), path_sq, quality = 90)\n  magick::image_write(magick::image_scale(thumb_wd, \"x200\"), path_wd, quality = 90)\n\n  invisible()\n}\n\n#' @rdname use_tidy_post\n#' @export\n#' @param min Minimum number of uses\ntidy_show_meta <- function(min = 1, site = \".\") {\n  site <- site_root(site)\n  rmd <- dir_ls(path(site, \"content\"), recurse = TRUE, regexp = \"\\\\.(Rmd|Rmarkdown)$\")\n\n  yaml <- lapply(rmd, rmarkdown::yaml_front_matter)\n\n  tags <- unlist(lapply(yaml, \"[[\", \"tags\"), use.names = FALSE)\n  tags_df <- as.data.frame(table(tags), responseName = \"n\")\n  tags_df <- tags_df[tags_df$n >= min, , drop = FALSE]\n\n  cats <- unlist(lapply(yaml, \"[[\", \"categories\"), use.names = FALSE)\n  cats_df <- as.data.frame(table(cats), responseName = \"n\")\n  cats_df <- cats_df[cats_df$n >= min, , drop = FALSE]\n\n  cat_line(\"## Categories\")\n  cat_line(\"* \", cats_df$cats, \" (\", cats_df$n, \")\")\n  cat_line()\n  cat_line(\"## Tags\")\n  cat_line(\"* \", tags_df$tags, \" (\", tags_df$n, \")\")\n\n  invisible()\n}\n\n\n# helpers -----------------------------------------------------------------\n\ncheck_slug <- function(slug) {\n  if (!is.character(slug) || length(slug) != 1) {\n    abort(\"`slug` must be a single string\")\n  }\n\n  if (grepl(\"[ ._]\", slug)) {\n    abort(c(\n      \"`slug` must not contain any spaces, `.`, or `_`\",\n      i = \"Separate words with -\"\n    ))\n  }\n}\n\nunslug <- function(x) {\n  gsub(\"-\", \" \", x)\n}\n\ntidy_pleased <- function() {\n  phrases <- list(\n    chuffed =     c(\"\"),\n    pleased =     c(\"\", \"most\", \"very\", \"extremely\", \"well\"),\n    stoked =      c(\"\"),\n    chuffed =     c(\"\", \"very\"),\n    happy =       c(\"\", \"so\", \"very\", \"exceedingly\"),\n    thrilled =    c(\"\"),\n    delighted =   c(\"\"),\n    \"tickled pink\" = c(\"\")\n  )\n\n  i <- sample(length(phrases), 1)\n\n  word <- names(phrases)[[i]]\n  modifier <- sample(phrases[[i]], 1)\n\n  paste0(modifier, if (modifier != \"\") \" \", word)\n}\n\nactive_file <- function(ext = NULL) {\n  if (!is_installed(\"rstudioapi\") || !rstudioapi::isAvailable()) {\n    abort(\"Must supply `path` outside of RStudio\")\n  }\n\n  path <- rstudioapi::getSourceEditorContext()$path\n\n  if (!is.null(ext) && path_ext(path) != ext) {\n    abort(paste0(\"Open file must have extension (\", ext, \")\"))\n  }\n\n  path\n}\n\ncat_line <- function(...) cat(paste0(..., \"\\n\", collapse = \"\"))\n"
  },
  {
    "path": "R/utils.R",
    "content": "first_path <- function(paths) {\n  for (path in paths) {\n    if (file_exists(path)) {\n      return(path)\n    }\n  }\n\n  abort(c(\n    \"Can't find any of the following candidate paths\",\n    paths\n  ))\n}\n\n# copies from withr\nset_envvar <- function(envs, action = \"replace\") {\n  if (length(envs) == 0) return()\n\n  stopifnot(is_named(envs))\n  stopifnot(is.character(action), length(action) == 1)\n  action <- match.arg(action, c(\"replace\", \"prefix\", \"suffix\"))\n\n  # if there are duplicated entries keep only the last one\n  envs <- envs[!duplicated(names(envs), fromLast = TRUE)]\n\n  old <- Sys.getenv(names(envs), names = TRUE, unset = NA)\n  set <- !is.na(envs)\n\n  both_set <- set & !is.na(old)\n  if (any(both_set)) {\n    if (action == \"prefix\") {\n      envs[both_set] <- paste(envs[both_set], old[both_set])\n    } else if (action == \"suffix\") {\n      envs[both_set] <- paste(old[both_set], envs[both_set])\n    }\n  }\n\n  if (any(set))  do.call(\"Sys.setenv\", as.list(envs[set]))\n  if (any(!set)) Sys.unsetenv(names(envs)[!set])\n\n  invisible(old)\n}\n\n\n# helpers for testing -----------------------------------------------------\n\nxpath_xml <- function(x, xpath = \".\") {\n  x <- xml2::xml_find_all(x, xpath)\n  structure(x, class = c(\"pkgdown_xml\", class(x)))\n}\nxpath_attr <- function(x, xpath, attr) {\n  gsub(\"\\r\", \"\", xml2::xml_attr(xml2::xml_find_all(x, xpath), attr), fixed = TRUE)\n}\nxpath_text <- function(x, xpath = \".\", trim = FALSE) {\n  xml2::xml_text(xml2::xml_find_all(x, xpath), trim = trim)\n}\nxpath_length <- function(x, xpath = \".\") {\n  length(xml2::xml_find_all(x, xpath))\n}\n"
  },
  {
    "path": "README.md",
    "content": "\n# hugodown <img src='man/figures/logo.png' align=\"right\" height=\"138.5\" />\n\n<!-- badges: start -->\n[![Lifecycle: experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://www.tidyverse.org/lifecycle/#experimental)\n[![R-CMD-check](https://github.com/r-lib/hugodown/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/r-lib/hugodown/actions/workflows/R-CMD-check.yaml)\n[![Codecov test coverage](https://codecov.io/gh/r-lib/hugodown/branch/master/graph/badge.svg)](https://codecov.io/gh/r-lib/hugodown?branch=master)\n<!-- badges: end -->\n\nhugodown is an experimental package that aims to facilitate the use of [RMarkdown](http://rmarkdown.rstudio.com/) and [hugo](http://gohugo.io/) together. It's similar to [blogdown](https://bookdown.org/yihui/blogdown/), but is focussed purely on Hugo websites, and enforces a stricter partitioning of roles: hugodown is responsible for transforming `.Rmd` to `.md`, and hugo is responsible for transforming `.md` to `.html`.\n\n## Compared to blogdown\n\n* It only re-runs your R code when you explicitly ask for it (by knitting the \n  post). This makes hugodown considerably easier to use for long-running blogs \n  and blogs with multiple contributors. \n  \n* Local previews are pinned to a specific version of hugo. This makes it easier\n  to work with multiple blogs, and protects your from hugo <-> theme \n  version incompatibilities.\n  \n* It provides support for getting started with a limited number of themes,\n  automatically making needed tweaks to ensure that html widgets, syntax \n  highlighting, and math display work out of the box.\n\n* It does not currently support within page cross-references for figures, \n  tables, and equations.\n\n* It is more opinionated about hugo configuration; see `vignette(\"config\")` \n  for details.\n  \n* It is designed around a single Rmarkdown format, `.Rmd`.\n\n## Installation\n\nhugodown isn't available from CRAN yet (and might never be), but you can install the development version from GitHub with:\n\n``` r\ndevtools::install_github(\"r-lib/hugodown\")\n```\n\n## Usage\n\nThe key to using hugodown is to put `output: hugodown::md_document()` in the YAML metadata of your `.Rmd` files. Then knitting the file will generate a `.md` file designed to work well with hugo. The rest of hugodown just makes your life a little easier:\n\n* `hugo_start()` will automatically start a hugo server in the background,\n  automatically previewing your site as you update it.\n\n* `use_post()` will create a new post (filling in default content from\n  the hugo [archetype](https://gohugo.io/content-management/archetypes/)).\n  \n* To knit an `.Rmd` post, you can use the Knit button to knit to the correct output format. You can also use the keyboard shortcut `Cmd+Shift+K` (Mac) or `Ctrl+Shift+K` (Windows/Linux).\n  \n* `site_outdated()` lists all `.Rmd` files that need to be re-rendered \n  (i.e. they have changed since the last time their `.md` was rendered).\n  \nWith hugodown, knitting an individual post and building the site are two separate processes. A good workflow when working with an existing Hugo site in RStudio is to open the site's `.Rproj` file, use `hugo_start()`, then add or edit your posts. Because the hugo server will only add `.Rmd` content to your site preview after knitting, you'll need to use the keyboard shortcut to knit first.\n\n### Citations\n\nTo use citations in a blog post, just provide a `bibliography` in the YAML metadata. If you want to use footnotes for citations (a style that generally works well in blogs), you'll need to find a footnote style CSL file (e.g. [`chicago-fullnote-bibliography.csl`][footnote-csl], and use the following YAML header.\n\n```yaml\nbibliography: refs.bib\nsuppress-bibliography: true\ncsl: chicago-fullnote-bibliography.csl\n```\n\n## Converting from blogdown\n\n* Make sure your post archetype has extension `.Rmd` and includes\n  `output: hugodown::md_document` in the YAML. The post archetype\n  should typically be `archetypes/blog/index.Rmd`.\n  \n* Delete `index.Rmd` from the root of your site.\n\n* Ensure that hugo is configured as described in `vignette(\"config\")`.\n\n[yihui-mathjax]: https://yihui.org/en/2018/07/latex-math-markdown/ \n[tourmaline]: https://github.com/rstudio/hugo-tourmaline\n[footer_mathjax]: https://github.com/rstudio/hugo-tourmaline/blob/master/layouts/partials/footer_mathjax.html\n[footer]: https://github.com/rstudio/hugo-tourmaline/blob/master/layouts/partials/footer.html#L22\n[math_code]: https://github.com/rstudio/hugo-tourmaline/blob/master/static/js/math-code.js\n[styles]: https://xyproto.github.io/splash/docs/all.html\n[footnote-csl]: https://github.com/citation-style-language/styles/blob/master/chicago-fullnote-bibliography.csl\n"
  },
  {
    "path": "_pkgdown.yml",
    "content": "url: https://hugodown.r-lib.org\n\ntemplate:\n  params:\n    ganalytics: UA-115082821-1\n"
  },
  {
    "path": "codecov.yml",
    "content": "comment: false\n\ncoverage:\n  status:\n    project:\n      default:\n        target: auto\n        threshold: 1%\n        informational: true\n    patch:\n      default:\n        target: auto\n        threshold: 1%\n        informational: true\n"
  },
  {
    "path": "hugodown.Rproj",
    "content": "Version: 1.0\n\nRestoreWorkspace: No\nSaveWorkspace: No\nAlwaysSaveHistory: Default\n\nEnableCodeIndexing: Yes\nUseSpacesForTab: Yes\nNumSpacesForTab: 2\nEncoding: UTF-8\n\nRnwWeave: knitr\nLaTeX: XeLaTeX\n\nAutoAppendNewline: Yes\nStripTrailingWhitespace: Yes\nLineEndingConversion: Posix\n\nBuildType: Package\nPackageUseDevtools: Yes\nPackageInstallArgs: --no-multiarch --with-keep.source\nPackageRoxygenize: rd,collate,namespace\n"
  },
  {
    "path": "inst/academic/README.md",
    "content": "This is a [hugo](http://gohugo.io/) [academic](https://sourcethemes.com/academic) created by [hugodown](http://hugodown.r-lib.org/).\n\n## Basic operation\n\n* Preview the site with `hugodown::hugo_start()`; it will automatically\n  update (navigating to the latest change) as you modify `content/`.\n\n* Create a new post bundle with `hugodown::use_post('post/short-title')`.\n"
  },
  {
    "path": "inst/academic/highlight-dark.css",
    "content": "/* Background */ .chroma { color: #f8f8f2; background-color: #282a36 }\n/* Other */ .chroma .x {  }\n/* Error */ .chroma .err {  }\n/* LineTableTD */ .chroma .lntd { vertical-align: top; padding: 0; margin: 0; border: 0; }\n/* LineTable */ .chroma .lntable { border-spacing: 0; padding: 0; margin: 0; border: 0; width: auto; overflow: auto; display: block; }\n/* LineHighlight */ .chroma .hl { display: block; width: 100%;background-color: #ffffcc }\n/* LineNumbersTable */ .chroma .lnt { margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #7f7f7f }\n/* LineNumbers */ .chroma .ln { margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #7f7f7f }\n/* Keyword */ .chroma .k { color: #ff79c6 }\n/* KeywordConstant */ .chroma .kc { color: #ff79c6 }\n/* KeywordDeclaration */ .chroma .kd { color: #8be9fd; font-style: italic }\n/* KeywordNamespace */ .chroma .kn { color: #ff79c6 }\n/* KeywordPseudo */ .chroma .kp { color: #ff79c6 }\n/* KeywordReserved */ .chroma .kr { color: #ff79c6 }\n/* KeywordType */ .chroma .kt { color: #8be9fd }\n/* Name */ .chroma .n {  }\n/* NameAttribute */ .chroma .na { color: #50fa7b }\n/* NameBuiltin */ .chroma .nb { color: #8be9fd; font-style: italic }\n/* NameBuiltinPseudo */ .chroma .bp {  }\n/* NameClass */ .chroma .nc { color: #50fa7b }\n/* NameConstant */ .chroma .no {  }\n/* NameDecorator */ .chroma .nd {  }\n/* NameEntity */ .chroma .ni {  }\n/* NameException */ .chroma .ne {  }\n/* NameFunction */ .chroma .nf { color: #50fa7b }\n/* NameFunctionMagic */ .chroma .fm {  }\n/* NameLabel */ .chroma .nl { color: #8be9fd; font-style: italic }\n/* NameNamespace */ .chroma .nn {  }\n/* NameOther */ .chroma .nx {  }\n/* NameProperty */ .chroma .py {  }\n/* NameTag */ .chroma .nt { color: #ff79c6 }\n/* NameVariable */ .chroma .nv { color: #8be9fd; font-style: italic }\n/* NameVariableClass */ .chroma .vc { color: #8be9fd; font-style: italic }\n/* NameVariableGlobal */ .chroma .vg { color: #8be9fd; font-style: italic }\n/* NameVariableInstance */ .chroma .vi { color: #8be9fd; font-style: italic }\n/* NameVariableMagic */ .chroma .vm {  }\n/* Literal */ .chroma .l {  }\n/* LiteralDate */ .chroma .ld {  }\n/* LiteralString */ .chroma .s { color: #f1fa8c }\n/* LiteralStringAffix */ .chroma .sa { color: #f1fa8c }\n/* LiteralStringBacktick */ .chroma .sb { color: #f1fa8c }\n/* LiteralStringChar */ .chroma .sc { color: #f1fa8c }\n/* LiteralStringDelimiter */ .chroma .dl { color: #f1fa8c }\n/* LiteralStringDoc */ .chroma .sd { color: #f1fa8c }\n/* LiteralStringDouble */ .chroma .s2 { color: #f1fa8c }\n/* LiteralStringEscape */ .chroma .se { color: #f1fa8c }\n/* LiteralStringHeredoc */ .chroma .sh { color: #f1fa8c }\n/* LiteralStringInterpol */ .chroma .si { color: #f1fa8c }\n/* LiteralStringOther */ .chroma .sx { color: #f1fa8c }\n/* LiteralStringRegex */ .chroma .sr { color: #f1fa8c }\n/* LiteralStringSingle */ .chroma .s1 { color: #f1fa8c }\n/* LiteralStringSymbol */ .chroma .ss { color: #f1fa8c }\n/* LiteralNumber */ .chroma .m { color: #bd93f9 }\n/* LiteralNumberBin */ .chroma .mb { color: #bd93f9 }\n/* LiteralNumberFloat */ .chroma .mf { color: #bd93f9 }\n/* LiteralNumberHex */ .chroma .mh { color: #bd93f9 }\n/* LiteralNumberInteger */ .chroma .mi { color: #bd93f9 }\n/* LiteralNumberIntegerLong */ .chroma .il { color: #bd93f9 }\n/* LiteralNumberOct */ .chroma .mo { color: #bd93f9 }\n/* Operator */ .chroma .o { color: #ff79c6 }\n/* OperatorWord */ .chroma .ow { color: #ff79c6 }\n/* Punctuation */ .chroma .p {  }\n/* Comment */ .chroma .c { color: #6272a4 }\n/* CommentHashbang */ .chroma .ch { color: #6272a4 }\n/* CommentMultiline */ .chroma .cm { color: #6272a4 }\n/* CommentSingle */ .chroma .c1 { color: #6272a4 }\n/* CommentSpecial */ .chroma .cs { color: #6272a4 }\n/* CommentPreproc */ .chroma .cp { color: #ff79c6 }\n/* CommentPreprocFile */ .chroma .cpf { color: #ff79c6 }\n/* Generic */ .chroma .g {  }\n/* GenericDeleted */ .chroma .gd { color: #8b080b }\n/* GenericEmph */ .chroma .ge { text-decoration: underline }\n/* GenericError */ .chroma .gr {  }\n/* GenericHeading */ .chroma .gh { font-weight: bold }\n/* GenericInserted */ .chroma .gi { font-weight: bold }\n/* GenericOutput */ .chroma .go { color: #44475a }\n/* GenericPrompt */ .chroma .gp {  }\n/* GenericStrong */ .chroma .gs {  }\n/* GenericSubheading */ .chroma .gu { font-weight: bold }\n/* GenericTraceback */ .chroma .gt {  }\n/* GenericUnderline */ .chroma .gl { text-decoration: underline }\n/* TextWhitespace */ .chroma .w {  }\n"
  },
  {
    "path": "inst/academic/highlight-light.css",
    "content": "/* Background */ .chroma { background-color: #ffffff }\n/* Other */ .chroma .x {  }\n/* Error */ .chroma .err { color: #a61717; background-color: #e3d2d2 }\n/* LineTableTD */ .chroma .lntd { vertical-align: top; padding: 0; margin: 0; border: 0; }\n/* LineTable */ .chroma .lntable { border-spacing: 0; padding: 0; margin: 0; border: 0; width: auto; overflow: auto; display: block; }\n/* LineHighlight */ .chroma .hl { display: block; width: 100%;background-color: #ffffcc }\n/* LineNumbersTable */ .chroma .lnt { margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #7f7f7f }\n/* LineNumbers */ .chroma .ln { margin-right: 0.4em; padding: 0 0.4em 0 0.4em;color: #7f7f7f }\n/* Keyword */ .chroma .k { color: #000000; font-weight: bold }\n/* KeywordConstant */ .chroma .kc { color: #000000; font-weight: bold }\n/* KeywordDeclaration */ .chroma .kd { color: #000000; font-weight: bold }\n/* KeywordNamespace */ .chroma .kn { color: #000000; font-weight: bold }\n/* KeywordPseudo */ .chroma .kp { color: #000000; font-weight: bold }\n/* KeywordReserved */ .chroma .kr { color: #000000; font-weight: bold }\n/* KeywordType */ .chroma .kt { color: #445588; font-weight: bold }\n/* Name */ .chroma .n {  }\n/* NameAttribute */ .chroma .na { color: #008080 }\n/* NameBuiltin */ .chroma .nb { color: #0086b3 }\n/* NameBuiltinPseudo */ .chroma .bp { color: #999999 }\n/* NameClass */ .chroma .nc { color: #445588; font-weight: bold }\n/* NameConstant */ .chroma .no { color: #008080 }\n/* NameDecorator */ .chroma .nd { color: #3c5d5d; font-weight: bold }\n/* NameEntity */ .chroma .ni { color: #800080 }\n/* NameException */ .chroma .ne { color: #990000; font-weight: bold }\n/* NameFunction */ .chroma .nf { color: #990000; font-weight: bold }\n/* NameFunctionMagic */ .chroma .fm {  }\n/* NameLabel */ .chroma .nl { color: #990000; font-weight: bold }\n/* NameNamespace */ .chroma .nn { color: #555555 }\n/* NameOther */ .chroma .nx {  }\n/* NameProperty */ .chroma .py {  }\n/* NameTag */ .chroma .nt { color: #000080 }\n/* NameVariable */ .chroma .nv { color: #008080 }\n/* NameVariableClass */ .chroma .vc { color: #008080 }\n/* NameVariableGlobal */ .chroma .vg { color: #008080 }\n/* NameVariableInstance */ .chroma .vi { color: #008080 }\n/* NameVariableMagic */ .chroma .vm {  }\n/* Literal */ .chroma .l {  }\n/* LiteralDate */ .chroma .ld {  }\n/* LiteralString */ .chroma .s { color: #dd1144 }\n/* LiteralStringAffix */ .chroma .sa { color: #dd1144 }\n/* LiteralStringBacktick */ .chroma .sb { color: #dd1144 }\n/* LiteralStringChar */ .chroma .sc { color: #dd1144 }\n/* LiteralStringDelimiter */ .chroma .dl { color: #dd1144 }\n/* LiteralStringDoc */ .chroma .sd { color: #dd1144 }\n/* LiteralStringDouble */ .chroma .s2 { color: #dd1144 }\n/* LiteralStringEscape */ .chroma .se { color: #dd1144 }\n/* LiteralStringHeredoc */ .chroma .sh { color: #dd1144 }\n/* LiteralStringInterpol */ .chroma .si { color: #dd1144 }\n/* LiteralStringOther */ .chroma .sx { color: #dd1144 }\n/* LiteralStringRegex */ .chroma .sr { color: #009926 }\n/* LiteralStringSingle */ .chroma .s1 { color: #dd1144 }\n/* LiteralStringSymbol */ .chroma .ss { color: #990073 }\n/* LiteralNumber */ .chroma .m { color: #009999 }\n/* LiteralNumberBin */ .chroma .mb { color: #009999 }\n/* LiteralNumberFloat */ .chroma .mf { color: #009999 }\n/* LiteralNumberHex */ .chroma .mh { color: #009999 }\n/* LiteralNumberInteger */ .chroma .mi { color: #009999 }\n/* LiteralNumberIntegerLong */ .chroma .il { color: #009999 }\n/* LiteralNumberOct */ .chroma .mo { color: #009999 }\n/* Operator */ .chroma .o { color: #000000; font-weight: bold }\n/* OperatorWord */ .chroma .ow { color: #000000; font-weight: bold }\n/* Punctuation */ .chroma .p {  }\n/* Comment */ .chroma .c { color: #999988; font-style: italic }\n/* CommentHashbang */ .chroma .ch { color: #999988; font-style: italic }\n/* CommentMultiline */ .chroma .cm { color: #999988; font-style: italic }\n/* CommentSingle */ .chroma .c1 { color: #999988; font-style: italic }\n/* CommentSpecial */ .chroma .cs { color: #999999; font-weight: bold; font-style: italic }\n/* CommentPreproc */ .chroma .cp { color: #999999; font-weight: bold; font-style: italic }\n/* CommentPreprocFile */ .chroma .cpf { color: #999999; font-weight: bold; font-style: italic }\n/* Generic */ .chroma .g {  }\n/* GenericDeleted */ .chroma .gd { color: #000000; background-color: #ffdddd }\n/* GenericEmph */ .chroma .ge { color: #000000; font-style: italic }\n/* GenericError */ .chroma .gr { color: #aa0000 }\n/* GenericHeading */ .chroma .gh { color: #999999 }\n/* GenericInserted */ .chroma .gi { color: #000000; background-color: #ddffdd }\n/* GenericOutput */ .chroma .go { color: #888888 }\n/* GenericPrompt */ .chroma .gp { color: #555555 }\n/* GenericStrong */ .chroma .gs { font-weight: bold }\n/* GenericSubheading */ .chroma .gu { color: #aaaaaa }\n/* GenericTraceback */ .chroma .gt { color: #aa0000 }\n/* GenericUnderline */ .chroma .gl { text-decoration: underline }\n/* TextWhitespace */ .chroma .w { color: #bbbbbb }\n"
  },
  {
    "path": "inst/academic/index.Rmd",
    "content": "---\nsite: hugodown:::hugodown_site\n---\n"
  },
  {
    "path": "inst/templates/netlify.toml",
    "content": "[build]\n  publish = \"public\"\n  command = \"hugo\"\n\n[build.environment]\n  HUGO_VERSION = \"{{hugo_version}}\"\n  HUGO_BUILDFUTURE = \"true\"\n\n[context.deploy-preview.environment]\n  command = \"hugo --baseURL $DEPLOY_PRIME_URL\"\n"
  },
  {
    "path": "inst/templates/template.Rproj",
    "content": "Version: 1.0\n\nRestoreWorkspace: No\nSaveWorkspace: No\nAlwaysSaveHistory: Default\n\nEnableCodeIndexing: Yes\nUseSpacesForTab: Yes\nNumSpacesForTab: 2\nEncoding: UTF-8\n\nRnwWeave: Sweave\nLaTeX: pdfLaTeX\n\nAutoAppendNewline: Yes\nStripTrailingWhitespace: Yes\nLineEndingConversion: Posix\n\nBuildType: Website\n"
  },
  {
    "path": "man/create_site_academic.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/site-academic.R\n\\name{create_site_academic}\n\\alias{create_site_academic}\n\\title{Create a hugo academic site}\n\\usage{\ncreate_site_academic(\n  path = \".\",\n  open = is_interactive(),\n  rstudio = rstudioapi::isAvailable()\n)\n}\n\\arguments{\n\\item{path}{Path to create site}\n\n\\item{open}{Open new site after creation?}\n\n\\item{rstudio}{Create RStudio project?}\n}\n\\description{\nCreate a hugo academic 4.8.0 site, configured to work well with hugodown.\nIn particular, it ensures that the following features important for R\nusers work correctly:\n\\itemize{\n\\item Syntax highlighting (turns off default js highlighting, renables\ndefault chroma, and sets up styles in \\code{assets/chroma.css}).\n\\item Math\n\\item HTML widgets\n\\item Default post archetype is tweaked to create \\code{.Rmd}\n}\n}\n"
  },
  {
    "path": "man/embed_gist.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/shortcode.R\n\\name{embed_gist}\n\\alias{embed_gist}\n\\alias{embed_instagram}\n\\alias{embed_tweet}\n\\alias{embed_vimeo}\n\\alias{embed_youtube}\n\\title{Generate hugo shortcodes to embed various types of media}\n\\usage{\nembed_gist(username, id, filename = NULL)\n\nembed_instagram(id, caption = TRUE)\n\nembed_tweet(id, username = NULL)\n\nembed_vimeo(id)\n\nembed_youtube(id, autoplay = FALSE)\n}\n\\arguments{\n\\item{username}{GitHub/Twitter user name}\n\n\\item{id}{A string giving the object id. You'll usually find this by\ninspecting the URL:\n\\itemize{\n\\item gist: \\verb{https://gist.github.com/spf13/7896402} -> \\code{7896402}\n\\item instagram: \\verb{https://www.instagram.com/p/BWNjjyYFxVx/} -> \\code{BWNjjyYFxVx}\n\\item twitter: \\verb{https://twitter.com/spf13/status/877500564405444608} -> \\code{877500564405444608}\n\\item vimeo: \\verb{https://vimeo.com/channels/staffpicks/146022717} -> \\code{146022717}\n\\item youtube: \\verb{https://www.youtube.com/watch?v=w7Ft2ymGmfc} -> \\code{w7Ft2ymGmfc}\n}}\n\n\\item{filename}{Pick single file from multiple file gist}\n\n\\item{caption}{Show instagram caption?}\n\n\\item{autoplay}{Automatically play youtube video?}\n}\n\\description{\nThese are wrappers that make it easy to generate\n\\href{https://gohugo.io/content-management/shortcodes/}{hugo shortcodes} that\nmake it easy to embed various types of media into your pages. You use from\ninline R code like:\n\n\\if{html}{\\out{<div class=\"sourceCode\">}}\\preformatted{This tweet announced the release of hugo 0.24:\n\n`R embed_tweet(\"877500564405444608\")`\n}\\if{html}{\\out{</div>}}\n}\n"
  },
  {
    "path": "man/hugo_build.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/hugo-server.R\n\\name{hugo_build}\n\\alias{hugo_build}\n\\title{Build site}\n\\usage{\nhugo_build(\n  site = \".\",\n  dest = NULL,\n  build_drafts = FALSE,\n  build_future = FALSE,\n  clean = FALSE,\n  base_url = NULL,\n  relative_urls = NULL\n)\n}\n\\arguments{\n\\item{site}{Path to hugo site.}\n\n\\item{dest}{Destination directory. If \\code{NULL}, the default, will build\nin \\code{{site}/public}}\n\n\\item{build_drafts, build_future}{Should drafts and future posts be included\nin the built site?}\n\n\\item{clean}{Remove files in \\verb{public/} that don't exist in the source.}\n\n\\item{base_url}{\\verb{<string>} Optionally override the \\code{baseURL} setting from\nhugo config.}\n\n\\item{relative_urls}{\\verb{<bool>} Optionally the override the \\code{relativeURL}\nsetting from hugo config.}\n}\n\\description{\nBuild static html into specified directory. Useful for debugging and some\ndeployment scenarios\n}\n"
  },
  {
    "path": "man/hugo_document.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/md-document.R\n\\name{hugo_document}\n\\alias{hugo_document}\n\\title{Deprecated: please use \\code{md_document()}}\n\\usage{\nhugo_document(\n  fig_width = 7,\n  fig_asp = 0.618,\n  fig_retina = 2,\n  tidyverse_style = TRUE\n)\n}\n\\description{\nDeprecated: please use \\code{md_document()}\n}\n\\keyword{internal}\n"
  },
  {
    "path": "man/hugo_install.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/hugo-install.R\n\\name{hugo_install}\n\\alias{hugo_install}\n\\title{Install specified version of hugo}\n\\usage{\nhugo_install(version = NULL, os = hugo_os(), arch = \"64bit\", extended = TRUE)\n}\n\\arguments{\n\\item{version}{String giving version (e.g. \"0.69.0\"). If omitted will\ndefault to latest release.}\n\n\\item{os}{Operating system, one of \"Linux\", \"Windows\", \"macOS\". Defaults\nto current operating system.}\n\n\\item{arch}{Architecture}\n\n\\item{extended}{Installed hugo-extended which also includes SCSS etc?}\n}\n\\description{\nDownloads binary from hugo releases, and installs in system wide cache.\n}\n\\examples{\n\\dontrun{\nhugo_install()\n}\n}\n"
  },
  {
    "path": "man/hugo_locate.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/hugo.R\n\\name{hugo_locate}\n\\alias{hugo_locate}\n\\title{Locates a specific Hugo installation}\n\\usage{\nhugo_locate(version = hugo_default_get())\n}\n\\arguments{\n\\item{version}{The Hugo version to be located}\n}\n\\value{\nReturns the path to the Hugo installation, or an error if no\nHugo install is found\n}\n\\description{\nLocates a specific Hugo installation\n}\n"
  },
  {
    "path": "man/hugo_start.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/hugo-server.R\n\\name{hugo_start}\n\\alias{hugo_start}\n\\alias{hugo_stop}\n\\alias{hugo_browse}\n\\title{Manage the hugo server}\n\\usage{\nhugo_start(\n  site = \".\",\n  auto_navigate = TRUE,\n  browse = TRUE,\n  render_to_disk = FALSE,\n  port = 1313\n)\n\nhugo_stop()\n\nhugo_browse()\n}\n\\arguments{\n\\item{site}{Path to hugo site.}\n\n\\item{auto_navigate}{Automatically navigate to the most recently changed\npage?}\n\n\\item{browse}{Automatically preview the site after the server starts?}\n\n\\item{render_to_disk}{Render site to disk? The default is to serve the\nsite from memory, but rendering to disk can be helpful for debugging.}\n\n\\item{port}{Port to run server on. For advanced use only.}\n}\n\\description{\n\\code{hugo_start()} starts a hugo server that will automatically re-generate\nthe site whenever the input changes. You only need to execute this once\nper session; it continues to run in the background as you work on the site.\nFor large sites the hugo server can be slow to start; if it takes longer\nthan 30 seconds \\code{hugo_start()} throws an error.\n\n\\code{hugo_stop()} kills the server. This happens automatically when you exit\nR so you shouldn't normally need to run this.\n\n\\code{hugo_browse()} opens the site in the RStudio viewer or your web browser.\n}\n\\section{Hugo version}{\n\nhugodown will attempt to automatically use the correct version of hugo for\nyour site (prompting you to call \\code{\\link[=hugo_install]{hugo_install()}} if needed). It looks in\ntwo places:\n\\itemize{\n\\item If \\verb{_hugodown.yaml} is present, it looks for the \\code{hugo_version} key.\n\\item If \\code{netlify.toml} is present, it looks in\n\\code{context$production$environment$HUGO_VERSION}\n}\n\nThis means if you already use netlify, hugodown will automatically match\nthe version of hugo that you're using for deployment.\n}\n\n"
  },
  {
    "path": "man/hugo_version.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/hugo-version.R\n\\name{hugo_version}\n\\alias{hugo_version}\n\\title{Find hugo version needed for current site}\n\\usage{\nhugo_version(site = \".\")\n}\n\\arguments{\n\\item{site}{Path to hugo site.}\n}\n\\description{\nHugo changes rapidly, so it's important to pin your site to a specific\nversion and then deliberately update when needed. This function reports\nwhich of hugo your site correctly uses.\n\nThe primary location of this information is the \\code{hugo_version} field\nin \\code{hugodown.yaml}. If that doesn't exist, we also look in \\code{netlify.toml}.\n}\n\\seealso{\n\\code{\\link[=hugo_install]{hugo_install()}} to install any version of hugo.\n}\n"
  },
  {
    "path": "man/hugodown-package.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/hugodown-package.R\n\\docType{package}\n\\name{hugodown-package}\n\\alias{hugodown}\n\\alias{hugodown-package}\n\\title{hugodown: Make websites with hugo and RMarkdown}\n\\description{\n\\if{html}{\\figure{logo.png}{options: style='float: right' alt='logo' width='120'}}\n\nhugodown is a minimal version of blogdown that only supports hugo, and more clearly delineates the roles of RMarkdown (turning .Rmd into .md) and hugo (turning .md into .html).\n}\n\\seealso{\nUseful links:\n\\itemize{\n  \\item \\url{https://github.com/r-lib/hugodown}\n  \\item Report bugs at \\url{https://github.com/r-lib/hugodown/issues}\n}\n\n}\n\\author{\n\\strong{Maintainer}: Hadley Wickham \\email{hadley@rstudio.com}\n\nOther contributors:\n\\itemize{\n  \\item RStudio [copyright holder]\n}\n\n}\n\\keyword{internal}\n"
  },
  {
    "path": "man/md_document.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/md-document.R\n\\name{md_document}\n\\alias{md_document}\n\\title{An Rmd output format that produces Hugo-flavoured markdown}\n\\usage{\nmd_document(\n  fig_width = 7,\n  fig_asp = 0.618,\n  fig_retina = 2,\n  tidyverse_style = TRUE\n)\n}\n\\arguments{\n\\item{fig_width}{Figure width (in inches).}\n\n\\item{fig_asp}{Figure aspect ratio, defaults to the golden ratio.}\n\n\\item{fig_retina}{Scaling to perform for retina displays. Defaults to\n\\code{NULL} which performs no scaling. A setting of 2 will work for all\nwidely used retina displays, but will also result in the output of\n\\verb{<img>} tags rather than markdown images due to the need to set the\nwidth of the image explicitly.}\n\n\\item{tidyverse_style}{Use tidyverse knitr conventions? This sets\n\\code{collapse = TRUE}, \\verb{comment = \"#>}, \\code{fig.align = \"center\"}, and\n\\code{out.width = \"700px\"}.}\n}\n\\description{\nThis RMarkdown output format is designed to generate markdown that is\nmaximally compatible with Hugo. It intelligently generates a preview so\nthat you see something useful when Hugo isn't running, but it doesn't\nget in the way of hugo's full-site preview when it is.\n}\n\\section{Syntax highlighting}{\n\n\n\\code{md_document()} uses a hybrid system for syntax highlighting.\nFor R code it uses \\href{http://github.com/r-lib/downlit}{downlit}. For\nother languages, it relies on Chroma, the syntax highlighter built into\nhugo.\n}\n\n"
  },
  {
    "path": "man/shortcode.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/shortcode.R\n\\name{shortcode}\n\\alias{shortcode}\n\\title{Generate a hugo shortcode}\n\\usage{\nshortcode(\n  .name,\n  ...,\n  .contents = NULL,\n  .output = c(\"html\", \"md\"),\n  .inline = FALSE\n)\n}\n\\arguments{\n\\item{.name}{Name of the shortcode}\n\n\\item{...}{Arguments to the shortcode, supplied either by name or\nposition depending on the shortcode. By default, strings will\nautomatically be quoted with single quotes. Suppress this quoting\nby wrapping the argument in \\code{I()}.}\n\n\\item{.contents}{Contents of the shortcode for paired shortcodes.}\n\n\\item{.output}{Is the output of the shortcode html or markdown? This\ncontrols whether the shortcode uses \\verb{<>} or \\verb{\\%}.}\n\n\\item{.inline}{Is the shortcode designed to be used inline or in its own\nparagraph? Controls whether the shortcode is wrapped in a block or inline\n\\href{https://pandoc.org/MANUAL.html#extension-raw_attribute}{raw attribute}.}\n}\n\\description{\nGenerate a hugo shortcode with appropriate pandoc markup to preserve it as\nis when embedded in an R markdown document.\n\nGenerally, I don't recommend calling this function directly; instead\nuse it inside a function with the same name as the shortcode you want to\nwrap. See \\code{\\link[=embed_gist]{embed_gist()}} and friends for examples\n}\n\\examples{\npkg <- function(name) {\n  shortcode(\"pkg\", name, .inline = TRUE)\n}\npkg(\"hugodown\")\n}\n"
  },
  {
    "path": "man/site_outdated.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/site.R\n\\name{site_outdated}\n\\alias{site_outdated}\n\\title{Find \\code{.Rmd}s that need to be re-rendered.}\n\\usage{\nsite_outdated(site = \".\")\n}\n\\arguments{\n\\item{site}{Path to hugo site.}\n}\n\\description{\n\\code{\\link[=md_document]{md_document()}} adds a hash of the input \\code{.Rmd} in the YAML metdata of\nthe \\code{.md} file that it creates. This provides a reliable way to determine\nwhether or not a \\code{.Rmd} has been changed since the last time the \\code{.md}\nwas rendered.\n}\n"
  },
  {
    "path": "man/use_netlify_toml.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/netlify.R\n\\name{use_netlify_toml}\n\\alias{use_netlify_toml}\n\\title{Create \\code{netlify.toml}}\n\\usage{\nuse_netlify_toml(site = \".\")\n}\n\\arguments{\n\\item{site}{Path to the hugo site.}\n}\n\\description{\nThis helper creates a basic \\code{netlify.toml} file, automatically setting the\nhugo version to match your blog. This is needed when publishing your site\nwith \\href{https://www.netlify.com}{netlify}; see \\code{vignette(\"deploy\")} for more\ndetails.\n}\n"
  },
  {
    "path": "man/use_post.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/post.R\n\\name{use_post}\n\\alias{use_post}\n\\title{Create a new post}\n\\usage{\nuse_post(path, kind = NULL, data = list(), site = \".\", open = is_interactive())\n}\n\\arguments{\n\\item{path}{Directory to create, like \\code{blog/2020-my-favourite-package}.}\n\n\\item{kind}{Kind of archetype of use; usually automatically derived\nfrom the base directory of \\code{path}.}\n\n\\item{data}{Any additional data to be used when templating \\code{.Rmd} files.\n\nThe default data includes:\n\\itemize{\n\\item \\code{date}: today's date (in YYYY-MM-DD format).\n\\item \\code{author}: \\code{\\link[whoami:fullname]{whoami::fullname()}}.\n\\item \\code{slug}: taken from the file name of \\code{path}.\n}}\n\n\\item{site}{Path to the hugo site.}\n\n\\item{open}{Open file for interactive editing?}\n}\n\\description{\nPost creation takes advantage of Hugo's\n\\href{https://gohugo.io/content-management/archetypes/}{archetypes} or templates,\nwith an extension for \\code{.Rmd} files. \\code{use_post()} first calls \\verb{hugo new}\n(which will apply go templating to \\code{.md} files in the archetype),\nand then uses \\href{https://github.com/edwindj/whisker}{whisker} to template\nany \\code{.Rmd} files.\n}\n"
  },
  {
    "path": "man/use_tidy_post.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/tidy.R\n\\name{use_tidy_post}\n\\alias{use_tidy_post}\n\\alias{use_tidy_thumbnails}\n\\alias{tidy_show_meta}\n\\title{Various helpers for tidyverse.org and similar sites}\n\\usage{\nuse_tidy_post(slug, site = \".\", open = is_interactive())\n\nuse_tidy_thumbnails(path = NULL)\n\ntidy_show_meta(min = 1, site = \".\")\n}\n\\arguments{\n\\item{slug}{File name of new post. Year and month will be automatically\nappended.}\n\n\\item{site}{Path to the hugo site.}\n\n\\item{open}{Open file for interactive editing?}\n\n\\item{path}{Path to blog post}\n\n\\item{min}{Minimum number of uses}\n}\n\\description{\n\\itemize{\n\\item \\code{use_tidy_post()} makes a new post\n\\item \\code{use_tidy_thumbnails()} resizes thumbnails to the correct size\n\\item \\code{tidy_show_meta()} prints tags and categories used by existing posts.\n}\n}\n"
  },
  {
    "path": "tests/testthat/.gitignore",
    "content": "knit-hooks_files\n"
  },
  {
    "path": "tests/testthat/_snaps/md-document.md",
    "content": "# interweaving of code and output generates correct html\n\n    ---\n    output: hugodown::md_document\n    rmd_hash: 51bc60383311007d\n    \n    ---\n    \n    ## Mixed as_is and coode\n    \n    <div class=\"highlight\">\n    \n    <pre class='chroma'><code class='language-r' data-lang='r'><span><span class='nv'>df</span> <span class='o'>&lt;-</span> <span class='nf'><a href='https://rdrr.io/r/base/data.frame.html'>data.frame</a></span><span class='o'>(</span>x <span class='o'>=</span> <span class='m'>1</span><span class='o'>)</span></span>\n    <span><span class='nv'>df</span></span>\n    <span><span class='c'>#&gt;   x</span></span>\n    <span><span class='c'>#&gt; 1 1</span></span>\n    <span></span><span></span>\n    <span><span class='nf'>knitr</span><span class='nf'>::</span><span class='nf'><a href='https://rdrr.io/pkg/knitr/man/kable.html'>kable</a></span><span class='o'>(</span><span class='nv'>df</span><span class='o'>)</span></span>\n    </code></pre>\n    \n    |   x |\n    |----:|\n    |   1 |\n    \n    </div>\n    \n    ## All code/output\n    \n    <div class=\"highlight\">\n    \n    <pre class='chroma'><code class='language-r' data-lang='r'><span><span class='c'># comment</span></span>\n    <span><span class='nf'><a href='https://rdrr.io/r/base/print.html'>print</a></span><span class='o'>(</span><span class='s'>\"print\"</span><span class='o'>)</span></span>\n    <span><span class='c'>#&gt; [1] \"print\"</span></span>\n    <span></span><span><span class='nf'><a href='https://rdrr.io/r/base/message.html'>message</a></span><span class='o'>(</span><span class='s'>\"message\"</span><span class='o'>)</span></span>\n    <span><span class='c'>#&gt; message</span></span>\n    <span></span><span><span class='kr'><a href='https://rdrr.io/r/base/warning.html'>warning</a></span><span class='o'>(</span><span class='s'>\"warning\"</span><span class='o'>)</span></span>\n    <span><span class='c'>#&gt; Warning: warning</span></span>\n    <span></span></code></pre>\n    \n    </div>\n    \n    ## Chunk with only a figure\n    \n    <div class=\"highlight\">\n    \n    <img src=\"figs/unnamed-chunk-3-1.png\" width=\"700px\" style=\"display: block; margin: auto;\" />\n    \n    </div>\n    \n\n"
  },
  {
    "path": "tests/testthat/archetypes/_hugodown.yaml",
    "content": "hugo_version: 0.72.0\n"
  },
  {
    "path": "tests/testthat/archetypes/archetypes/Rmd/index.Rmd",
    "content": "---\nslug: {{ slug }}\n---\n"
  },
  {
    "path": "tests/testthat/archetypes/archetypes/blog/index.Rmd",
    "content": "---\nslug: {{ slug }}\npackage: {{ package }}\n---\n"
  },
  {
    "path": "tests/testthat/archetypes/archetypes/md/index.md",
    "content": "---\nslug: {{ .Name }}\ntitle: \"{{ replace .Name \"-\" \" \" | title }}\"\n---\n"
  },
  {
    "path": "tests/testthat/archetypes/config.yml",
    "content": ""
  },
  {
    "path": "tests/testthat/code-invalid.Rmd",
    "content": "---\noutput: hugodown::md_document\n---\n\n```{r, eval = FALSE}\n1 + \n```\n"
  },
  {
    "path": "tests/testthat/code.Rmd",
    "content": "---\noutput: hugodown::md_document\n---\n\n```{r}\n1 + 1\n```\n\n`stats::median()`\n\n```{r, error = TRUE}\nprint(\"print\")\nmessage(\"message\")\n# comment\nwarning(\"warning\")\nstop(\"error!\")\nplot(1 + 1)\n```\n"
  },
  {
    "path": "tests/testthat/config-hugodown/_hugodown.yaml",
    "content": "test: true\nhugo_version: 0.66.0\n"
  },
  {
    "path": "tests/testthat/config-hugodown/config.yaml",
    "content": ""
  },
  {
    "path": "tests/testthat/config-toml/config.toml",
    "content": ""
  },
  {
    "path": "tests/testthat/config-yaml/config.yaml",
    "content": ""
  },
  {
    "path": "tests/testthat/config-yml/config.yml",
    "content": ""
  },
  {
    "path": "tests/testthat/curly.Rmd",
    "content": "---\noutput: hugodown::md_document\n---\n\n```{r, eval = FALSE}\n{{ curly }}\n```\n"
  },
  {
    "path": "tests/testthat/div.Rmd",
    "content": "---\noutput: hugodown::md_document\n---\n\n:::special\nThis is special\n:::\n"
  },
  {
    "path": "tests/testthat/emoji.Rmd",
    "content": "---\noutput: hugodown::md_document\n---\n\n:smile_cat:\n"
  },
  {
    "path": "tests/testthat/error.Rmd",
    "content": "---\noutput: hugodown::md_document\n---\n\n```{r}\nstop(\"Failure\")\n```\n\n"
  },
  {
    "path": "tests/testthat/knit-hooks.Rmd",
    "content": "---\noutput: hugodown::md_document\n---\n\n## Mixed as_is and coode\n\n```{r}\ndf <- data.frame(x = 1)\ndf\n\nknitr::kable(df)\n```\n\n\n## All code/output\n\n```{r}\n# comment\nprint(\"print\")\nmessage(\"message\")\nwarning(\"warning\")\n```\n\n## Chunk with only a figure\n\n```{r, echo = FALSE}\nplot(1:5)\n```\n"
  },
  {
    "path": "tests/testthat/math.Rmd",
    "content": "---\noutput: hugodown::md_document\n---\n\n$a_1 + b_2$\n"
  },
  {
    "path": "tests/testthat/meta.Rmd",
    "content": "---\nauthor: Hadley\noutput: hugodown::md_document\n# this is a comment\n---\n"
  },
  {
    "path": "tests/testthat/minimal/.gitignore",
    "content": "public\n"
  },
  {
    "path": "tests/testthat/minimal/LICENSE",
    "content": "License\n=========\n\nThis project is licensed under the terms of the MIT License describe below.\n\nCopyright (c) 2017 Arun Ravindran\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."
  },
  {
    "path": "tests/testthat/minimal/README.md",
    "content": "Minimal site created for Hugo, a static site generator\n\nRead the tutorial at http://arunrocks.com for more details.\n"
  },
  {
    "path": "tests/testthat/minimal/_hugodown.yaml",
    "content": "hugo_version: 0.72.0\n"
  },
  {
    "path": "tests/testthat/minimal/config.toml",
    "content": "baseURL = \"http://example.org/\"\ntheme = \"bare\""
  },
  {
    "path": "tests/testthat/minimal/content/_index.md",
    "content": "+++\ntitle = \"Home page\"\n+++\n\nThis page has **bold** and *italics* formatting.\n"
  },
  {
    "path": "tests/testthat/minimal/themes/bare/layouts/index.html",
    "content": "<html>\n  <body>\n    <h1>Welcome!</h1>\n    \n    <h2>{{ .Title }}</h2>\n    {{ .Content }}\n\n  </body>\n</html>\n"
  },
  {
    "path": "tests/testthat/minimal/themes/bare/theme.toml",
    "content": "name = \"Bare\"\nlicense = \"MIT\"\n"
  },
  {
    "path": "tests/testthat/outdated/config.yml",
    "content": ""
  },
  {
    "path": "tests/testthat/outdated/content/blog/_index.md",
    "content": "---\ntitle: Blog\n---\n"
  },
  {
    "path": "tests/testthat/outdated/content/blog/ok-has-html/index.Rmd",
    "content": "---\ntitle: This post is out of date\noutput: hugodown::md_document\n---\n\nText\n"
  },
  {
    "path": "tests/testthat/outdated/content/blog/ok-has-html/index.html",
    "content": ""
  },
  {
    "path": "tests/testthat/outdated/content/blog/ok-no-hash/index.Rmd",
    "content": "---\ntitle: This post is out of date\noutput: hugodown::md_document\n---\n\nText\n"
  },
  {
    "path": "tests/testthat/outdated/content/blog/ok-no-hash/index.md",
    "content": "---\ntitle: This post is out of date\noutput: hugodown::md_document\n\n---\n\nText\n\n"
  },
  {
    "path": "tests/testthat/outdated/content/blog/outdated-no-md/index.Rmd",
    "content": "---\ntitle: This post is out of date\noutput: hugodown::md_document\n---\n\n"
  },
  {
    "path": "tests/testthat/outdated/content/blog/outdated-old-hash/index.Rmd",
    "content": "---\ntitle: This post is out of date\noutput: hugodown::md_document\n---\n\nText\n"
  },
  {
    "path": "tests/testthat/outdated/content/blog/outdated-old-hash/index.md",
    "content": "---\ntitle: This post is out of date\noutput: hugodown::md_document\nrmd_hash: wrong\n\n---\n\nText\n\n"
  },
  {
    "path": "tests/testthat/output.Rmd",
    "content": "---\noutput: hugodown::md_document\n---\n\n```{r, echo = FALSE}\ncat(cli::col_blue(\"blue\"))\ncat(cli::symbol$tick)\n```\n"
  },
  {
    "path": "tests/testthat/plot.Rmd",
    "content": "---\noutput: hugodown::md_document\n---\n\n```{r, echo = FALSE}\nplot(1:5, 1:5)\n```\n\n```{r, echo = FALSE, out.width=\"50%\"}\nplot(1:5, 1:5)\n```\n"
  },
  {
    "path": "tests/testthat/raw-html.Rmd",
    "content": "---\noutput: hugodown::md_document\n---\n\n```{=html}\n<raw>\n```\n\nThis is `<raw>`{=html}\n"
  },
  {
    "path": "tests/testthat/table.Rmd",
    "content": "---\noutput: hugodown::md_document\n---\n\n                 mpg   cyl \n--------------  ----  ---- \nMazda RX4         21     6 \nMazda RX4 Wag     21     6 \n"
  },
  {
    "path": "tests/testthat/test-hugo-install.R",
    "content": "test_that(\"can retrieve download urls\", {\n  skip_on_cran()\n\n  expect_equal(\n    hugo_release(\"0.69.0\", \"Linux\")$url,\n    \"https://github.com/gohugoio/hugo/releases/download/v0.69.0/hugo_extended_0.69.0_Linux-64bit.tar.gz\"\n  )\n\n  expect_error(hugo_release(\"foo\", \"Linux\"), \"Can't find version\")\n  expect_error(hugo_release(\"0.69.0\", \"Linux\", arch = \"blah\"), \"Can't find release\")\n})\n\ntest_that(\"can install specified linux/mac version\", {\n  skip_on_cran()\n  old <- hugo_default_get()\n  on.exit(hugo_default_set(old))\n\n  home <- hugo_home(\"0.55.0\", \"Linux\")\n  if (dir_exists(home)) dir_delete(home)\n  suppressMessages(hugo_install(\"0.55.0\", \"Linux\"))\n  expect_true(file_exists(path(home, \"hugo\")))\n\n  # Returns early if already installed\n  suppressMessages(\n    expect_message(hugo_install(\"0.55.0\", \"Linux\"), \"installed\")\n  )\n})\n\ntest_that(\"can install specified windows version\", {\n  skip_on_cran()\n  old <- hugo_default_get()\n  on.exit(hugo_default_set(old))\n\n  home <- hugo_home(\"0.55.0\", \"Windows\")\n  if (dir_exists(home)) dir_delete(home)\n  suppressMessages(hugo_install(\"0.55.0\", \"Windows\"))\n  expect_true(file_exists(path(home, \"hugo.exe\")))\n})\n\ntest_that(\"can get, set, and increment version\", {\n  old <- hugo_default_get()\n  on.exit(hugo_default_set(old))\n\n  if (file_exists(hugo_default_path())) {\n    file_delete(hugo_default_path())\n  }\n\n  expect_equal(hugo_default_get(), NA)\n  hugo_default_inc(\"0.1.0\")\n  expect_equal(hugo_default_get(), package_version(\"0.1.0\"))\n  hugo_default_inc(\"0.0.1\")\n  expect_equal(hugo_default_get(), package_version(\"0.1.0\"))\n  hugo_default_inc(\"1.0.0\")\n  expect_equal(hugo_default_get(), package_version(\"1.0.0\"))\n})\n"
  },
  {
    "path": "tests/testthat/test-hugo-server.R",
    "content": "test_that(\"can start, restart, and stop server\", {\n  skip_if_no_hugo()\n  site <- test_path(\"minimal\")\n\n  suppressMessages(hugo_start(site, browse = FALSE))\n  expect_true(hugo_running())\n  expect_true(port_active(1313))\n\n  suppressMessages(hugo_start(site, browse = FALSE))\n  expect_true(hugo_running())\n\n  suppressMessages(hugo_stop())\n  expect_false(hugo_running())\n  expect_false(port_active(1313))\n})\n\n# build -------------------------------------------------------------------\n\ntest_that(\"default builds into public\", {\n  skip_if_no_hugo()\n\n  path <- local_dir(test_path(\"minimal\"))\n  hugo_build(path)\n  expect_true(file_exists(path(path, \"public\", \"index.html\")))\n})\n\ntest_that(\"can build into any directory\", {\n  skip_if_no_hugo()\n  path <- dir_create(file_temp())\n\n  hugo_build(test_path(\"minimal\"), path)\n  expect_true(file_exists(path(path, \"index.html\")))\n})\n"
  },
  {
    "path": "tests/testthat/test-hugo-version.R",
    "content": "test_that(\"can find version from hugodown.yml\", {\n  expect_equal(hugo_version(test_path(\"config-hugodown\")), \"0.66.0\")\n})\n\ntest_that(\"falls back to latest with a warning\", {\n  expect_warning(out <- hugo_version(test_path(\"config-toml\")), \"install\")\n  expect_equal(out, hugo_default_get())\n})\n"
  },
  {
    "path": "tests/testthat/test-hugo.R",
    "content": "test_that(\"can extract basic config options\", {\n  skip_if_no_hugo()\n\n  config <- hugo_config(test_path(\"minimal/\"))\n  expect_type(config, \"list\")\n\n  expect_equal(hugo_config_bool(config, \"builddrafts\"), FALSE)\n  expect_equal(hugo_config_int(config, \"paginate\"), 10)\n  expect_equal(hugo_config_str(config, \"themesdir\"), \"themes\")\n})\n\ntest_that(\"can override config with env var\", {\n  skip_if_no_hugo()\n\n  config1 <- hugo_config(test_path(\"minimal/\"))\n  expect_equal(hugo_config_bool(config1, \"builddrafts\"), FALSE)\n\n  config2 <- hugo_config(test_path(\"minimal/\"), c(builddrafts = \"true\"))\n  expect_equal(hugo_config_bool(config2, \"builddrafts\"), TRUE)\n})\n"
  },
  {
    "path": "tests/testthat/test-md-document.R",
    "content": "test_that(\"errors are handled gracefully\", {\n  rmd <- local_file(test_path(\"error.Rmd\"))\n  expect_message(expect_error(rmarkdown::render(rmd, quiet = TRUE), \"Failure\"))\n  expect_equal(length(dir_ls(path_dir(rmd))), 1L)\n})\n\ntest_that(\"figures placed in figs/ directory\", {\n  rmd <- local_render(test_path(\"plot.Rmd\"))\n\n  figs <- path(rmd$dir, \"figs\")\n  expect_true(dir_exists(figs))\n  expect_equal(length(dir_ls(figs)), 2L)\n\n  # Check we're not converting percentage widths to latex\n  expect_match(rmd$lines[[15]], 'width=\"50%\"')\n})\n\ntest_that(\"tables use pipes\", {\n  rmd <- local_render(test_path(\"table.Rmd\"))\n  expect_equal(sum(grepl(\"|\", rmd$lines, fixed = TRUE)), 4)\n})\n\ntest_that(\"code is linked/highlighted\", {\n  rmd <- local_render(test_path(\"code.Rmd\"))\n\n  expect_equal(\n    xpath_text(rmd$xml, \"(//pre)[1]\"),\n    \"1 + 1\\n#> [1] 2\\n\"\n  )\n\n  expect_equal(sum(grepl(\"<pre\", rmd$lines, fixed = TRUE)), 2)\n  expect_equal(sum(grepl(\"[`stats::median()`]\", rmd$lines, fixed = TRUE)), 1)\n})\n\ntest_that(\"unparseable code is left as is\", {\n  rmd <- local_render(test_path(\"code-invalid.Rmd\"))\n  expect_match(rmd$lines[9], \"1 + \", fixed = TRUE)\n})\n\ntest_that(\"output gets unicode and colour\", {\n  skip_on_os(\"windows\")\n\n  rmd <- local_render(test_path(\"output.Rmd\"))\n  code <- xpath_xml(rmd$xml, \"//pre//code/span\")\n\n  expect_equal(xpath_attr(code[[1]], \"./span/span\", \"style\"), \"color: #0000BB;\")\n  expect_equal(xpath_text(code[[3]], \".\"), \"#> \\u2714\")\n})\n\ntest_that(\"interweaving of code and output generates correct html\", {\n  rmd <- local_render(test_path(\"knit-hooks.Rmd\"))\n  expect_snapshot_output(cat_line(rmd$lines))\n})\n\ntest_that(\"markdown div syntax is converted to native divs\", {\n  rmd <- local_render(test_path(\"div.Rmd\"))\n  expect_equal(xpath_attr(rmd$xml, \"//div\", \"class\"), \"special\")\n})\n\ntest_that(\"emojis are preserved\", {\n  rmd <- local_render(test_path(\"emoji.Rmd\"))\n  expect_equal(xpath_text(rmd$xml, trim = TRUE), \":smile_cat:\")\n})\n\ntest_that(\"math is untransformed\", {\n  rmd <- local_render(test_path(\"math.Rmd\"))\n  expect_equal(xpath_text(rmd$xml, trim = TRUE), \"$a_1 + b_2$\")\n})\n\ntest_that(\"raw html is preserved\", {\n  rmd <- local_render(test_path(\"raw-html.Rmd\"))\n\n  expect_equal(rmd$lines[[7]], \"<raw>\")\n  expect_equal(rmd$lines[[9]], \"This is <raw>\")\n})\n\ntest_that(\"hash added to yaml header\", {\n  rmd <- local_render(test_path(\"meta.Rmd\"))\n\n  yaml <- rmarkdown::yaml_front_matter(rmd$src)\n  yaml$rmd_hash <- rmd_hash(rmd$src)\n  expect_equal(rmarkdown::yaml_front_matter(rmd$dst), yaml)\n\n  # Test that yaml is preserved as is (i.e. no round-tripping)\n  expect_equal(rmd$lines[[4]], \"# this is a comment\")\n})\n\ntest_that(\"html dependencies are captured\", {\n  rmd <- local_render(test_path(\"widget.Rmd\"))\n\n  # Have copied over dependencies\n  widget_js <- path(rmd$dir, paste0(\"htmlwidgets-\", packageVersion(\"htmlwidgets\")))\n  expect_true(dir_exists(widget_js))\n\n  # And written in yaml metadata\n  yaml <- rmarkdown::yaml_front_matter(rmd$dst)\n  expect_type(yaml$html_dependencies, \"character\")\n  expect_true(length(yaml$html_dependencies) > 1)\n})\n\ntest_that(\"curly operator is escaped\", {\n  rmd <- local_render(test_path(\"curly.Rmd\"))\n\n  expect_match(rmd$lines[[9]], \"&#123;\")\n  expect_match(rmd$lines[[9]], \"&#125;\")\n})\n# helpers -----------------------------------------------------------------\n\ntest_that(\"link_inline() works with an nubmer of links\", {\n  expect_equal(link_inline(\"a\"), \"a\")\n  expect_equal(link_inline(\"`b`\"), \"`b`\")\n  expect_equal(link_inline(\"`c` `d`\"), \"`c` `d`\")\n\n  expect_equal(\n    link_inline(\"`stats::median`\"),\n    \"[`stats::median`](https://rdrr.io/r/stats/median.html)\"\n  )\n})\n\ntest_that(\"link_inline() doesn't link within links or headers\", {\n  expect_equal(link_inline(\"# `base::t`\"), \"# `base::t`\")\n  expect_equal(link_inline(\"[`base::t`]()\"), \"[`base::t`]()\")\n  expect_equal(link_inline(\"<pre>\\n`base::t`</pre>\"), \"<pre>\\n`base::t`</pre>\")\n})\n"
  },
  {
    "path": "tests/testthat/test-netlify.R",
    "content": "test_that(\"multiplication works\", {\n  path <- local_dir(test_path(\"config-hugodown\"))\n  suppressMessages(use_netlify_toml(path))\n\n  expect_true(file_exists(path(path, \"netlify.toml\")))\n\n  toml <- RcppTOML::parseTOML(path(path, \"netlify.toml\"))\n  expect_equal(toml$build$environment$HUGO_VERSION, \"0.66.0\")\n})\n"
  },
  {
    "path": "tests/testthat/test-post.R",
    "content": "test_that(\"archetypes use hugo or whisker templating\", {\n  skip_if_no_hugo()\n\n  site <- local_dir(test_path(\"archetypes\"))\n  dir_create(path(site, \"content\", \"Rmd\"))\n  dir_create(path(site, \"content\", \"md\"))\n\n  suppressMessages({\n    test_Rmd <- use_post(\"Rmd/test\", site = site, open = FALSE)\n    test_md <- use_post(\"md/test\", site = site, open = FALSE)\n  })\n\n  rmd <- brio::read_lines(path(test_Rmd, \"index.Rmd\"))\n  expect_equal(rmd[[2]], \"slug: test\")\n\n  md <- brio::read_lines(path(test_md, \"index.md\"))\n  expect_equal(md[[2]], \"slug: test\")\n})\n\ntest_that(\"catch common errors\", {\n  skip_if_no_hugo()\n\n  site <- local_dir(test_path(\"archetypes\"))\n  expect_error(use_post(\"Rmd/test\", site = site), \"Can't find\")\n\n  dir_create(path(site, \"content\", \"Rmd\"))\n  suppressMessages({\n    use_post(\"Rmd/test\", site = site, open = FALSE)\n    expect_error(use_post(\"Rmd/test\", site = site), \"already exists\")\n  })\n\n})\n"
  },
  {
    "path": "tests/testthat/test-shortcode-arguments.txt",
    "content": "> inline <- (function(...) cat(shortcode(..., .inline = TRUE)))\n> # No arguments\n> inline(\"name\")\n`{{< name >}}`{=html}\n\n> # Position vs name\n> inline(\"name\", 1, 2, 3)\n`{{< name 1 2 3 >}}`{=html}\n\n> inline(\"name\", x = 1, y = 2, z = 3)\n`{{< name x=1 y=2 z=3 >}}`{=html}\n\n> # Quoting\n> inline(\"name\", \"x\")\n`{{< name 'x' >}}`{=html}\n\n> inline(\"name\", I(\"'x'\"))\n`{{< name 'x' >}}`{=html}\n\n> # Contents\n> inline(\"name\", .contents = \"contents\")\n`{{< name >}}contents{{< /name >}}`{=html}\n\n"
  },
  {
    "path": "tests/testthat/test-shortcode-embed.txt",
    "content": "> embed_gist(\"spf13\", \"7896402\")\n[1] \"```{=html}\\n{{< gist 'spf13' '7896402' >}}\\n```\\n\"\n\n> embed_instagram(\"BWNjjyYFxVx\", caption = TRUE)\n[1] \"```{=html}\\n{{< instagram BWNjjyYFxVx >}}\\n```\\n\"\n\n> embed_instagram(\"BWNjjyYFxVx\", caption = FALSE)\n[1] \"```{=html}\\n{{< instagram BWNjjyYFxVx hidecaption >}}\\n```\\n\"\n\n> embed_tweet(\"877500564405444608\")\n[1] \"```{=html}\\n{{< tweet id='877500564405444608' >}}\\n```\\n\"\n\n> embed_vimeo(\"146022717\")\n[1] \"```{=html}\\n{{< vimeo 146022717 >}}\\n```\\n\"\n\n> embed_youtube(\"w7Ft2ymGmfc\", autoplay = FALSE)\n[1] \"```{=html}\\n{{< youtube id='w7Ft2ymGmfc' >}}\\n```\\n\"\n\n> embed_youtube(\"w7Ft2ymGmfc\", autoplay = TRUE)\n[1] \"```{=html}\\n{{< youtube id=w7Ft2ymGmfc autoplay='true' >}}\\n```\\n\"\n\n"
  },
  {
    "path": "tests/testthat/test-shortcode-wrapper.txt",
    "content": "> # type\n> cat(shortcode(\"name\", .output = \"md\"))\n```{=html}\n{{% name %}}\n```\n\n> cat(shortcode(\"name\", .output = \"html\"))\n```{=html}\n{{< name >}}\n```\n\n"
  },
  {
    "path": "tests/testthat/test-shortcode.R",
    "content": "test_that(\"handles all variants of argument specification\", {\n  verify_output(test_path(\"test-shortcode-arguments.txt\"), {\n    inline <- function(...) cat(shortcode(..., .inline = TRUE))\n    \"No arguments\"\n    inline(\"name\")\n\n    \"Position vs name\"\n    inline(\"name\", 1, 2, 3)\n    inline(\"name\", x = 1, y = 2, z = 3)\n\n    \"Quoting\"\n    inline(\"name\", \"x\")\n    inline(\"name\", I(\"'x'\"))\n\n    \"Contents\"\n    inline(\"name\", .contents = \"contents\")\n  })\n})\n\ntest_that(\"handles md and html output\", {\n  verify_output(test_path(\"test-shortcode-wrapper.txt\"), {\n    \"type\"\n    cat(shortcode(\"name\", .output = \"md\"))\n    cat(shortcode(\"name\", .output = \"html\"))\n  })\n})\n\n\ntest_that(\"test built-in embed shortcodes\", {\n  verify_output(test_path(\"test-shortcode-embed.txt\"), {\n    embed_gist(\"spf13\", \"7896402\")\n\n    embed_instagram(\"BWNjjyYFxVx\", caption = TRUE)\n    embed_instagram(\"BWNjjyYFxVx\", caption = FALSE)\n\n    embed_tweet(\"877500564405444608\")\n\n    embed_vimeo(\"146022717\")\n\n    embed_youtube(\"w7Ft2ymGmfc\", autoplay = FALSE)\n    embed_youtube(\"w7Ft2ymGmfc\", autoplay = TRUE)\n  })\n})\n"
  },
  {
    "path": "tests/testthat/test-site.R",
    "content": "test_that(\"recognises major config formats\", {\n  toml <- as.character(path_abs(test_path(\"config-toml\")))\n  expect_equal(site_root(toml), toml)\n\n  yaml <- as.character(path_abs(test_path(\"config-yaml\")))\n  expect_equal(site_root(yaml), yaml)\n\n  yml <- as.character(path_abs(test_path(\"config-yml\")))\n  expect_equal(site_root(yml), yml)\n})\n\ntest_that(\"walks up path to find root\", {\n  outdated <- as.character(path_abs(test_path(\"outdated\")))\n  expect_equal(site_root(path(outdated, \"content\")), outdated)\n  expect_equal(site_root(path(outdated, \"content\", \"blog\")), outdated)\n\n  expect_error(site_root(test_path(\".\")), \"config\")\n})\n\ntest_that(\"can find hugodown config\", {\n  config <- site_config(test_path(\"config-hugodown\"))\n  expect_equal(config, list(test = TRUE, hugo_version = \"0.66.0\"))\n})\n\n# out of date -------------------------------------------------------------\n\ntest_that(\"old blogdown posts don't need render\", {\n  blog <- test_path(\"outdated/content/blog\")\n\n  expect_false(rmd_needs_render(path(blog, \"ok-no-hash/index.Rmd\")))\n  expect_false(rmd_needs_render(path(blog, \"ok-has-html/index.Rmd\")))\n})\n\ntest_path(\"site_outdated() processes whole directory\", {\n  site <- test_path(\"outdated\")\n  outdated <- as.character(path_rel(site_outdated(site), site))\n\n  expect_equal(outdated, c(\n    \"content/blog/outdated-no-md/index.Rmd\",\n    \"content/blog/outdated-old-hash/index.Rmd\"\n  ))\n})\n"
  },
  {
    "path": "tests/testthat/test-tidy-pleased.txt",
    "content": "> set.seed(1014)\n> writeLines(replicate(20, tidy_pleased()))\nvery happy\nchuffed\nso happy\ndelighted\ndelighted\nthrilled\nhappy\ndelighted\ndelighted\nvery pleased\nthrilled\nhappy\nchuffed\nextremely pleased\ntickled pink\nstoked\nthrilled\ndelighted\nso happy\nchuffed\n\n"
  },
  {
    "path": "tests/testthat/test-tidy.R",
    "content": "test_that(\"tidy_post() adds additional data\", {\n  skip_if_no_hugo()\n\n  site <- local_dir(test_path(\"archetypes\"))\n  dir_create(path(site, \"content\", \"blog\"))\n  suppressMessages({\n    test_Rmd <- use_tidy_post(\"testthat-1-0-0\", site = site, open = FALSE)\n  })\n\n  rmd <- brio::read_lines(path(test_Rmd, \"index.Rmd\"))\n  expect_equal(rmd[[3]], \"package: testthat\")\n})\n\ntest_that(\"tidy_thumnail() complains about bad inputs\", {\n  skip_if_not_installed(\"magick\")\n\n  thumb_path <- function(x) test_path(\"thumbs\", x)\n  expect_error(use_tidy_thumbnails(thumb_path(\"missing\")), \"Can't find\")\n  expect_error(use_tidy_thumbnails(thumb_path(\"not-square\")), \"not square\")\n  expect_error(use_tidy_thumbnails(thumb_path(\"too-narrow\")), \"too narrow\")\n})\n\ntest_that(\"tidy_thumbnail() modifies images\", {\n  skip_if_not_installed(\"magick\")\n  path <- local_dir(test_path(\"thumbs\", \"ok\"))\n\n  use_tidy_thumbnails(path)\n\n  sq <- magick::image_info(magick::image_read(file.path(path, \"thumbnail-sq.jpg\")))\n  expect_equal(sq$width, 300)\n  expect_equal(sq$height, 300)\n\n  wd <- magick::image_info(magick::image_read(file.path(path, \"thumbnail-wd.jpg\")))\n  expect_equal(wd$width, 1000)\n  expect_equal(wd$height, 200)\n})\n\ntest_that(\"check_slug ensures name ok\", {\n  expect_error(check_slug(1), \"single string\")\n  expect_error(check_slug(letters[1:3]), \"single string\")\n\n  expect_error(check_slug(\"bad name\"), \"must not contain\")\n  expect_error(check_slug(\"bad.name\"), \"must not contain\")\n  expect_error(check_slug(\"bad_name\"), \"must not contain\")\n})\n\ntest_that(\"tidy_pleased() generates random phrases\", {\n  skip_if(getRversion() < \"3.6\") # RNG changed\n\n  verify_output(test_path(\"test-tidy-pleased.txt\"), {\n    set.seed(1014)\n    writeLines(replicate(20, tidy_pleased()))\n  })\n})\n"
  },
  {
    "path": "tests/testthat/widget.Rmd",
    "content": "---\noutput: hugodown::md_document\n---\n\n```{r}\nlibrary(DiagrammeR)\ngrViz(\"\n  digraph {\n    layout = twopi\n    node [shape = circle]\n    A -> {B C D} \n  }\")\n```\n"
  },
  {
    "path": "tests/testthat.R",
    "content": "library(testthat)\nlibrary(hugodown)\n\ntest_check(\"hugodown\")\n"
  },
  {
    "path": "vignettes/.gitignore",
    "content": "*.html\n*.R\n"
  },
  {
    "path": "vignettes/config.Rmd",
    "content": "---\ntitle: \"Configuration\"\noutput: rmarkdown::html_vignette\nvignette: >\n  %\\VignetteIndexEntry{Configuration}\n  %\\VignetteEngine{knitr::rmarkdown}\n  %\\VignetteEncoding{UTF-8}\n---\n\n```{r, include = FALSE}\nknitr::opts_chunk$set(\n  collapse = TRUE,\n  comment = \"#>\"\n)\n```\n\nThere are three types of configuration related to hugodown:\n\n-   hugo configuration, because hugodown assumes certain things to be true about your hugo setup.\n\n-   Syntax highlight css\n\n-   hugodown specific configuration, which allows you to control over various ways in which hugodown works.\n\n## Hugo\n\nhugodown does not work with every possible hugo site. There is some config that we assume (typically in `config.toml`, but hugo has a bewildering array of places that this might live instead.)\n\n-   You must use the goldmark markdown renderer, and set `unsafe: true`\n\n    ``` {.toml}\n    [markup]\n      defaultMarkdownHandler = \"goldmark\"\n      [markup.goldmark.renderer]\n        unsafe = true\n    ```\n\n-   For best syntax hightlighting results, you must use classes:\n\n    ``` {.toml}\n    pygmentsUseClasses = true\n    ```\n\n    Then you'll need to do some work on CSS side, see [below](#syntax-highlighting) for details.\n\n-   We recommend ignoring knitr intermediates:\n\n    ``` {.toml}\n    ignoreFiles = ['\\.Rmd$', '_files$', '_cache$', '\\.knit\\.md$', '\\.utf8\\.md$']\n    ```\n\n-   To use html widgets, you must include the following Go template somewhere in the `<head>` layout file for your theme. This will help Hugo find the HTML dependencies needed to render the widget in a post. You may find this [blog post](https://zwbetz.com/override-a-hugo-theme/) helpful for overriding Hugo layouts.\n\n        {{ range .Params.html_dependencies }}\n          {{ . | safeHTML }}\n        {{ end }}\n\n-   To use mathjax, you will need to use a series of [small hacks][yihui-mathjax]. The easiest way is to copy from an existing template, like [tourmaline]. Take note of the [`footer_mathjax.html`][footer\\_mathjax] partial, which is then included in the [`footer.html`][footer]. You'll also need to include [`math_code.js`][math\\_code] in your `static/` directory. Once that's done you can use inline math like `$math$`, and display math like `` `$$ math $$` `` (note the extra backtick compared to usual).\n\n## Syntax highlighting {#syntax-highlighting}\n\nThe hugo config above causes downlit/hugo to generate output html with the following structure:\n\n``` {.html}\n<div class=\"highlight\">\n  <pre class='chroma'><code class='language-r' data-lang='r'>\n    <span class='m'>1</span> <span class='o'>+</span> <span class='m'>1</span>\n    <span class='c'>#&gt; [1] 2</span>\n  </code></pre>\n</div>\n```\n\nTo have that look good on your website, you need to defines styles for the CSS necessary classes. You can generate starter CSS with the code below, substituting `pygments` for the [style of your choice](https://xyproto.github.io/splash/docs/longer/all.html):\n\n    hugo gen chromastyles --style=pygments > static/css/highlight.css\n\nThis generates a file containing definitions that look like this:\n\n``` {.css}\n/* Background */ .chroma {  }\n/* Other */ .chroma .x {  }\n/* Error */ .chroma .err {  }\n...\n/* Keyword */ .chroma .k { color: #008000; }\n...\n/* LiteralNumber */ .chroma .m { color: #666666 }\n...\n/* Operator */ .chroma .o { color: #666666 }\n```\n\nUnfortunately, the correct location for `highlight.css` file varies by theme, so you'll need to do a little detective work to figure out the best place to put it. Is it:\n\n-   A special file name?\n\n-   A `customCSS` param in the website configuration?\n\n-   A link in a custom layout?\n\nYou may also need to do some detective work to figure out how these styles interact with your existing styles, particularly for links within code. Your best bet is to use the [web developer console](https://developer.mozilla.org/en-US/docs/Tools/Web_Console/Opening_the_Web_Console) to figure out what's going wrong. You'll then need to figure out how to tweak `highlight.css` to override these styles. This is a pain, which is why hugodown ships with a couple of themes that are preconfigured.\n\n### highlight.js inactivation\n\nIf you are using an old hugo theme that uses highlight.js you may want to convert to server-side syntax highlighting. This is not required (and not important if you only use R code on your blog), but is a good idea if you show a variety of programming languages and want the code style to be as consistent as possible.\n\nFrom easiest to hardest, based on the theme you chose:\n\n-   Read how the theme currently handles syntax highlighting (docs might be in the GitHub/GitLab repo README or in the example site... that does not necessarily have search). If the theme docs indicate how to turn off highlight.js, yay, do that!\n-   Look for \"highlight\" in existing issues of your theme issue tracker: others might have also asked how to turn it off, and received ideas or posted their tricks.\n-   Otherwise, look for all occurrences of \"highlight\" in *the source* of the theme. Note that highlight.js works with JS and CSS so you might have to remove scripts, stylesheets, and/or links to them from layout files. Your theme might lack docs about syntax highlighting, but it might still contain docs about customization in general. If not you'll probably need to create custom head/footer where you use the theme head and footer minus references to highlight.js.\n\n## hugodown\n\nhugodown also has its own configuration file, `_hugodown.yaml`. Currently this has one option:\n\n-   `hugo_version`: this defines the version of hugo needed by the current site.\n"
  },
  {
    "path": "vignettes/deploy.Rmd",
    "content": "---\ntitle: \"Deployment\"\noutput: rmarkdown::html_vignette\nvignette: >\n  %\\VignetteIndexEntry{Deployment}\n  %\\VignetteEngine{knitr::rmarkdown}\n  %\\VignetteEncoding{UTF-8}\n---\n\n```{r, include = FALSE}\nknitr::opts_chunk$set(\n  collapse = TRUE,\n  comment = \"#>\"\n)\n```\n\nThis vignette describes the process of deployment, how you get your hugodown website off your local computer and on to the internet for everyone to see. The easiest workflow for most people is to use [netlify](https://www.netlify.com). I'll describe this process in details, and then discuss other approaches that require a manual build site.\n\n(Most of these techiques assume that you're already familiar with the basics of Git and GitHub. If you're not, you can try the Dropbox deployment described below, or try reading with [Happy Git and GitHub for the R user](http://happygitwithr.com/) by Jenny Bryan.)\n\n## Netlify\n\n(Adapted from [A Spoonful of Hugo: The netlify.toml File](https://alison.rbind.io/post/2017-06-12-up-and-running-with-blogdown/#deploy-in-netlify) by Alison Hill, with permission.)\n\nFirst, create an account if you don't already have one:\n\n1.  Navigate to [Netlify](https://www.netlify.com/) and click on the *Sign Up* link.\n\n    ```{r, echo = FALSE, out.width = \"400px\"}\n    knitr::include_graphics(\"netlify-landing.png\")\n    ```\n\n2.  Sign up with *GitHub* to connect your GitHub and Netlify accounts.\n\n    ```{r, echo = FALSE, out.width = \"400px\"}\n    knitr::include_graphics(\"netlify-sign-up.png\")\n    ```\n\n    If you use a different version control service, select GitLab or BitBucket instead.\n\nNext create a netlify site for your GitHub repo:\n\n1.  On the netlify website, go *New Site from Git* and pick your repo. You'll be prompted to fill in these fields. They are probably already filled in correctly for you:\n\n    ```{r, echo = FALSE, out.width = \"400px\"}\n    knitr::include_graphics(\"netlify-deploy-settings.png\")\n    ```\n\n    Leave the advanced settings as is, and click deploy site. (This won't work but we'll fix it momentarily.)\n\nFinally, configure your blog with `netlify.toml`. This prevents the biggest source of pain when deploying with netlify: version mismatches.\n\n1.  Check you have a `_hugodown.yaml` file that contains `hugo_version: 0.66.0` or similar. It's added automatically you created your site with a hugodown helper; you'll need to add it yourself if you've created the site another way.\n\n2.  Run `hugodown::use_netlify_toml()`, check the new `netlify.toml` in, commit, and push to Github.\n\nNow return to [netlify](https://app.netlify.com), and look in the deploy log. You should see entries like:\n\n    10:00:42 PM: Build ready to start\n    10:00:43 PM: build-image version: 8e315e54bc4032a32e73290be556cde4f8348c12\n    ...\n    10:00:56 PM: Found netlify.toml. Overriding site configuration\n    ...\n    10:01:02 PM: Installing Hugo 0.68.3\n    10:01:02 PM: Hugo Static Site Generator v0.68.3-157669A0 linux/amd64 BuildDate: 2020-03-24T12:05:34Z\n    ...\n    10:01:04 PM: Executing user command: hugo\n    10:01:04 PM: Building sites …\n    ...\n    10:01:23 PM: Site is live\n\nSuccess!\n\n## Manual builds\n\nThe advantage of netlify is that automatically runs hugo for you; in other deployment scenarios you'll need to run `hugodown::build_site()` and publish the `public/` directory that it creates. The following sections provide some advice for deployment scenarios that need this.\n\n### RStudio connect\n\nFor most sites, `rmarkdown::publish_site()` should just work.\n\nIf you deploy your site this way, and it doesn't look quite right (e.g. missing style sheets) it's likely because the theme you're using requires a `baseURL`. In this case, you'll need to update your `config.toml` with the URL for your site and republish.\n\n### GitHub pages\n\nYou'll need to make a few changes to your site:\n\n-   Run `file.create(\"static/.nojekyll\")`. This ensures that GitHub pages knows that you're using a regular HTML website, not a jekyll website (jekyll is GitHub's own blogging system).\n\n-   If you have a custom domain name, create a `static/CNAME` file containing your domain name (e.g. just `tidyverse.org`, not `https://tidyverse.org`). Note that setting a custom domain name in the admin settings on your GitHub repo will not work.\n\n-   In `config.toml`:\n\n    -   Set `publishDir = \"docs/\"`\n\n    -   Set `baseURL` to the url where you site will be published.\n\nTo deploy:\n\n-   Run `hugodown::build_site()` and check in the rendered `docs/` directory. (If no `docs/` directory is created, double check your config above).\n\nAfter the first deploy, you'll need to go the admin page for your repo and select \\\"master branch `/docs` folder) for source:\n\n```{r, echo = FALSE, out.width = \"400px\"}\nknitr::include_graphics(\"github-setup.png\")\n```\n\n### Site44 (dropbox)\n\nIf you don't use Git and GitHub, one deployment option is [Site44](https://www.site44.com/), a service that allows you to publish websites from within Dropbox folders. Site44 creates a `Dropbox/Apps/site44` directory, and any folders within that directory are published as websites.\n\nThe recommended workflow for deploying hugodown websites to Site44 is to develop your website in a separate project directory, and then, when it's ready for final publishing, run `build_site()` then copy the contents of the `public` directory to the folder for your website.\n\n### Amazon S3\n\nIf you are a user of Amazon Web Services you can serve your website directly from Amazon S3. This option is a bit more technically involved than GitHub Pages, Netlify, or Site 44. See the article on [Hosting a Static Website on Amazon S3](https://docs.aws.amazon.com/AmazonS3/latest/dev/WebsiteHosting.html) for additional details.\n"
  }
]