diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 1d7d564..0000000 --- a/.editorconfig +++ /dev/null @@ -1,25 +0,0 @@ -root = true - -[*] -charset = utf-8 -insert_final_newline = true -trim_trailing_whitespace = true - -[*.md] -indent_size = 2 -indent_style = space -max_line_length = 100 # Please keep this in sync with bin/lesson_check.py! - -[*.r] -max_line_length = 80 - -[*.py] -indent_size = 4 -indent_style = space -max_line_length = 79 - -[*.sh] -end_of_line = lf - -[Makefile] -indent_style = tab diff --git a/.github/workflows/README.md b/.github/workflows/README.md deleted file mode 100644 index 7076ddd..0000000 --- a/.github/workflows/README.md +++ /dev/null @@ -1,198 +0,0 @@ -# Carpentries Workflows - -This directory contains workflows to be used for Lessons using the {sandpaper} -lesson infrastructure. Two of these workflows require R (`sandpaper-main.yaml` -and `pr-receive.yaml`) and the rest are bots to handle pull request management. - -These workflows will likely change as {sandpaper} evolves, so it is important to -keep them up-to-date. To do this in your lesson you can do the following in your -R console: - -```r -# Install/Update sandpaper -options(repos = c(carpentries = "https://carpentries.r-universe.dev/", - CRAN = "https://cloud.r-project.org")) -install.packages("sandpaper") - -# update the workflows in your lesson -library("sandpaper") -update_github_workflows() -``` - -Inside this folder, you will find a file called `sandpaper-version.txt`, which -will contain a version number for sandpaper. This will be used in the future to -alert you if a workflow update is needed. - -What follows are the descriptions of the workflow files: - -## Deployment - -### 01 Build and Deploy (sandpaper-main.yaml) - -This is the main driver that will only act on the main branch of the repository. -This workflow does the following: - - 1. checks out the lesson - 2. provisions the following resources - - R - - pandoc - - lesson infrastructure (stored in a cache) - - lesson dependencies if needed (stored in a cache) - 3. builds the lesson via `sandpaper:::ci_deploy()` - -#### Caching - -This workflow has two caches; one cache is for the lesson infrastructure and -the other is for the the lesson dependencies if the lesson contains rendered -content. These caches are invalidated by new versions of the infrastructure and -the `renv.lock` file, respectively. If there is a problem with the cache, -manual invaliation is necessary. You will need maintain access to the repository -and you can either go to the actions tab and [click on the caches button to find -and invalidate the failing cache](https://github.blog/changelog/2022-10-20-manage-caches-in-your-actions-workflows-from-web-interface/) -or by setting the `CACHE_VERSION` secret to the current date (which will -invalidate all of the caches). - -## Updates - -### Setup Information - -These workflows run on a schedule and at the maintainer's request. Because they -create pull requests that update workflows/require the downstream actions to run, -they need a special repository/organization secret token called -`SANDPAPER_WORKFLOW` and it must have the `public_repo` and `workflow` scope. - -This can be an individual user token, OR it can be a trusted bot account. If you -have a repository in one of the official Carpentries accounts, then you do not -need to worry about this token being present because the Carpentries Core Team -will take care of supplying this token. - -If you want to use your personal account: you can go to - -to create a token. Once you have created your token, you should copy it to your -clipboard and then go to your repository's settings > secrets > actions and -create or edit the `SANDPAPER_WORKFLOW` secret, pasting in the generated token. - -If you do not specify your token correctly, the runs will not fail and they will -give you instructions to provide the token for your repository. - -### 02 Maintain: Update Workflow Files (update-workflow.yaml) - -The {sandpaper} repository was designed to do as much as possible to separate -the tools from the content. For local builds, this is absolutely true, but -there is a minor issue when it comes to workflow files: they must live inside -the repository. - -This workflow ensures that the workflow files are up-to-date. The way it work is -to download the update-workflows.sh script from GitHub and run it. The script -will do the following: - -1. check the recorded version of sandpaper against the current version on github -2. update the files if there is a difference in versions - -After the files are updated, if there are any changes, they are pushed to a -branch called `update/workflows` and a pull request is created. Maintainers are -encouraged to review the changes and accept the pull request if the outputs -are okay. - -This update is run weekly or on demand. - -### 03 Maintain: Update Package Cache (update-cache.yaml) - -For lessons that have generated content, we use {renv} to ensure that the output -is stable. This is controlled by a single lockfile which documents the packages -needed for the lesson and the version numbers. This workflow is skipped in -lessons that do not have generated content. - -Because the lessons need to remain current with the package ecosystem, it's a -good idea to make sure these packages can be updated periodically. The -update cache workflow will do this by checking for updates, applying them in a -branch called `updates/packages` and creating a pull request with _only the -lockfile changed_. - -From here, the markdown documents will be rebuilt and you can inspect what has -changed based on how the packages have updated. - -## Pull Request and Review Management - -Because our lessons execute code, pull requests are a secruity risk for any -lesson and thus have security measures associted with them. **Do not merge any -pull requests that do not pass checks and do not have bots commented on them.** - -This series of workflows all go together and are described in the following -diagram and the below sections: - -![Graph representation of a pull request](https://carpentries.github.io/sandpaper/articles/img/pr-flow.dot.svg) - -### Pre Flight Pull Request Validation (pr-preflight.yaml) - -This workflow runs every time a pull request is created and its purpose is to -validate that the pull request is okay to run. This means the following things: - -1. The pull request does not contain modified workflow files -2. If the pull request contains modified workflow files, it does not contain - modified content files (such as a situation where @carpentries-bot will - make an automated pull request) -3. The pull request does not contain an invalid commit hash (e.g. from a fork - that was made before a lesson was transitioned from styles to use the - workbench). - -Once the checks are finished, a comment is issued to the pull request, which -will allow maintainers to determine if it is safe to run the -"Receive Pull Request" workflow from new contributors. - -### Receive Pull Request (pr-receive.yaml) - -**Note of caution:** This workflow runs arbitrary code by anyone who creates a -pull request. GitHub has safeguarded the token used in this workflow to have no -priviledges in the repository, but we have taken precautions to protect against -spoofing. - -This workflow is triggered with every push to a pull request. If this workflow -is already running and a new push is sent to the pull request, the workflow -running from the previous push will be cancelled and a new workflow run will be -started. - -The first step of this workflow is to check if it is valid (e.g. that no -workflow files have been modified). If there are workflow files that have been -modified, a comment is made that indicates that the workflow is not run. If -both a workflow file and lesson content is modified, an error will occurr. - -The second step (if valid) is to build the generated content from the pull -request. This builds the content and uploads three artifacts: - -1. The pull request number (pr) -2. A summary of changes after the rendering process (diff) -3. The rendered files (build) - -Because this workflow builds generated content, it follows the same general -process as the `sandpaper-main` workflow with the same caching mechanisms. - -The artifacts produced are used by the next workflow. - -### Comment on Pull Request (pr-comment.yaml) - -This workflow is triggered if the `pr-receive.yaml` workflow is successful. -The steps in this workflow are: - -1. Test if the workflow is valid and comment the validity of the workflow to the - pull request. -2. If it is valid: create an orphan branch with two commits: the current state - of the repository and the proposed changes. -3. If it is valid: update the pull request comment with the summary of changes - -Importantly: if the pull request is invalid, the branch is not created so any -malicious code is not published. - -From here, the maintainer can request changes from the author and eventually -either merge or reject the PR. When this happens, if the PR was valid, the -preview branch needs to be deleted. - -### Send Close PR Signal (pr-close-signal.yaml) - -Triggered any time a pull request is closed. This emits an artifact that is the -pull request number for the next action - -### Remove Pull Request Branch (pr-post-remove-branch.yaml) - -Tiggered by `pr-close-signal.yaml`. This removes the temporary branch associated with -the pull request (if it was created). diff --git a/.github/workflows/pr-close-signal.yaml b/.github/workflows/pr-close-signal.yaml deleted file mode 100644 index b1303c2..0000000 --- a/.github/workflows/pr-close-signal.yaml +++ /dev/null @@ -1,22 +0,0 @@ -name: "Bot: Send Close Pull Request Signal" - -on: - pull_request: - types: - [closed] - -jobs: - send-close-signal: - name: "Send closing signal" - runs-on: ubuntu-22.04 - if: ${{ github.event.action == 'closed' }} - steps: - - name: "Create PRtifact" - run: | - mkdir -p ./pr - printf ${{ github.event.number }} > ./pr/NUM - - name: Upload Diff - uses: actions/upload-artifact@v4 - with: - name: pr - path: ./pr diff --git a/.github/workflows/pr-comment.yaml b/.github/workflows/pr-comment.yaml deleted file mode 100644 index f80d9d0..0000000 --- a/.github/workflows/pr-comment.yaml +++ /dev/null @@ -1,184 +0,0 @@ -name: "Bot: Comment on the Pull Request" - -# read-write repo token -# access to secrets -on: - workflow_run: - workflows: ["Receive Pull Request"] - types: - - completed - -concurrency: - group: pr-${{ github.event.workflow_run.pull_requests[0].number }} - cancel-in-progress: true - - -jobs: - # Pull requests are valid if: - # - they match the sha of the workflow run head commit - # - they are open - # - no .github files were committed - test-pr: - name: "Test if pull request is valid" - runs-on: ubuntu-22.04 - if: > - github.event.workflow_run.event == 'pull_request' && - github.event.workflow_run.conclusion == 'success' - outputs: - is_valid: ${{ steps.check-pr.outputs.VALID }} - payload: ${{ steps.check-pr.outputs.payload }} - number: ${{ steps.get-pr.outputs.NUM }} - msg: ${{ steps.check-pr.outputs.MSG }} - steps: - - name: 'Download PR artifact' - id: dl - uses: carpentries/actions/download-workflow-artifact@main - with: - run: ${{ github.event.workflow_run.id }} - name: 'pr' - - - name: "Get PR Number" - if: ${{ steps.dl.outputs.success == 'true' }} - id: get-pr - run: | - unzip pr.zip - echo "NUM=$(<./NR)" >> $GITHUB_OUTPUT - - - name: "Fail if PR number was not present" - id: bad-pr - if: ${{ steps.dl.outputs.success != 'true' }} - run: | - echo '::error::A pull request number was not recorded. The pull request that triggered this workflow is likely malicious.' - exit 1 - - name: "Get Invalid Hashes File" - id: hash - run: | - echo "json<> $GITHUB_OUTPUT - - name: "Check PR" - id: check-pr - if: ${{ steps.dl.outputs.success == 'true' }} - uses: carpentries/actions/check-valid-pr@main - with: - pr: ${{ steps.get-pr.outputs.NUM }} - sha: ${{ github.event.workflow_run.head_sha }} - headroom: 3 # if it's within the last three commits, we can keep going, because it's likely rapid-fire - invalid: ${{ fromJSON(steps.hash.outputs.json)[github.repository] }} - fail_on_error: true - - # Create an orphan branch on this repository with two commits - # - the current HEAD of the md-outputs branch - # - the output from running the current HEAD of the pull request through - # the md generator - create-branch: - name: "Create Git Branch" - needs: test-pr - runs-on: ubuntu-22.04 - if: ${{ needs.test-pr.outputs.is_valid == 'true' }} - env: - NR: ${{ needs.test-pr.outputs.number }} - permissions: - contents: write - steps: - - name: 'Checkout md outputs' - uses: actions/checkout@v4 - with: - ref: md-outputs - path: built - fetch-depth: 1 - - - name: 'Download built markdown' - id: dl - uses: carpentries/actions/download-workflow-artifact@main - with: - run: ${{ github.event.workflow_run.id }} - name: 'built' - - - if: ${{ steps.dl.outputs.success == 'true' }} - run: unzip built.zip - - - name: "Create orphan and push" - if: ${{ steps.dl.outputs.success == 'true' }} - run: | - cd built/ - git config --local user.email "actions@github.com" - git config --local user.name "GitHub Actions" - CURR_HEAD=$(git rev-parse HEAD) - git checkout --orphan md-outputs-PR-${NR} - git add -A - git commit -m "source commit: ${CURR_HEAD}" - ls -A | grep -v '^.git$' | xargs -I _ rm -r '_' - cd .. - unzip -o -d built built.zip - cd built - git add -A - git commit --allow-empty -m "differences for PR #${NR}" - git push -u --force --set-upstream origin md-outputs-PR-${NR} - - # Comment on the Pull Request with a link to the branch and the diff - comment-pr: - name: "Comment on Pull Request" - needs: [test-pr, create-branch] - runs-on: ubuntu-22.04 - if: ${{ needs.test-pr.outputs.is_valid == 'true' }} - env: - NR: ${{ needs.test-pr.outputs.number }} - permissions: - pull-requests: write - steps: - - name: 'Download comment artifact' - id: dl - uses: carpentries/actions/download-workflow-artifact@main - with: - run: ${{ github.event.workflow_run.id }} - name: 'diff' - - - if: ${{ steps.dl.outputs.success == 'true' }} - run: unzip ${{ github.workspace }}/diff.zip - - - name: "Comment on PR" - id: comment-diff - if: ${{ steps.dl.outputs.success == 'true' }} - uses: carpentries/actions/comment-diff@main - with: - pr: ${{ env.NR }} - path: ${{ github.workspace }}/diff.md - - # Comment if the PR is open and matches the SHA, but the workflow files have - # changed - comment-changed-workflow: - name: "Comment if workflow files have changed" - needs: test-pr - runs-on: ubuntu-22.04 - if: ${{ always() && needs.test-pr.outputs.is_valid == 'false' }} - env: - NR: ${{ github.event.workflow_run.pull_requests[0].number }} - body: ${{ needs.test-pr.outputs.msg }} - permissions: - pull-requests: write - steps: - - name: 'Check for spoofing' - id: dl - uses: carpentries/actions/download-workflow-artifact@main - with: - run: ${{ github.event.workflow_run.id }} - name: 'built' - - - name: 'Alert if spoofed' - id: spoof - if: ${{ steps.dl.outputs.success == 'true' }} - run: | - echo 'body<> $GITHUB_ENV - echo '' >> $GITHUB_ENV - echo '## :x: DANGER :x:' >> $GITHUB_ENV - echo 'This pull request has modified workflows that created output. Close this now.' >> $GITHUB_ENV - echo '' >> $GITHUB_ENV - echo 'EOF' >> $GITHUB_ENV - - - name: "Comment on PR" - id: comment-diff - uses: carpentries/actions/comment-diff@main - with: - pr: ${{ env.NR }} - body: ${{ env.body }} diff --git a/.github/workflows/pr-post-remove-branch.yaml b/.github/workflows/pr-post-remove-branch.yaml deleted file mode 100644 index 9419e2b..0000000 --- a/.github/workflows/pr-post-remove-branch.yaml +++ /dev/null @@ -1,32 +0,0 @@ -name: "Bot: Remove Temporary PR Branch" - -on: - workflow_run: - workflows: ["Bot: Send Close Pull Request Signal"] - types: - - completed - -jobs: - delete: - name: "Delete branch from Pull Request" - runs-on: ubuntu-22.04 - if: > - github.event.workflow_run.event == 'pull_request' && - github.event.workflow_run.conclusion == 'success' - permissions: - contents: write - steps: - - name: 'Download artifact' - uses: carpentries/actions/download-workflow-artifact@main - with: - run: ${{ github.event.workflow_run.id }} - name: pr - - name: "Get PR Number" - id: get-pr - run: | - unzip pr.zip - echo "NUM=$(<./NUM)" >> $GITHUB_OUTPUT - - name: 'Remove branch' - uses: carpentries/actions/remove-branch@main - with: - pr: ${{ steps.get-pr.outputs.NUM }} diff --git a/.github/workflows/pr-preflight.yaml b/.github/workflows/pr-preflight.yaml deleted file mode 100644 index 34ad7ae..0000000 --- a/.github/workflows/pr-preflight.yaml +++ /dev/null @@ -1,39 +0,0 @@ -name: "Pull Request Preflight Check" - -on: - pull_request_target: - branches: - ["main"] - types: - ["opened", "synchronize", "reopened"] - -jobs: - test-pr: - name: "Test if pull request is valid" - if: ${{ github.event.action != 'closed' }} - runs-on: ubuntu-22.04 - outputs: - is_valid: ${{ steps.check-pr.outputs.VALID }} - permissions: - pull-requests: write - steps: - - name: "Get Invalid Hashes File" - id: hash - run: | - echo "json<> $GITHUB_OUTPUT - - name: "Check PR" - id: check-pr - uses: carpentries/actions/check-valid-pr@main - with: - pr: ${{ github.event.number }} - invalid: ${{ fromJSON(steps.hash.outputs.json)[github.repository] }} - fail_on_error: true - - name: "Comment result of validation" - id: comment-diff - if: ${{ always() }} - uses: carpentries/actions/comment-diff@main - with: - pr: ${{ github.event.number }} - body: ${{ steps.check-pr.outputs.MSG }} diff --git a/.github/workflows/pr-receive.yaml b/.github/workflows/pr-receive.yaml deleted file mode 100644 index 7fbff6c..0000000 --- a/.github/workflows/pr-receive.yaml +++ /dev/null @@ -1,132 +0,0 @@ -name: "Receive Pull Request" - -on: - pull_request: - types: - [opened, synchronize, reopened] - -concurrency: - group: ${{ github.ref }} - cancel-in-progress: true - -jobs: - test-pr: - name: "Record PR number" - if: ${{ github.event.action != 'closed' }} - runs-on: ubuntu-22.04 - outputs: - is_valid: ${{ steps.check-pr.outputs.VALID }} - steps: - - name: "Record PR number" - id: record - if: ${{ always() }} - run: | - echo ${{ github.event.number }} > ${{ github.workspace }}/NR # 2022-03-02: artifact name fixed to be NR - - name: "Upload PR number" - id: upload - if: ${{ always() }} - uses: actions/upload-artifact@v4 - with: - name: pr - path: ${{ github.workspace }}/NR - - name: "Get Invalid Hashes File" - id: hash - run: | - echo "json<> $GITHUB_OUTPUT - - name: "echo output" - run: | - echo "${{ steps.hash.outputs.json }}" - - name: "Check PR" - id: check-pr - uses: carpentries/actions/check-valid-pr@main - with: - pr: ${{ github.event.number }} - invalid: ${{ fromJSON(steps.hash.outputs.json)[github.repository] }} - - build-md-source: - name: "Build markdown source files if valid" - needs: test-pr - runs-on: ubuntu-22.04 - if: ${{ needs.test-pr.outputs.is_valid == 'true' }} - env: - GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} - RENV_PATHS_ROOT: ~/.local/share/renv/ - CHIVE: ${{ github.workspace }}/site/chive - PR: ${{ github.workspace }}/site/pr - MD: ${{ github.workspace }}/site/built - steps: - - name: "Check Out Main Branch" - uses: actions/checkout@v4 - - - name: "Check Out Staging Branch" - uses: actions/checkout@v4 - with: - ref: md-outputs - path: ${{ env.MD }} - - - name: "Set up R" - uses: r-lib/actions/setup-r@v2 - with: - use-public-rspm: true - install-r: false - - - name: "Set up Pandoc" - uses: r-lib/actions/setup-pandoc@v2 - - - name: "Setup Lesson Engine" - uses: carpentries/actions/setup-sandpaper@main - with: - cache-version: ${{ secrets.CACHE_VERSION }} - - - name: "Setup Package Cache" - uses: carpentries/actions/setup-lesson-deps@main - with: - cache-version: ${{ secrets.CACHE_VERSION }} - - - name: "Validate and Build Markdown" - id: build-site - run: | - sandpaper::package_cache_trigger(TRUE) - sandpaper::validate_lesson(path = '${{ github.workspace }}') - sandpaper:::build_markdown(path = '${{ github.workspace }}', quiet = FALSE) - shell: Rscript {0} - - - name: "Generate Artifacts" - id: generate-artifacts - run: | - sandpaper:::ci_bundle_pr_artifacts( - repo = '${{ github.repository }}', - pr_number = '${{ github.event.number }}', - path_md = '${{ env.MD }}', - path_pr = '${{ env.PR }}', - path_archive = '${{ env.CHIVE }}', - branch = 'md-outputs' - ) - shell: Rscript {0} - - - name: "Upload PR" - uses: actions/upload-artifact@v4 - with: - name: pr - path: ${{ env.PR }} - overwrite: true - - - name: "Upload Diff" - uses: actions/upload-artifact@v4 - with: - name: diff - path: ${{ env.CHIVE }} - retention-days: 1 - - - name: "Upload Build" - uses: actions/upload-artifact@v4 - with: - name: built - path: ${{ env.MD }} - retention-days: 1 - - - name: "Teardown" - run: sandpaper::reset_site() - shell: Rscript {0} diff --git a/.github/workflows/sandpaper-main.yaml b/.github/workflows/sandpaper-main.yaml deleted file mode 100644 index b3d1de8..0000000 --- a/.github/workflows/sandpaper-main.yaml +++ /dev/null @@ -1,64 +0,0 @@ -name: "01 Build and Deploy Site" - -on: - push: - branches: - - main - - master - schedule: - - cron: '0 0 * * 2' - workflow_dispatch: - inputs: - name: - description: 'Who triggered this build?' - required: true - default: 'Maintainer (via GitHub)' - reset: - description: 'Reset cached markdown files' - required: false - default: false - type: boolean -jobs: - full-build: - name: "Build Full Site" - - # 2024-10-01: ubuntu-latest is now 24.04 and R is not installed by default in the runner image - # pin to 22.04 for now - runs-on: ubuntu-22.04 - permissions: - checks: write - contents: write - pages: write - env: - GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} - RENV_PATHS_ROOT: ~/.local/share/renv/ - steps: - - - name: "Checkout Lesson" - uses: actions/checkout@v4 - - - name: "Set up R" - uses: r-lib/actions/setup-r@v2 - with: - use-public-rspm: true - install-r: false - - - name: "Set up Pandoc" - uses: r-lib/actions/setup-pandoc@v2 - - - name: "Setup Lesson Engine" - uses: carpentries/actions/setup-sandpaper@main - with: - cache-version: ${{ secrets.CACHE_VERSION }} - - - name: "Setup Package Cache" - uses: carpentries/actions/setup-lesson-deps@main - with: - cache-version: ${{ secrets.CACHE_VERSION }} - - - name: "Deploy Site" - run: | - reset <- "${{ github.event.inputs.reset }}" == "true" - sandpaper::package_cache_trigger(TRUE) - sandpaper:::ci_deploy(reset = reset) - shell: Rscript {0} diff --git a/.github/workflows/sandpaper-version.txt b/.github/workflows/sandpaper-version.txt deleted file mode 100644 index f2f6c13..0000000 --- a/.github/workflows/sandpaper-version.txt +++ /dev/null @@ -1 +0,0 @@ -0.16.11 diff --git a/.github/workflows/update-cache.yaml b/.github/workflows/update-cache.yaml deleted file mode 100644 index a011c0c..0000000 --- a/.github/workflows/update-cache.yaml +++ /dev/null @@ -1,125 +0,0 @@ -name: "03 Maintain: Update Package Cache" - -on: - workflow_dispatch: - inputs: - name: - description: 'Who triggered this build (enter github username to tag yourself)?' - required: true - default: 'monthly run' - schedule: - # Run every tuesday - - cron: '0 0 * * 2' - -jobs: - preflight: - name: "Preflight Check" - runs-on: ubuntu-22.04 - outputs: - ok: ${{ steps.check.outputs.ok }} - steps: - - id: check - run: | - if [[ ${{ github.event_name }} == 'workflow_dispatch' ]]; then - echo "ok=true" >> $GITHUB_OUTPUT - echo "Running on request" - # using single brackets here to avoid 08 being interpreted as octal - # https://github.com/carpentries/sandpaper/issues/250 - elif [ `date +%d` -le 7 ]; then - # If the Tuesday lands in the first week of the month, run it - echo "ok=true" >> $GITHUB_OUTPUT - echo "Running on schedule" - else - echo "ok=false" >> $GITHUB_OUTPUT - echo "Not Running Today" - fi - - check_renv: - name: "Check if We Need {renv}" - runs-on: ubuntu-22.04 - needs: preflight - if: ${{ needs.preflight.outputs.ok == 'true'}} - outputs: - needed: ${{ steps.renv.outputs.exists }} - steps: - - name: "Checkout Lesson" - uses: actions/checkout@v4 - - id: renv - run: | - if [[ -d renv ]]; then - echo "exists=true" >> $GITHUB_OUTPUT - fi - - check_token: - name: "Check SANDPAPER_WORKFLOW token" - runs-on: ubuntu-22.04 - needs: check_renv - if: ${{ needs.check_renv.outputs.needed == 'true' }} - outputs: - workflow: ${{ steps.validate.outputs.wf }} - repo: ${{ steps.validate.outputs.repo }} - steps: - - name: "validate token" - id: validate - uses: carpentries/actions/check-valid-credentials@main - with: - token: ${{ secrets.SANDPAPER_WORKFLOW }} - - update_cache: - name: "Update Package Cache" - needs: check_token - if: ${{ needs.check_token.outputs.repo== 'true' }} - runs-on: ubuntu-22.04 - env: - GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} - RENV_PATHS_ROOT: ~/.local/share/renv/ - steps: - - - name: "Checkout Lesson" - uses: actions/checkout@v4 - - - name: "Set up R" - uses: r-lib/actions/setup-r@v2 - with: - use-public-rspm: true - install-r: false - - - name: "Update {renv} deps and determine if a PR is needed" - id: update - uses: carpentries/actions/update-lockfile@main - with: - cache-version: ${{ secrets.CACHE_VERSION }} - - - name: Create Pull Request - id: cpr - if: ${{ steps.update.outputs.n > 0 }} - uses: carpentries/create-pull-request@main - with: - token: ${{ secrets.SANDPAPER_WORKFLOW }} - delete-branch: true - branch: "update/packages" - commit-message: "[actions] update ${{ steps.update.outputs.n }} packages" - title: "Update ${{ steps.update.outputs.n }} packages" - body: | - :robot: This is an automated build - - This will update ${{ steps.update.outputs.n }} packages in your lesson with the following versions: - - ``` - ${{ steps.update.outputs.report }} - ``` - - :stopwatch: In a few minutes, a comment will appear that will show you how the output has changed based on these updates. - - If you want to inspect these changes locally, you can use the following code to check out a new branch: - - ```bash - git fetch origin update/packages - git checkout update/packages - ``` - - - Auto-generated by [create-pull-request][1] on ${{ steps.update.outputs.date }} - - [1]: https://github.com/carpentries/create-pull-request/tree/main - labels: "type: package cache" - draft: false diff --git a/.github/workflows/update-workflows.yaml b/.github/workflows/update-workflows.yaml deleted file mode 100644 index 6414cf2..0000000 --- a/.github/workflows/update-workflows.yaml +++ /dev/null @@ -1,66 +0,0 @@ -name: "02 Maintain: Update Workflow Files" - -on: - workflow_dispatch: - inputs: - name: - description: 'Who triggered this build (enter github username to tag yourself)?' - required: true - default: 'weekly run' - clean: - description: 'Workflow files/file extensions to clean (no wildcards, enter "" for none)' - required: false - default: '.yaml' - schedule: - # Run every Tuesday - - cron: '0 0 * * 2' - -jobs: - check_token: - name: "Check SANDPAPER_WORKFLOW token" - runs-on: ubuntu-22.04 - outputs: - workflow: ${{ steps.validate.outputs.wf }} - repo: ${{ steps.validate.outputs.repo }} - steps: - - name: "validate token" - id: validate - uses: carpentries/actions/check-valid-credentials@main - with: - token: ${{ secrets.SANDPAPER_WORKFLOW }} - - update_workflow: - name: "Update Workflow" - runs-on: ubuntu-22.04 - needs: check_token - if: ${{ needs.check_token.outputs.workflow == 'true' }} - steps: - - name: "Checkout Repository" - uses: actions/checkout@v4 - - - name: Update Workflows - id: update - uses: carpentries/actions/update-workflows@main - with: - clean: ${{ github.event.inputs.clean }} - - - name: Create Pull Request - id: cpr - if: "${{ steps.update.outputs.new }}" - uses: carpentries/create-pull-request@main - with: - token: ${{ secrets.SANDPAPER_WORKFLOW }} - delete-branch: true - branch: "update/workflows" - commit-message: "[actions] update sandpaper workflow to version ${{ steps.update.outputs.new }}" - title: "Update Workflows to Version ${{ steps.update.outputs.new }}" - body: | - :robot: This is an automated build - - Update Workflows from sandpaper version ${{ steps.update.outputs.old }} -> ${{ steps.update.outputs.new }} - - - Auto-generated by [create-pull-request][1] on ${{ steps.update.outputs.date }} - - [1]: https://github.com/carpentries/create-pull-request/tree/main - labels: "type: template and tools" - draft: false diff --git a/.gitignore b/.gitignore deleted file mode 100644 index c001767..0000000 --- a/.gitignore +++ /dev/null @@ -1,57 +0,0 @@ -# sandpaper files -episodes/*html -site/* -!site/README.md - -# History files -.Rhistory -.Rapp.history -# Session Data files -.RData -# User-specific files -.Ruserdata -# Example code in package build process -*-Ex.R -# Output files from R CMD build -/*.tar.gz -# Output files from R CMD check -/*.Rcheck/ -# RStudio files -.Rproj.user/ -# produced vignettes -vignettes/*.html -vignettes/*.pdf -# OAuth2 token, see https://github.com/hadley/httr/releases/tag/v0.3 -.httr-oauth -# knitr and R markdown default cache directories -*_cache/ -/cache/ -# Temporary files created by R markdown -*.utf8.md -*.knit.md -# R Environment Variables -.Renviron -# pkgdown site -docs/ -# translation temp files -po/*~ -# renv detritus -renv/sandbox/ -*.pyc -*~ -.DS_Store -.ipynb_checkpoints -.sass-cache -.jekyll-cache/ -__pycache__ -_site -.Rproj.user -.bundle/ -.vendor/ -vendor/ -.docker-vendor/ -Gemfile.lock -.*history - -# Course developer file to testing lesson code -test.ipynb \ No newline at end of file diff --git a/episodes/01-introduction.md b/01-introduction.md similarity index 100% rename from episodes/01-introduction.md rename to 01-introduction.md diff --git a/episodes/02-dictionaries.md b/02-dictionaries.md similarity index 100% rename from episodes/02-dictionaries.md rename to 02-dictionaries.md diff --git a/episodes/03-numpy_essential.md b/03-numpy_essential.md similarity index 100% rename from episodes/03-numpy_essential.md rename to 03-numpy_essential.md diff --git a/episodes/04-software_package_management.md b/04-software_package_management.md similarity index 100% rename from episodes/04-software_package_management.md rename to 04-software_package_management.md diff --git a/episodes/05-defensive_programming.md b/05-defensive_programming.md similarity index 100% rename from episodes/05-defensive_programming.md rename to 05-defensive_programming.md diff --git a/episodes/06-units_and_quantities.md b/06-units_and_quantities.md similarity index 100% rename from episodes/06-units_and_quantities.md rename to 06-units_and_quantities.md diff --git a/episodes/07-pandas_essential.md b/07-pandas_essential.md similarity index 100% rename from episodes/07-pandas_essential.md rename to 07-pandas_essential.md diff --git a/AUTHORS b/AUTHORS deleted file mode 100644 index c6d0539..0000000 --- a/AUTHORS +++ /dev/null @@ -1,9 +0,0 @@ -Douglas Lowe douglas.lowe@manchester.ac.uk -Ann Gledson -Anthony Evans -Hugo Chu -Lasse Schmieding -Peter Crowther -Sarah Jaffa -Scott Archer-Nicholls -Andrew Gait \ No newline at end of file diff --git a/CITATION b/CITATION deleted file mode 100644 index 56ece3c..0000000 --- a/CITATION +++ /dev/null @@ -1 +0,0 @@ -FIXME: describe how to cite this lesson. \ No newline at end of file diff --git a/CITATION.cff b/CITATION.cff deleted file mode 100644 index 8664c63..0000000 --- a/CITATION.cff +++ /dev/null @@ -1,22 +0,0 @@ -# This template CITATION.cff file was generated with cffinit. -# Visit https://bit.ly/cffinit to replace its contents -# with information about your lesson. -# Remember to update this file periodically, -# ensuring that the author list and other fields remain accurate. - -cff-version: 1.2.0 -title: FIXME -message: >- - Please cite this lesson using the information in this file - when you refer to it in publications, and/or if you - re-use, adapt, or expand on the content in your own - training material. -type: dataset -authors: - - given-names: FIXME - family-names: FIXME -abstract: >- - FIXME Replace this with a short abstract describing the - lesson, e.g. its target audience and main intended - learning objectives. -license: CC-BY-4.0 \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 6c2b81c..0000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,123 +0,0 @@ -## Contributing - -[The Carpentries][cp-site] ([Software Carpentry][swc-site], [Data -Carpentry][dc-site], and [Library Carpentry][lc-site]) are open source -projects, and we welcome contributions of all kinds: new lessons, fixes to -existing material, bug reports, and reviews of proposed changes are all -welcome. - -### Contributor Agreement - -By contributing, you agree that we may redistribute your work under [our -license](LICENSE.md). In exchange, we will address your issues and/or assess -your change proposal as promptly as we can, and help you become a member of our -community. Everyone involved in [The Carpentries][cp-site] agrees to abide by -our [code of conduct](CODE_OF_CONDUCT.md). - -### How to Contribute - -The easiest way to get started is to file an issue to tell us about a spelling -mistake, some awkward wording, or a factual error. This is a good way to -introduce yourself and to meet some of our community members. - -1. If you do not have a [GitHub][github] account, you can [send us comments by - email][contact]. However, we will be able to respond more quickly if you use - one of the other methods described below. - -2. If you have a [GitHub][github] account, or are willing to [create - one][github-join], but do not know how to use Git, you can report problems - or suggest improvements by [creating an issue][repo-issues]. This allows us - to assign the item to someone and to respond to it in a threaded discussion. - -3. If you are comfortable with Git, and would like to add or change material, - you can submit a pull request (PR). Instructions for doing this are - [included below](#using-github). For inspiration about changes that need to - be made, check out the [list of open issues][issues] across the Carpentries. - -Note: if you want to build the website locally, please refer to [The Workbench -documentation][template-doc]. - -### Where to Contribute - -1. If you wish to change this lesson, add issues and pull requests here. -2. If you wish to change the template used for workshop websites, please refer - to [The Workbench documentation][template-doc]. - - -### What to Contribute - -There are many ways to contribute, from writing new exercises and improving -existing ones to updating or filling in the documentation and submitting [bug -reports][issues] about things that do not work, are not clear, or are missing. -If you are looking for ideas, please see [the list of issues for this -repository][repo-issues], or the issues for [Data Carpentry][dc-issues], -[Library Carpentry][lc-issues], and [Software Carpentry][swc-issues] projects. - -Comments on issues and reviews of pull requests are just as welcome: we are -smarter together than we are on our own. **Reviews from novices and newcomers -are particularly valuable**: it's easy for people who have been using these -lessons for a while to forget how impenetrable some of this material can be, so -fresh eyes are always welcome. - -### What *Not* to Contribute - -Our lessons already contain more material than we can cover in a typical -workshop, so we are usually *not* looking for more concepts or tools to add to -them. As a rule, if you want to introduce a new idea, you must (a) estimate how -long it will take to teach and (b) explain what you would take out to make room -for it. The first encourages contributors to be honest about requirements; the -second, to think hard about priorities. - -We are also not looking for exercises or other material that only run on one -platform. Our workshops typically contain a mixture of Windows, macOS, and -Linux users; in order to be usable, our lessons must run equally well on all -three. - -### Using GitHub - -If you choose to contribute via GitHub, you may want to look at [How to -Contribute to an Open Source Project on GitHub][how-contribute]. In brief, we -use [GitHub flow][github-flow] to manage changes: - -1. Create a new branch in your desktop copy of this repository for each - significant change. -2. Commit the change in that branch. -3. Push that branch to your fork of this repository on GitHub. -4. Submit a pull request from that branch to the [upstream repository][repo]. -5. If you receive feedback, make changes on your desktop and push to your - branch on GitHub: the pull request will update automatically. - -NB: The published copy of the lesson is usually in the `main` branch. - -Each lesson has a team of maintainers who review issues and pull requests or -encourage others to do so. The maintainers are community volunteers, and have -final say over what gets merged into the lesson. - -### Other Resources - -The Carpentries is a global organisation with volunteers and learners all over -the world. We share values of inclusivity and a passion for sharing knowledge, -teaching and learning. There are several ways to connect with The Carpentries -community listed at including via social -media, slack, newsletters, and email lists. You can also [reach us by -email][contact]. - -[repo]: https://example.com/FIXME -[repo-issues]: https://example.com/FIXME/issues -[contact]: mailto:team@carpentries.org -[cp-site]: https://carpentries.org/ -[dc-issues]: https://github.com/issues?q=user%3Adatacarpentry -[dc-lessons]: https://datacarpentry.org/lessons/ -[dc-site]: https://datacarpentry.org/ -[discuss-list]: https://carpentries.topicbox.com/groups/discuss -[github]: https://github.com -[github-flow]: https://guides.github.com/introduction/flow/ -[github-join]: https://github.com/join -[how-contribute]: https://egghead.io/courses/how-to-contribute-to-an-open-source-project-on-github -[issues]: https://carpentries.org/help-wanted-issues/ -[lc-issues]: https://github.com/issues?q=user%3ALibraryCarpentry -[swc-issues]: https://github.com/issues?q=user%3Aswcarpentry -[swc-lessons]: https://software-carpentry.org/lessons/ -[swc-site]: https://software-carpentry.org/ -[lc-site]: https://librarycarpentry.org/ -[template-doc]: https://carpentries.github.io/workbench/ diff --git a/README.md b/README.md deleted file mode 100644 index 19d5c53..0000000 --- a/README.md +++ /dev/null @@ -1,84 +0,0 @@ -> **ATTENTION** This is an experimental test of [The Carpentries Workbench](https://carpentries.github.io/workbench) lesson infrastructure. -> It was automatically converted from the source lesson via [the lesson transition script](https://github.com/carpentries/lesson-transition/). -> -> If anything seems off, please contact Zhian Kamvar [zkamvar@carpentries.org](mailto:zkamvar@carpentries.org) - -# Programming with Python - -[![Create a Slack Account with us](https://img.shields.io/badge/Create_Slack_Account-The_Carpentries-071159.svg)](https://swc-slack-invite.herokuapp.com/) - -**Thanks for contributing to The Carpentries Incubator!** -This repository provides a blank starting point for lessons to be developed here. - -A member of the [Carpentries Curriculum Team](https://carpentries.org/team/) -will work with you to get your lesson listed on the -[Community Developed Lessons page][community-lessons] -and make sure you have everything you need to begin developing your new lesson. - -## What to do next - -Before you begin developing your new lesson, -here are a few things we recommend you do: - -- [ ] Decide on a title for your new lesson! -Once you've chosen a new title, you can set the value for `lesson_title` -in <_config.yml> -- [ ] Add the URL to your built lesson pages to the repository description\* -- [ ] [Add relevant topic tags to your lesson repository][cdh-topic-tags]. -- [ ] Fill in the fields marked `FIXME` in: -- this README -- <_config.yml> -- [ ] If you're going to be developing lesson material for the first time -according to our design principles, -consider reading the [Carpentries Curriculum Development Handbook][cdh] -- [ ] Consult the [Lesson Example][lesson-example] website to find out more about -working with the lesson template -- [ ] If you are planning to write your lesson in RMarkdown, -[create a `main` branch and set this as the default branch in your repository settings][change-default-branch] -- [ ] Update this README with relevant information about your lesson -and delete this section - -\* To set the URL on GitHub, click the gear wheel button next to **About** -on the right of the repository landing page. -The lesson URL structure is **\**: -a repository at will have pages at -the lesson URL . - -## Contributing - -We welcome all contributions to improve the lesson! Maintainers will do their best to help you if you have any -questions, concerns, or experience any difficulties along the way. - -We'd like to ask you to familiarize yourself with our [Contribution Guide](CONTRIBUTING.md) and have a look at -the [more detailed guidelines][lesson-example] on proper formatting, ways to render the lesson locally, and even -how to write new episodes. - -Please see the current list of [issues][FIXME] for ideas for contributing to this -repository. For making your contribution, we use the GitHub flow, which is -nicely explained in the chapter [Contributing to a Project](https://git-scm.com/book/en/v2/GitHub-Contributing-to-a-Project) in Pro Git -by Scott Chacon. -Look for the tag ![good\_first\_issue](https://img.shields.io/badge/-good%20first%20issue-gold.svg). This indicates that the maintainers will welcome a pull request fixing this issue. - -## Maintainer(s) - -Current maintainers of this lesson are - -- Scott Archer-Nicholls -- Andrew Gait - -## Authors - -A list of contributors to the lesson can be found in - -## Citation - -To cite this lesson, please consult with - -[community-lessons]: https://carpentries.org/community-lessons -[cdh-topic-tags]: https://cdh.carpentries.org/the-carpentries-incubator.html#topic-tags -[cdh]: https://cdh.carpentries.org -[lesson-example]: https://carpentries.github.io/lesson-example -[change-default-branch]: https://docs.github.com/en/github/administering-a-repository/changing-the-default-branch - - - diff --git a/buoyant-barnacle-2.Rproj b/buoyant-barnacle-2.Rproj deleted file mode 100644 index 7bdb19d..0000000 --- a/buoyant-barnacle-2.Rproj +++ /dev/null @@ -1,13 +0,0 @@ -Version: 1.0 - -RestoreWorkspace: No -SaveWorkspace: No -AlwaysSaveHistory: Default - -EnableCodeIndexing: Yes -Encoding: UTF-8 - -AutoAppendNewline: Yes -StripTrailingWhitespace: Yes -LineEndingConversion: Posix - diff --git a/episodes/data/502nmos.fits b/data/502nmos.fits similarity index 100% rename from episodes/data/502nmos.fits rename to data/502nmos.fits diff --git a/episodes/data/gapminder_gdp_europe.csv b/data/gapminder_gdp_europe.csv similarity index 100% rename from episodes/data/gapminder_gdp_europe.csv rename to data/gapminder_gdp_europe.csv diff --git a/episodes/data/python-intermediate-data.zip b/data/python-intermediate-data.zip similarity index 100% rename from episodes/data/python-intermediate-data.zip rename to data/python-intermediate-data.zip diff --git a/episodes/data/ro-crate-metadata-1.json b/data/ro-crate-metadata-1.json similarity index 100% rename from episodes/data/ro-crate-metadata-1.json rename to data/ro-crate-metadata-1.json diff --git a/episodes/data/ro-crate-metadata-2.json b/data/ro-crate-metadata-2.json similarity index 100% rename from episodes/data/ro-crate-metadata-2.json rename to data/ro-crate-metadata-2.json diff --git a/episodes/data/ro-crate-metadata-3.json b/data/ro-crate-metadata-3.json similarity index 100% rename from episodes/data/ro-crate-metadata-3.json rename to data/ro-crate-metadata-3.json diff --git a/episodes/data/ro-crate-metadata-4.json b/data/ro-crate-metadata-4.json similarity index 100% rename from episodes/data/ro-crate-metadata-4.json rename to data/ro-crate-metadata-4.json diff --git a/learners/discuss.md b/discuss.md similarity index 100% rename from learners/discuss.md rename to discuss.md diff --git a/episodes/introduction.Rmd b/episodes/introduction.Rmd deleted file mode 100644 index 77edfd7..0000000 --- a/episodes/introduction.Rmd +++ /dev/null @@ -1,111 +0,0 @@ ---- -title: 'introduction' -teaching: 10 -exercises: 2 ---- - -:::::::::::::::::::::::::::::::::::::: questions - -- How do you write a lesson using R Markdown and `{sandpaper}`? - -:::::::::::::::::::::::::::::::::::::::::::::::: - -::::::::::::::::::::::::::::::::::::: objectives - -- Explain how to use markdown with the new lesson template -- Demonstrate how to include pieces of code, figures, and nested challenge blocks - -:::::::::::::::::::::::::::::::::::::::::::::::: - -## Introduction - -This is a lesson created via The Carpentries Workbench. It is written in -[Pandoc-flavored Markdown][pandoc] for static files (with extension `.md`) and -[R Markdown][r-markdown] for dynamic files that can render code into output -(with extension `.Rmd`). Please refer to the [Introduction to The Carpentries -Workbench][carpentries-workbench] for full documentation. - -What you need to know is that there are three sections required for a valid -Carpentries lesson template: - - 1. `questions` are displayed at the beginning of the episode to prime the - learner for the content. - 2. `objectives` are the learning objectives for an episode displayed with - the questions. - 3. `keypoints` are displayed at the end of the episode to reinforce the - objectives. - -:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: instructor - -Inline instructor notes can help inform instructors of timing challenges -associated with the lessons. They appear in the "Instructor View" - -:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: - -::::::::::::::::::::::::::::::::::::: challenge - -## Challenge 1: Can you do it? - -What is the output of this command? - -```r -paste("This", "new", "lesson", "looks", "good") -``` - -:::::::::::::::::::::::: solution - -## Output - -```output -[1] "This new lesson looks good" -``` - -::::::::::::::::::::::::::::::::: - - -## Challenge 2: how do you nest solutions within challenge blocks? - -:::::::::::::::::::::::: solution - -You can add a line with at least three colons and a `solution` tag. - -::::::::::::::::::::::::::::::::: -:::::::::::::::::::::::::::::::::::::::::::::::: - -## Figures - -You can include figures generated from R Markdown: - -```{r pyramid, fig.alt = "pie chart illusion of a pyramid", fig.cap = "Sun arise each and every morning"} -pie( - c(Sky = 78, "Sunny side of pyramid" = 17, "Shady side of pyramid" = 5), - init.angle = 315, - col = c("deepskyblue", "yellow", "yellow3"), - border = FALSE -) -``` -Or you can use pandoc markdown for static figures with the following syntax: - -`![optional caption that appears below the figure](figure url){alt='alt text for -accessibility purposes'}` - -![You belong in The Carpentries!](https://raw.githubusercontent.com/carpentries/logo/master/Badge_Carpentries.svg){alt='Blue Carpentries hex person logo with no text.'} - -## Math - -One of our episodes contains $\LaTeX$ equations when describing how to create -dynamic reports with {knitr}, so we now use mathjax to describe this: - -`$\alpha = \dfrac{1}{(1 - \beta)^2}$` becomes: $\alpha = \dfrac{1}{(1 - \beta)^2}$ - -Cool, right? - -::::::::::::::::::::::::::::::::::::: keypoints - -- Use `.md` files for episodes when you want static content -- Use `.Rmd` files for episodes when you need to generate output -- Run `sandpaper::check_lesson()` to identify any issues with your lesson -- Run `sandpaper::build_lesson()` to preview your lesson locally - -:::::::::::::::::::::::::::::::::::::::::::::::: - diff --git a/episodes/fig/albania_austria_belgium_bar_chart.png b/fig/albania_austria_belgium_bar_chart.png similarity index 100% rename from episodes/fig/albania_austria_belgium_bar_chart.png rename to fig/albania_austria_belgium_bar_chart.png diff --git a/episodes/fig/gauss_curve.png b/fig/gauss_curve.png similarity index 100% rename from episodes/fig/gauss_curve.png rename to fig/gauss_curve.png diff --git a/episodes/fig/gauss_curve_noisy.png b/fig/gauss_curve_noisy.png similarity index 100% rename from episodes/fig/gauss_curve_noisy.png rename to fig/gauss_curve_noisy.png diff --git a/episodes/fig/gauss_curve_signal.png b/fig/gauss_curve_signal.png similarity index 100% rename from episodes/fig/gauss_curve_signal.png rename to fig/gauss_curve_signal.png diff --git a/episodes/fig/gauss_function.png b/fig/gauss_function.png similarity index 100% rename from episodes/fig/gauss_function.png rename to fig/gauss_function.png diff --git a/episodes/fig/light_speed_eqn.png b/fig/light_speed_eqn.png similarity index 100% rename from episodes/fig/light_speed_eqn.png rename to fig/light_speed_eqn.png diff --git a/episodes/fig/nebulae_25_0mask.png b/fig/nebulae_25_0mask.png similarity index 100% rename from episodes/fig/nebulae_25_0mask.png rename to fig/nebulae_25_0mask.png diff --git a/episodes/fig/nebulae_25limit.png b/fig/nebulae_25limit.png similarity index 100% rename from episodes/fig/nebulae_25limit.png rename to fig/nebulae_25limit.png diff --git a/episodes/fig/nebulae_25mask.png b/fig/nebulae_25mask.png similarity index 100% rename from episodes/fig/nebulae_25mask.png rename to fig/nebulae_25mask.png diff --git a/episodes/fig/nebulae_raw.png b/fig/nebulae_raw.png similarity index 100% rename from episodes/fig/nebulae_raw.png rename to fig/nebulae_raw.png diff --git a/episodes/fig/photon_count_a.png b/fig/photon_count_a.png similarity index 100% rename from episodes/fig/photon_count_a.png rename to fig/photon_count_a.png diff --git a/episodes/fig/photon_count_b.png b/fig/photon_count_b.png similarity index 100% rename from episodes/fig/photon_count_b.png rename to fig/photon_count_b.png diff --git a/episodes/fig/photon_count_c.png b/fig/photon_count_c.png similarity index 100% rename from episodes/fig/photon_count_c.png rename to fig/photon_count_c.png diff --git a/episodes/fig/sin_curve_deg.png b/fig/sin_curve_deg.png similarity index 100% rename from episodes/fig/sin_curve_deg.png rename to fig/sin_curve_deg.png diff --git a/episodes/fig/sin_curve_rad.png b/fig/sin_curve_rad.png similarity index 100% rename from episodes/fig/sin_curve_rad.png rename to fig/sin_curve_rad.png diff --git a/episodes/fig/sweden-pandas-fig1.png b/fig/sweden-pandas-fig1.png similarity index 100% rename from episodes/fig/sweden-pandas-fig1.png rename to fig/sweden-pandas-fig1.png diff --git a/instructors/instructor-notes.md b/instructor-notes.md similarity index 100% rename from instructors/instructor-notes.md rename to instructor-notes.md diff --git a/profiles/learner-profiles.md b/learner-profiles.md similarity index 100% rename from profiles/learner-profiles.md rename to learner-profiles.md diff --git a/md5sum.txt b/md5sum.txt new file mode 100644 index 0000000..da3ee65 --- /dev/null +++ b/md5sum.txt @@ -0,0 +1,19 @@ +"file" "checksum" "built" "date" +"CODE_OF_CONDUCT.md" "c93c83c630db2fe2462240bf72552548" "site/built/CODE_OF_CONDUCT.md" "2025-04-15" +"LICENSE.md" "16e8eaad880865bc4a41811b3e8fa945" "site/built/LICENSE.md" "2025-04-15" +"config.yaml" "5d0ce56788d2bbd72d9428af554e1af3" "site/built/config.yaml" "2026-04-17" +"index.md" "b92970dbb54d63d6543a4c28e4df0a58" "site/built/index.md" "2025-04-15" +"links.md" "8184cf4149eafbf03ce8da8ff0778c14" "site/built/links.md" "2025-04-15" +"episodes/01-introduction.md" "00febcd4b0446ca443b0c1eaf3467841" "site/built/01-introduction.md" "2026-04-17" +"episodes/02-dictionaries.md" "83b33b6c48be79687521d24eae56c974" "site/built/02-dictionaries.md" "2026-04-16" +"episodes/03-numpy_essential.md" "72a9aa41a65900b4a87744e8f946fa00" "site/built/03-numpy_essential.md" "2026-04-16" +"episodes/04-software_package_management.md" "62db2ba2a4291e16d2bdd07b77bfc961" "site/built/04-software_package_management.md" "2025-04-15" +"episodes/05-defensive_programming.md" "08dac8f8cc0e094ee684903fef65a5d5" "site/built/05-defensive_programming.md" "2026-04-16" +"episodes/06-units_and_quantities.md" "7e259f66d6f8889505c252a04082481f" "site/built/06-units_and_quantities.md" "2026-04-13" +"episodes/07-pandas_essential.md" "53da61ecedb6dcb8735ab4cc6fbe0f99" "site/built/07-pandas_essential.md" "2026-04-13" +"instructors/instructor-notes.md" "a59fd3b94c07c3fe3218c054a0f03277" "site/built/instructor-notes.md" "2025-04-15" +"learners/discuss.md" "2758e2e5abd231d82d25c6453d8abbc6" "site/built/discuss.md" "2025-04-15" +"learners/reference.md" "28853696c21dd22dfb883e9c241e95fb" "site/built/reference.md" "2025-04-15" +"learners/setup.md" "57f8b387989c25897284cf5cf9d909c1" "site/built/setup.md" "2026-04-16" +"profiles/learner-profiles.md" "60b93493cf1da06dfd63255d73854461" "site/built/learner-profiles.md" "2025-04-15" +"renv/profiles/lesson-requirements/renv.lock" "27e4855ba3f7161ae21bda4f9d207141" "site/built/renv.lock" "2026-04-13" diff --git a/learners/reference.md b/reference.md similarity index 100% rename from learners/reference.md rename to reference.md diff --git a/renv/profiles/lesson-requirements/renv.lock b/renv.lock similarity index 83% rename from renv/profiles/lesson-requirements/renv.lock rename to renv.lock index fbd452e..f7b313d 100644 --- a/renv/profiles/lesson-requirements/renv.lock +++ b/renv.lock @@ -1,6 +1,6 @@ { "R": { - "Version": "4.4.3", + "Version": "4.5.3", "Repositories": [ { "Name": "carpentries", @@ -526,7 +526,7 @@ "Source": "Repository", "Type": "Package", "Title": "A General-Purpose Package for Dynamic Report Generation in R", - "Authors@R": "c( person(\"Yihui\", \"Xie\", role = c(\"aut\", \"cre\"), email = \"xie@yihui.name\", comment = c(ORCID = \"0000-0003-0645-5666\")), person(\"Abhraneel\", \"Sarma\", role = \"ctb\"), person(\"Adam\", \"Vogt\", role = \"ctb\"), person(\"Alastair\", \"Andrew\", role = \"ctb\"), person(\"Alex\", \"Zvoleff\", role = \"ctb\"), person(\"Amar\", \"Al-Zubaidi\", role = \"ctb\"), person(\"Andre\", \"Simon\", role = \"ctb\", comment = \"the CSS files under inst/themes/ were derived from the Highlight package http://www.andre-simon.de\"), person(\"Aron\", \"Atkins\", role = \"ctb\"), person(\"Aaron\", \"Wolen\", role = \"ctb\"), person(\"Ashley\", \"Manton\", role = \"ctb\"), person(\"Atsushi\", \"Yasumoto\", role = \"ctb\", comment = c(ORCID = \"0000-0002-8335-495X\")), person(\"Ben\", \"Baumer\", role = \"ctb\"), person(\"Brian\", \"Diggs\", role = \"ctb\"), person(\"Brian\", \"Zhang\", role = \"ctb\"), person(\"Bulat\", \"Yapparov\", role = \"ctb\"), person(\"Cassio\", \"Pereira\", role = \"ctb\"), person(\"Christophe\", \"Dervieux\", role = \"ctb\"), person(\"David\", \"Hall\", role = \"ctb\"), person(\"David\", \"Hugh-Jones\", role = \"ctb\"), person(\"David\", \"Robinson\", role = \"ctb\"), person(\"Doug\", \"Hemken\", role = \"ctb\"), person(\"Duncan\", \"Murdoch\", role = \"ctb\"), person(\"Elio\", \"Campitelli\", role = \"ctb\"), person(\"Ellis\", \"Hughes\", role = \"ctb\"), person(\"Emily\", \"Riederer\", role = \"ctb\"), person(\"Fabian\", \"Hirschmann\", role = \"ctb\"), person(\"Fitch\", \"Simeon\", role = \"ctb\"), person(\"Forest\", \"Fang\", role = \"ctb\"), person(c(\"Frank\", \"E\", \"Harrell\", \"Jr\"), role = \"ctb\", comment = \"the Sweavel package at inst/misc/Sweavel.sty\"), person(\"Garrick\", \"Aden-Buie\", role = \"ctb\"), person(\"Gregoire\", \"Detrez\", role = \"ctb\"), person(\"Hadley\", \"Wickham\", role = \"ctb\"), person(\"Hao\", \"Zhu\", role = \"ctb\"), person(\"Heewon\", \"Jeon\", role = \"ctb\"), person(\"Henrik\", \"Bengtsson\", role = \"ctb\"), person(\"Hiroaki\", \"Yutani\", role = \"ctb\"), person(\"Ian\", \"Lyttle\", role = \"ctb\"), person(\"Hodges\", \"Daniel\", role = \"ctb\"), person(\"Jacob\", \"Bien\", role = \"ctb\"), person(\"Jake\", \"Burkhead\", role = \"ctb\"), person(\"James\", \"Manton\", role = \"ctb\"), person(\"Jared\", \"Lander\", role = \"ctb\"), person(\"Jason\", \"Punyon\", role = \"ctb\"), person(\"Javier\", \"Luraschi\", role = \"ctb\"), person(\"Jeff\", \"Arnold\", role = \"ctb\"), person(\"Jenny\", \"Bryan\", role = \"ctb\"), person(\"Jeremy\", \"Ashkenas\", role = c(\"ctb\", \"cph\"), comment = \"the CSS file at inst/misc/docco-classic.css\"), person(\"Jeremy\", \"Stephens\", role = \"ctb\"), person(\"Jim\", \"Hester\", role = \"ctb\"), person(\"Joe\", \"Cheng\", role = \"ctb\"), person(\"Johannes\", \"Ranke\", role = \"ctb\"), person(\"John\", \"Honaker\", role = \"ctb\"), person(\"John\", \"Muschelli\", role = \"ctb\"), person(\"Jonathan\", \"Keane\", role = \"ctb\"), person(\"JJ\", \"Allaire\", role = \"ctb\"), person(\"Johan\", \"Toloe\", role = \"ctb\"), person(\"Jonathan\", \"Sidi\", role = \"ctb\"), person(\"Joseph\", \"Larmarange\", role = \"ctb\"), person(\"Julien\", \"Barnier\", role = \"ctb\"), person(\"Kaiyin\", \"Zhong\", role = \"ctb\"), person(\"Kamil\", \"Slowikowski\", role = \"ctb\"), person(\"Karl\", \"Forner\", role = \"ctb\"), person(c(\"Kevin\", \"K.\"), \"Smith\", role = \"ctb\"), person(\"Kirill\", \"Mueller\", role = \"ctb\"), person(\"Kohske\", \"Takahashi\", role = \"ctb\"), person(\"Lorenz\", \"Walthert\", role = \"ctb\"), person(\"Lucas\", \"Gallindo\", role = \"ctb\"), person(\"Marius\", \"Hofert\", role = \"ctb\"), person(\"Martin\", \"Modrák\", role = \"ctb\"), person(\"Michael\", \"Chirico\", role = \"ctb\"), person(\"Michael\", \"Friendly\", role = \"ctb\"), person(\"Michal\", \"Bojanowski\", role = \"ctb\"), person(\"Michel\", \"Kuhlmann\", role = \"ctb\"), person(\"Miller\", \"Patrick\", role = \"ctb\"), person(\"Nacho\", \"Caballero\", role = \"ctb\"), person(\"Nick\", \"Salkowski\", role = \"ctb\"), person(\"Niels Richard\", \"Hansen\", role = \"ctb\"), person(\"Noam\", \"Ross\", role = \"ctb\"), person(\"Obada\", \"Mahdi\", role = \"ctb\"), person(\"Pavel N.\", \"Krivitsky\", role = \"ctb\", comment=c(ORCID = \"0000-0002-9101-3362\")), person(\"Pedro\", \"Faria\", role = \"ctb\"), person(\"Qiang\", \"Li\", role = \"ctb\"), person(\"Ramnath\", \"Vaidyanathan\", role = \"ctb\"), person(\"Richard\", \"Cotton\", role = \"ctb\"), person(\"Robert\", \"Krzyzanowski\", role = \"ctb\"), person(\"Rodrigo\", \"Copetti\", role = \"ctb\"), person(\"Romain\", \"Francois\", role = \"ctb\"), person(\"Ruaridh\", \"Williamson\", role = \"ctb\"), person(\"Sagiru\", \"Mati\", role = \"ctb\", comment = c(ORCID = \"0000-0003-1413-3974\")), person(\"Scott\", \"Kostyshak\", role = \"ctb\"), person(\"Sebastian\", \"Meyer\", role = \"ctb\"), person(\"Sietse\", \"Brouwer\", role = \"ctb\"), person(c(\"Simon\", \"de\"), \"Bernard\", role = \"ctb\"), person(\"Sylvain\", \"Rousseau\", role = \"ctb\"), person(\"Taiyun\", \"Wei\", role = \"ctb\"), person(\"Thibaut\", \"Assus\", role = \"ctb\"), person(\"Thibaut\", \"Lamadon\", role = \"ctb\"), person(\"Thomas\", \"Leeper\", role = \"ctb\"), person(\"Tim\", \"Mastny\", role = \"ctb\"), person(\"Tom\", \"Torsney-Weir\", role = \"ctb\"), person(\"Trevor\", \"Davis\", role = \"ctb\"), person(\"Viktoras\", \"Veitas\", role = \"ctb\"), person(\"Weicheng\", \"Zhu\", role = \"ctb\"), person(\"Wush\", \"Wu\", role = \"ctb\"), person(\"Zachary\", \"Foster\", role = \"ctb\"), person(\"Zhian N.\", \"Kamvar\", role = \"ctb\", comment = c(ORCID = \"0000-0003-1458-7108\")), person(given = \"Posit Software, PBC\", role = c(\"cph\", \"fnd\")) )", + "Authors@R": "c( person(\"Yihui\", \"Xie\", role = c(\"aut\", \"cre\"), email = \"xie@yihui.name\", comment = c(ORCID = \"0000-0003-0645-5666\", URL = \"https://yihui.org\")), person(\"Abhraneel\", \"Sarma\", role = \"ctb\"), person(\"Adam\", \"Vogt\", role = \"ctb\"), person(\"Alastair\", \"Andrew\", role = \"ctb\"), person(\"Alex\", \"Zvoleff\", role = \"ctb\"), person(\"Amar\", \"Al-Zubaidi\", role = \"ctb\"), person(\"Andre\", \"Simon\", role = \"ctb\", comment = \"the CSS files under inst/themes/ were derived from the Highlight package http://www.andre-simon.de\"), person(\"Aron\", \"Atkins\", role = \"ctb\"), person(\"Aaron\", \"Wolen\", role = \"ctb\"), person(\"Ashley\", \"Manton\", role = \"ctb\"), person(\"Atsushi\", \"Yasumoto\", role = \"ctb\", comment = c(ORCID = \"0000-0002-8335-495X\")), person(\"Ben\", \"Baumer\", role = \"ctb\"), person(\"Brian\", \"Diggs\", role = \"ctb\"), person(\"Brian\", \"Zhang\", role = \"ctb\"), person(\"Bulat\", \"Yapparov\", role = \"ctb\"), person(\"Cassio\", \"Pereira\", role = \"ctb\"), person(\"Christophe\", \"Dervieux\", role = \"ctb\"), person(\"David\", \"Hall\", role = \"ctb\"), person(\"David\", \"Hugh-Jones\", role = \"ctb\"), person(\"David\", \"Robinson\", role = \"ctb\"), person(\"Doug\", \"Hemken\", role = \"ctb\"), person(\"Duncan\", \"Murdoch\", role = \"ctb\"), person(\"Elio\", \"Campitelli\", role = \"ctb\"), person(\"Ellis\", \"Hughes\", role = \"ctb\"), person(\"Emily\", \"Riederer\", role = \"ctb\"), person(\"Fabian\", \"Hirschmann\", role = \"ctb\"), person(\"Fitch\", \"Simeon\", role = \"ctb\"), person(\"Forest\", \"Fang\", role = \"ctb\"), person(c(\"Frank\", \"E\", \"Harrell\", \"Jr\"), role = \"ctb\", comment = \"the Sweavel package at inst/misc/Sweavel.sty\"), person(\"Garrick\", \"Aden-Buie\", role = \"ctb\"), person(\"Gregoire\", \"Detrez\", role = \"ctb\"), person(\"Hadley\", \"Wickham\", role = \"ctb\"), person(\"Hao\", \"Zhu\", role = \"ctb\"), person(\"Heewon\", \"Jeon\", role = \"ctb\"), person(\"Henrik\", \"Bengtsson\", role = \"ctb\"), person(\"Hiroaki\", \"Yutani\", role = \"ctb\"), person(\"Ian\", \"Lyttle\", role = \"ctb\"), person(\"Hodges\", \"Daniel\", role = \"ctb\"), person(\"Jacob\", \"Bien\", role = \"ctb\"), person(\"Jake\", \"Burkhead\", role = \"ctb\"), person(\"James\", \"Manton\", role = \"ctb\"), person(\"Jared\", \"Lander\", role = \"ctb\"), person(\"Jason\", \"Punyon\", role = \"ctb\"), person(\"Javier\", \"Luraschi\", role = \"ctb\"), person(\"Jeff\", \"Arnold\", role = \"ctb\"), person(\"Jenny\", \"Bryan\", role = \"ctb\"), person(\"Jeremy\", \"Ashkenas\", role = c(\"ctb\", \"cph\"), comment = \"the CSS file at inst/misc/docco-classic.css\"), person(\"Jeremy\", \"Stephens\", role = \"ctb\"), person(\"Jim\", \"Hester\", role = \"ctb\"), person(\"Joe\", \"Cheng\", role = \"ctb\"), person(\"Johannes\", \"Ranke\", role = \"ctb\"), person(\"John\", \"Honaker\", role = \"ctb\"), person(\"John\", \"Muschelli\", role = \"ctb\"), person(\"Jonathan\", \"Keane\", role = \"ctb\"), person(\"JJ\", \"Allaire\", role = \"ctb\"), person(\"Johan\", \"Toloe\", role = \"ctb\"), person(\"Jonathan\", \"Sidi\", role = \"ctb\"), person(\"Joseph\", \"Larmarange\", role = \"ctb\"), person(\"Julien\", \"Barnier\", role = \"ctb\"), person(\"Kaiyin\", \"Zhong\", role = \"ctb\"), person(\"Kamil\", \"Slowikowski\", role = \"ctb\"), person(\"Karl\", \"Forner\", role = \"ctb\"), person(c(\"Kevin\", \"K.\"), \"Smith\", role = \"ctb\"), person(\"Kirill\", \"Mueller\", role = \"ctb\"), person(\"Kohske\", \"Takahashi\", role = \"ctb\"), person(\"Lorenz\", \"Walthert\", role = \"ctb\"), person(\"Lucas\", \"Gallindo\", role = \"ctb\"), person(\"Marius\", \"Hofert\", role = \"ctb\"), person(\"Martin\", \"Modrák\", role = \"ctb\"), person(\"Michael\", \"Chirico\", role = \"ctb\"), person(\"Michael\", \"Friendly\", role = \"ctb\"), person(\"Michal\", \"Bojanowski\", role = \"ctb\"), person(\"Michel\", \"Kuhlmann\", role = \"ctb\"), person(\"Miller\", \"Patrick\", role = \"ctb\"), person(\"Nacho\", \"Caballero\", role = \"ctb\"), person(\"Nick\", \"Salkowski\", role = \"ctb\"), person(\"Niels Richard\", \"Hansen\", role = \"ctb\"), person(\"Noam\", \"Ross\", role = \"ctb\"), person(\"Obada\", \"Mahdi\", role = \"ctb\"), person(\"Pavel N.\", \"Krivitsky\", role = \"ctb\", comment=c(ORCID = \"0000-0002-9101-3362\")), person(\"Pedro\", \"Faria\", role = \"ctb\"), person(\"Qiang\", \"Li\", role = \"ctb\"), person(\"Ramnath\", \"Vaidyanathan\", role = \"ctb\"), person(\"Richard\", \"Cotton\", role = \"ctb\"), person(\"Robert\", \"Krzyzanowski\", role = \"ctb\"), person(\"Rodrigo\", \"Copetti\", role = \"ctb\"), person(\"Romain\", \"Francois\", role = \"ctb\"), person(\"Ruaridh\", \"Williamson\", role = \"ctb\"), person(\"Sagiru\", \"Mati\", role = \"ctb\", comment = c(ORCID = \"0000-0003-1413-3974\")), person(\"Scott\", \"Kostyshak\", role = \"ctb\"), person(\"Sebastian\", \"Meyer\", role = \"ctb\"), person(\"Sietse\", \"Brouwer\", role = \"ctb\"), person(c(\"Simon\", \"de\"), \"Bernard\", role = \"ctb\"), person(\"Sylvain\", \"Rousseau\", role = \"ctb\"), person(\"Taiyun\", \"Wei\", role = \"ctb\"), person(\"Thibaut\", \"Assus\", role = \"ctb\"), person(\"Thibaut\", \"Lamadon\", role = \"ctb\"), person(\"Thomas\", \"Leeper\", role = \"ctb\"), person(\"Tim\", \"Mastny\", role = \"ctb\"), person(\"Tom\", \"Torsney-Weir\", role = \"ctb\"), person(\"Trevor\", \"Davis\", role = \"ctb\"), person(\"Viktoras\", \"Veitas\", role = \"ctb\"), person(\"Weicheng\", \"Zhu\", role = \"ctb\"), person(\"Wush\", \"Wu\", role = \"ctb\"), person(\"Zachary\", \"Foster\", role = \"ctb\"), person(\"Zhian N.\", \"Kamvar\", role = \"ctb\", comment = c(ORCID = \"0000-0003-1458-7108\")), person(given = \"Posit Software, PBC\", role = c(\"cph\", \"fnd\")) )", "Description": "Provides a general-purpose tool for dynamic report generation in R using Literate Programming techniques.", "Depends": [ "R (>= 3.6.0)" @@ -536,12 +536,11 @@ "highr (>= 0.11)", "methods", "tools", - "xfun (>= 0.48)", + "xfun (>= 0.52)", "yaml (>= 2.1.19)" ], "Suggests": [ "bslib", - "codetools", "DBI (>= 0.4-1)", "digest", "formatR", @@ -553,6 +552,8 @@ "magick", "litedown", "markdown (>= 1.3)", + "otel", + "otelsdk", "png", "ragg", "reticulate (>= 1.4)", @@ -566,7 +567,7 @@ "testit", "tibble", "tikzDevice (>= 0.10)", - "tinytex (>= 0.46)", + "tinytex (>= 0.56)", "webshot", "rstudioapi", "svglite" @@ -577,10 +578,10 @@ "Encoding": "UTF-8", "VignetteBuilder": "litedown, knitr", "SystemRequirements": "Package vignettes based on R Markdown v2 or reStructuredText require Pandoc (http://pandoc.org). The function rst2pdf() requires rst2pdf (https://github.com/rst2pdf/rst2pdf).", - "Collate": "'block.R' 'cache.R' 'utils.R' 'citation.R' 'hooks-html.R' 'plot.R' 'defaults.R' 'concordance.R' 'engine.R' 'highlight.R' 'themes.R' 'header.R' 'hooks-asciidoc.R' 'hooks-chunk.R' 'hooks-extra.R' 'hooks-latex.R' 'hooks-md.R' 'hooks-rst.R' 'hooks-textile.R' 'hooks.R' 'output.R' 'package.R' 'pandoc.R' 'params.R' 'parser.R' 'pattern.R' 'rocco.R' 'spin.R' 'table.R' 'template.R' 'utils-conversion.R' 'utils-rd2html.R' 'utils-string.R' 'utils-sweave.R' 'utils-upload.R' 'utils-vignettes.R' 'zzz.R'", - "RoxygenNote": "7.3.2", + "Collate": "'block.R' 'cache.R' 'citation.R' 'hooks-html.R' 'plot.R' 'utils.R' 'defaults.R' 'concordance.R' 'engine.R' 'highlight.R' 'themes.R' 'header.R' 'hooks-asciidoc.R' 'hooks-chunk.R' 'hooks-extra.R' 'hooks-latex.R' 'hooks-md.R' 'hooks-rst.R' 'hooks-textile.R' 'hooks.R' 'otel.R' 'output.R' 'package.R' 'pandoc.R' 'params.R' 'parser.R' 'pattern.R' 'rocco.R' 'spin.R' 'table.R' 'template.R' 'utils-conversion.R' 'utils-rd2html.R' 'utils-string.R' 'utils-sweave.R' 'utils-upload.R' 'utils-vignettes.R' 'zzz.R'", + "RoxygenNote": "7.3.3", "NeedsCompilation": "no", - "Author": "Yihui Xie [aut, cre] (), Abhraneel Sarma [ctb], Adam Vogt [ctb], Alastair Andrew [ctb], Alex Zvoleff [ctb], Amar Al-Zubaidi [ctb], Andre Simon [ctb] (the CSS files under inst/themes/ were derived from the Highlight package http://www.andre-simon.de), Aron Atkins [ctb], Aaron Wolen [ctb], Ashley Manton [ctb], Atsushi Yasumoto [ctb] (), Ben Baumer [ctb], Brian Diggs [ctb], Brian Zhang [ctb], Bulat Yapparov [ctb], Cassio Pereira [ctb], Christophe Dervieux [ctb], David Hall [ctb], David Hugh-Jones [ctb], David Robinson [ctb], Doug Hemken [ctb], Duncan Murdoch [ctb], Elio Campitelli [ctb], Ellis Hughes [ctb], Emily Riederer [ctb], Fabian Hirschmann [ctb], Fitch Simeon [ctb], Forest Fang [ctb], Frank E Harrell Jr [ctb] (the Sweavel package at inst/misc/Sweavel.sty), Garrick Aden-Buie [ctb], Gregoire Detrez [ctb], Hadley Wickham [ctb], Hao Zhu [ctb], Heewon Jeon [ctb], Henrik Bengtsson [ctb], Hiroaki Yutani [ctb], Ian Lyttle [ctb], Hodges Daniel [ctb], Jacob Bien [ctb], Jake Burkhead [ctb], James Manton [ctb], Jared Lander [ctb], Jason Punyon [ctb], Javier Luraschi [ctb], Jeff Arnold [ctb], Jenny Bryan [ctb], Jeremy Ashkenas [ctb, cph] (the CSS file at inst/misc/docco-classic.css), Jeremy Stephens [ctb], Jim Hester [ctb], Joe Cheng [ctb], Johannes Ranke [ctb], John Honaker [ctb], John Muschelli [ctb], Jonathan Keane [ctb], JJ Allaire [ctb], Johan Toloe [ctb], Jonathan Sidi [ctb], Joseph Larmarange [ctb], Julien Barnier [ctb], Kaiyin Zhong [ctb], Kamil Slowikowski [ctb], Karl Forner [ctb], Kevin K. Smith [ctb], Kirill Mueller [ctb], Kohske Takahashi [ctb], Lorenz Walthert [ctb], Lucas Gallindo [ctb], Marius Hofert [ctb], Martin Modrák [ctb], Michael Chirico [ctb], Michael Friendly [ctb], Michal Bojanowski [ctb], Michel Kuhlmann [ctb], Miller Patrick [ctb], Nacho Caballero [ctb], Nick Salkowski [ctb], Niels Richard Hansen [ctb], Noam Ross [ctb], Obada Mahdi [ctb], Pavel N. Krivitsky [ctb] (), Pedro Faria [ctb], Qiang Li [ctb], Ramnath Vaidyanathan [ctb], Richard Cotton [ctb], Robert Krzyzanowski [ctb], Rodrigo Copetti [ctb], Romain Francois [ctb], Ruaridh Williamson [ctb], Sagiru Mati [ctb] (), Scott Kostyshak [ctb], Sebastian Meyer [ctb], Sietse Brouwer [ctb], Simon de Bernard [ctb], Sylvain Rousseau [ctb], Taiyun Wei [ctb], Thibaut Assus [ctb], Thibaut Lamadon [ctb], Thomas Leeper [ctb], Tim Mastny [ctb], Tom Torsney-Weir [ctb], Trevor Davis [ctb], Viktoras Veitas [ctb], Weicheng Zhu [ctb], Wush Wu [ctb], Zachary Foster [ctb], Zhian N. Kamvar [ctb] (), Posit Software, PBC [cph, fnd]", + "Author": "Yihui Xie [aut, cre] (ORCID: , URL: https://yihui.org), Abhraneel Sarma [ctb], Adam Vogt [ctb], Alastair Andrew [ctb], Alex Zvoleff [ctb], Amar Al-Zubaidi [ctb], Andre Simon [ctb] (the CSS files under inst/themes/ were derived from the Highlight package http://www.andre-simon.de), Aron Atkins [ctb], Aaron Wolen [ctb], Ashley Manton [ctb], Atsushi Yasumoto [ctb] (ORCID: ), Ben Baumer [ctb], Brian Diggs [ctb], Brian Zhang [ctb], Bulat Yapparov [ctb], Cassio Pereira [ctb], Christophe Dervieux [ctb], David Hall [ctb], David Hugh-Jones [ctb], David Robinson [ctb], Doug Hemken [ctb], Duncan Murdoch [ctb], Elio Campitelli [ctb], Ellis Hughes [ctb], Emily Riederer [ctb], Fabian Hirschmann [ctb], Fitch Simeon [ctb], Forest Fang [ctb], Frank E Harrell Jr [ctb] (the Sweavel package at inst/misc/Sweavel.sty), Garrick Aden-Buie [ctb], Gregoire Detrez [ctb], Hadley Wickham [ctb], Hao Zhu [ctb], Heewon Jeon [ctb], Henrik Bengtsson [ctb], Hiroaki Yutani [ctb], Ian Lyttle [ctb], Hodges Daniel [ctb], Jacob Bien [ctb], Jake Burkhead [ctb], James Manton [ctb], Jared Lander [ctb], Jason Punyon [ctb], Javier Luraschi [ctb], Jeff Arnold [ctb], Jenny Bryan [ctb], Jeremy Ashkenas [ctb, cph] (the CSS file at inst/misc/docco-classic.css), Jeremy Stephens [ctb], Jim Hester [ctb], Joe Cheng [ctb], Johannes Ranke [ctb], John Honaker [ctb], John Muschelli [ctb], Jonathan Keane [ctb], JJ Allaire [ctb], Johan Toloe [ctb], Jonathan Sidi [ctb], Joseph Larmarange [ctb], Julien Barnier [ctb], Kaiyin Zhong [ctb], Kamil Slowikowski [ctb], Karl Forner [ctb], Kevin K. Smith [ctb], Kirill Mueller [ctb], Kohske Takahashi [ctb], Lorenz Walthert [ctb], Lucas Gallindo [ctb], Marius Hofert [ctb], Martin Modrák [ctb], Michael Chirico [ctb], Michael Friendly [ctb], Michal Bojanowski [ctb], Michel Kuhlmann [ctb], Miller Patrick [ctb], Nacho Caballero [ctb], Nick Salkowski [ctb], Niels Richard Hansen [ctb], Noam Ross [ctb], Obada Mahdi [ctb], Pavel N. Krivitsky [ctb] (ORCID: ), Pedro Faria [ctb], Qiang Li [ctb], Ramnath Vaidyanathan [ctb], Richard Cotton [ctb], Robert Krzyzanowski [ctb], Rodrigo Copetti [ctb], Romain Francois [ctb], Ruaridh Williamson [ctb], Sagiru Mati [ctb] (ORCID: ), Scott Kostyshak [ctb], Sebastian Meyer [ctb], Sietse Brouwer [ctb], Simon de Bernard [ctb], Sylvain Rousseau [ctb], Taiyun Wei [ctb], Thibaut Assus [ctb], Thibaut Lamadon [ctb], Thomas Leeper [ctb], Tim Mastny [ctb], Tom Torsney-Weir [ctb], Trevor Davis [ctb], Viktoras Veitas [ctb], Weicheng Zhu [ctb], Wush Wu [ctb], Zachary Foster [ctb], Zhian N. Kamvar [ctb] (ORCID: ), Posit Software, PBC [cph, fnd]", "Maintainer": "Yihui Xie ", "Repository": "CRAN" }, @@ -855,10 +856,10 @@ "Config/Needs/website": "rstudio/quillt, pkgdown", "Config/testthat/edition": "3", "Encoding": "UTF-8", - "RoxygenNote": "7.3.2", + "RoxygenNote": "7.3.3", "SystemRequirements": "pandoc (>= 1.14) - http://pandoc.org", "NeedsCompilation": "no", - "Author": "JJ Allaire [aut], Yihui Xie [aut, cre] (), Christophe Dervieux [aut] (), Jonathan McPherson [aut], Javier Luraschi [aut], Kevin Ushey [aut], Aron Atkins [aut], Hadley Wickham [aut], Joe Cheng [aut], Winston Chang [aut], Richard Iannone [aut] (), Andrew Dunning [ctb] (), Atsushi Yasumoto [ctb, cph] (, Number sections Lua filter), Barret Schloerke [ctb], Carson Sievert [ctb] (), Devon Ryan [ctb] (), Frederik Aust [ctb] (), Jeff Allen [ctb], JooYoung Seo [ctb] (), Malcolm Barrett [ctb], Rob Hyndman [ctb], Romain Lesur [ctb], Roy Storey [ctb], Ruben Arslan [ctb], Sergio Oller [ctb], Posit Software, PBC [cph, fnd], jQuery UI contributors [ctb, cph] (jQuery UI library; authors listed in inst/rmd/h/jqueryui/AUTHORS.txt), Mark Otto [ctb] (Bootstrap library), Jacob Thornton [ctb] (Bootstrap library), Bootstrap contributors [ctb] (Bootstrap library), Twitter, Inc [cph] (Bootstrap library), Alexander Farkas [ctb, cph] (html5shiv library), Scott Jehl [ctb, cph] (Respond.js library), Ivan Sagalaev [ctb, cph] (highlight.js library), Greg Franko [ctb, cph] (tocify library), John MacFarlane [ctb, cph] (Pandoc templates), Google, Inc. [ctb, cph] (ioslides library), Dave Raggett [ctb] (slidy library), W3C [cph] (slidy library), Dave Gandy [ctb, cph] (Font-Awesome), Ben Sperry [ctb] (Ionicons), Drifty [cph] (Ionicons), Aidan Lister [ctb, cph] (jQuery StickyTabs), Benct Philip Jonsson [ctb, cph] (pagebreak Lua filter), Albert Krewinkel [ctb, cph] (pagebreak Lua filter)", + "Author": "JJ Allaire [aut], Yihui Xie [aut, cre] (ORCID: ), Christophe Dervieux [aut] (ORCID: ), Jonathan McPherson [aut], Javier Luraschi [aut], Kevin Ushey [aut], Aron Atkins [aut], Hadley Wickham [aut], Joe Cheng [aut], Winston Chang [aut], Richard Iannone [aut] (ORCID: ), Andrew Dunning [ctb] (ORCID: ), Atsushi Yasumoto [ctb, cph] (ORCID: , cph: Number sections Lua filter), Barret Schloerke [ctb], Carson Sievert [ctb] (ORCID: ), Devon Ryan [ctb] (ORCID: ), Frederik Aust [ctb] (ORCID: ), Jeff Allen [ctb], JooYoung Seo [ctb] (ORCID: ), Malcolm Barrett [ctb], Rob Hyndman [ctb], Romain Lesur [ctb], Roy Storey [ctb], Ruben Arslan [ctb], Sergio Oller [ctb], Posit Software, PBC [cph, fnd], jQuery UI contributors [ctb, cph] (jQuery UI library; authors listed in inst/rmd/h/jqueryui/AUTHORS.txt), Mark Otto [ctb] (Bootstrap library), Jacob Thornton [ctb] (Bootstrap library), Bootstrap contributors [ctb] (Bootstrap library), Twitter, Inc [cph] (Bootstrap library), Alexander Farkas [ctb, cph] (html5shiv library), Scott Jehl [ctb, cph] (Respond.js library), Ivan Sagalaev [ctb, cph] (highlight.js library), Greg Franko [ctb, cph] (tocify library), John MacFarlane [ctb, cph] (Pandoc templates), Google, Inc. [ctb, cph] (ioslides library), Dave Raggett [ctb] (slidy library), W3C [cph] (slidy library), Dave Gandy [ctb, cph] (Font-Awesome), Ben Sperry [ctb] (Ionicons), Drifty [cph] (Ionicons), Aidan Lister [ctb, cph] (jQuery StickyTabs), Benct Philip Jonsson [ctb, cph] (pagebreak Lua filter), Albert Krewinkel [ctb, cph] (pagebreak Lua filter)", "Maintainer": "Yihui Xie ", "Repository": "CRAN" }, @@ -947,29 +948,27 @@ "rstudioapi", "tinytex (>= 0.30)", "mime", - "litedown (>= 0.4)", + "litedown (>= 0.6)", "commonmark", - "knitr (>= 1.47)", + "knitr (>= 1.50)", "remotes", "pak", - "rhub", - "renv", "curl", "xml2", "jsonlite", "magick", "yaml", - "qs", - "rmarkdown" + "data.table", + "qs2" ], "License": "MIT + file LICENSE", "URL": "https://github.com/yihui/xfun", "BugReports": "https://github.com/yihui/xfun/issues", "Encoding": "UTF-8", - "RoxygenNote": "7.3.2", + "RoxygenNote": "7.3.3", "VignetteBuilder": "litedown", "NeedsCompilation": "yes", - "Author": "Yihui Xie [aut, cre, cph] (, https://yihui.org), Wush Wu [ctb], Daijiang Li [ctb], Xianying Tan [ctb], Salim Brüggemann [ctb] (), Christophe Dervieux [ctb]", + "Author": "Yihui Xie [aut, cre, cph] (ORCID: , URL: https://yihui.org), Wush Wu [ctb], Daijiang Li [ctb], Xianying Tan [ctb], Salim Brüggemann [ctb] (ORCID: ), Christophe Dervieux [ctb]", "Maintainer": "Yihui Xie ", "Repository": "CRAN" }, diff --git a/renv/activate.R b/renv/activate.R deleted file mode 100644 index c9f5942..0000000 --- a/renv/activate.R +++ /dev/null @@ -1,1313 +0,0 @@ - -local({ - - # the requested version of renv - version <- "1.1.2" - attr(version, "sha") <- NULL - - # the project directory - project <- Sys.getenv("RENV_PROJECT") - if (!nzchar(project)) - project <- getwd() - - # use start-up diagnostics if enabled - diagnostics <- Sys.getenv("RENV_STARTUP_DIAGNOSTICS", unset = "FALSE") - if (diagnostics) { - start <- Sys.time() - profile <- tempfile("renv-startup-", fileext = ".Rprof") - utils::Rprof(profile) - on.exit({ - utils::Rprof(NULL) - elapsed <- signif(difftime(Sys.time(), start, units = "auto"), digits = 2L) - writeLines(sprintf("- renv took %s to run the autoloader.", format(elapsed))) - writeLines(sprintf("- Profile: %s", profile)) - print(utils::summaryRprof(profile)) - }, add = TRUE) - } - - # figure out whether the autoloader is enabled - enabled <- local({ - - # first, check config option - override <- getOption("renv.config.autoloader.enabled") - if (!is.null(override)) - return(override) - - # if we're being run in a context where R_LIBS is already set, - # don't load -- presumably we're being run as a sub-process and - # the parent process has already set up library paths for us - rcmd <- Sys.getenv("R_CMD", unset = NA) - rlibs <- Sys.getenv("R_LIBS", unset = NA) - if (!is.na(rlibs) && !is.na(rcmd)) - return(FALSE) - - # next, check environment variables - # prefer using the configuration one in the future - envvars <- c( - "RENV_CONFIG_AUTOLOADER_ENABLED", - "RENV_AUTOLOADER_ENABLED", - "RENV_ACTIVATE_PROJECT" - ) - - for (envvar in envvars) { - envval <- Sys.getenv(envvar, unset = NA) - if (!is.na(envval)) - return(tolower(envval) %in% c("true", "t", "1")) - } - - # enable by default - TRUE - - }) - - # bail if we're not enabled - if (!enabled) { - - # if we're not enabled, we might still need to manually load - # the user profile here - profile <- Sys.getenv("R_PROFILE_USER", unset = "~/.Rprofile") - if (file.exists(profile)) { - cfg <- Sys.getenv("RENV_CONFIG_USER_PROFILE", unset = "TRUE") - if (tolower(cfg) %in% c("true", "t", "1")) - sys.source(profile, envir = globalenv()) - } - - return(FALSE) - - } - - # avoid recursion - if (identical(getOption("renv.autoloader.running"), TRUE)) { - warning("ignoring recursive attempt to run renv autoloader") - return(invisible(TRUE)) - } - - # signal that we're loading renv during R startup - options(renv.autoloader.running = TRUE) - on.exit(options(renv.autoloader.running = NULL), add = TRUE) - - # signal that we've consented to use renv - options(renv.consent = TRUE) - - # load the 'utils' package eagerly -- this ensures that renv shims, which - # mask 'utils' packages, will come first on the search path - library(utils, lib.loc = .Library) - - # unload renv if it's already been loaded - if ("renv" %in% loadedNamespaces()) - unloadNamespace("renv") - - # load bootstrap tools - ansify <- function(text) { - if (renv_ansify_enabled()) - renv_ansify_enhanced(text) - else - renv_ansify_default(text) - } - - renv_ansify_enabled <- function() { - - override <- Sys.getenv("RENV_ANSIFY_ENABLED", unset = NA) - if (!is.na(override)) - return(as.logical(override)) - - pane <- Sys.getenv("RSTUDIO_CHILD_PROCESS_PANE", unset = NA) - if (identical(pane, "build")) - return(FALSE) - - testthat <- Sys.getenv("TESTTHAT", unset = "false") - if (tolower(testthat) %in% "true") - return(FALSE) - - iderun <- Sys.getenv("R_CLI_HAS_HYPERLINK_IDE_RUN", unset = "false") - if (tolower(iderun) %in% "false") - return(FALSE) - - TRUE - - } - - renv_ansify_default <- function(text) { - text - } - - renv_ansify_enhanced <- function(text) { - - # R help links - pattern <- "`\\?(renv::(?:[^`])+)`" - replacement <- "`\033]8;;x-r-help:\\1\a?\\1\033]8;;\a`" - text <- gsub(pattern, replacement, text, perl = TRUE) - - # runnable code - pattern <- "`(renv::(?:[^`])+)`" - replacement <- "`\033]8;;x-r-run:\\1\a\\1\033]8;;\a`" - text <- gsub(pattern, replacement, text, perl = TRUE) - - # return ansified text - text - - } - - renv_ansify_init <- function() { - - envir <- renv_envir_self() - if (renv_ansify_enabled()) - assign("ansify", renv_ansify_enhanced, envir = envir) - else - assign("ansify", renv_ansify_default, envir = envir) - - } - - `%||%` <- function(x, y) { - if (is.null(x)) y else x - } - - catf <- function(fmt, ..., appendLF = TRUE) { - - quiet <- getOption("renv.bootstrap.quiet", default = FALSE) - if (quiet) - return(invisible()) - - msg <- sprintf(fmt, ...) - cat(msg, file = stdout(), sep = if (appendLF) "\n" else "") - - invisible(msg) - - } - - header <- function(label, - ..., - prefix = "#", - suffix = "-", - n = min(getOption("width"), 78)) - { - label <- sprintf(label, ...) - n <- max(n - nchar(label) - nchar(prefix) - 2L, 8L) - if (n <= 0) - return(paste(prefix, label)) - - tail <- paste(rep.int(suffix, n), collapse = "") - paste0(prefix, " ", label, " ", tail) - - } - - heredoc <- function(text, leave = 0) { - - # remove leading, trailing whitespace - trimmed <- gsub("^\\s*\\n|\\n\\s*$", "", text) - - # split into lines - lines <- strsplit(trimmed, "\n", fixed = TRUE)[[1L]] - - # compute common indent - indent <- regexpr("[^[:space:]]", lines) - common <- min(setdiff(indent, -1L)) - leave - text <- paste(substring(lines, common), collapse = "\n") - - # substitute in ANSI links for executable renv code - ansify(text) - - } - - bootstrap <- function(version, library) { - - friendly <- renv_bootstrap_version_friendly(version) - section <- header(sprintf("Bootstrapping renv %s", friendly)) - catf(section) - - # attempt to download renv - catf("- Downloading renv ... ", appendLF = FALSE) - withCallingHandlers( - tarball <- renv_bootstrap_download(version), - error = function(err) { - catf("FAILED") - stop("failed to download:\n", conditionMessage(err)) - } - ) - catf("OK") - on.exit(unlink(tarball), add = TRUE) - - # now attempt to install - catf("- Installing renv ... ", appendLF = FALSE) - withCallingHandlers( - status <- renv_bootstrap_install(version, tarball, library), - error = function(err) { - catf("FAILED") - stop("failed to install:\n", conditionMessage(err)) - } - ) - catf("OK") - - # add empty line to break up bootstrapping from normal output - catf("") - - return(invisible()) - } - - renv_bootstrap_tests_running <- function() { - getOption("renv.tests.running", default = FALSE) - } - - renv_bootstrap_repos <- function() { - - # get CRAN repository - cran <- getOption("renv.repos.cran", "https://cloud.r-project.org") - - # check for repos override - repos <- Sys.getenv("RENV_CONFIG_REPOS_OVERRIDE", unset = NA) - if (!is.na(repos)) { - - # check for RSPM; if set, use a fallback repository for renv - rspm <- Sys.getenv("RSPM", unset = NA) - if (identical(rspm, repos)) - repos <- c(RSPM = rspm, CRAN = cran) - - return(repos) - - } - - # check for lockfile repositories - repos <- tryCatch(renv_bootstrap_repos_lockfile(), error = identity) - if (!inherits(repos, "error") && length(repos)) - return(repos) - - # retrieve current repos - repos <- getOption("repos") - - # ensure @CRAN@ entries are resolved - repos[repos == "@CRAN@"] <- cran - - # add in renv.bootstrap.repos if set - default <- c(FALLBACK = "https://cloud.r-project.org") - extra <- getOption("renv.bootstrap.repos", default = default) - repos <- c(repos, extra) - - # remove duplicates that might've snuck in - dupes <- duplicated(repos) | duplicated(names(repos)) - repos[!dupes] - - } - - renv_bootstrap_repos_lockfile <- function() { - - lockpath <- Sys.getenv("RENV_PATHS_LOCKFILE", unset = "renv.lock") - if (!file.exists(lockpath)) - return(NULL) - - lockfile <- tryCatch(renv_json_read(lockpath), error = identity) - if (inherits(lockfile, "error")) { - warning(lockfile) - return(NULL) - } - - repos <- lockfile$R$Repositories - if (length(repos) == 0) - return(NULL) - - keys <- vapply(repos, `[[`, "Name", FUN.VALUE = character(1)) - vals <- vapply(repos, `[[`, "URL", FUN.VALUE = character(1)) - names(vals) <- keys - - return(vals) - - } - - renv_bootstrap_download <- function(version) { - - sha <- attr(version, "sha", exact = TRUE) - - methods <- if (!is.null(sha)) { - - # attempting to bootstrap a development version of renv - c( - function() renv_bootstrap_download_tarball(sha), - function() renv_bootstrap_download_github(sha) - ) - - } else { - - # attempting to bootstrap a release version of renv - c( - function() renv_bootstrap_download_tarball(version), - function() renv_bootstrap_download_cran_latest(version), - function() renv_bootstrap_download_cran_archive(version) - ) - - } - - for (method in methods) { - path <- tryCatch(method(), error = identity) - if (is.character(path) && file.exists(path)) - return(path) - } - - stop("All download methods failed") - - } - - renv_bootstrap_download_impl <- function(url, destfile) { - - mode <- "wb" - - # https://bugs.r-project.org/bugzilla/show_bug.cgi?id=17715 - fixup <- - Sys.info()[["sysname"]] == "Windows" && - substring(url, 1L, 5L) == "file:" - - if (fixup) - mode <- "w+b" - - args <- list( - url = url, - destfile = destfile, - mode = mode, - quiet = TRUE - ) - - if ("headers" %in% names(formals(utils::download.file))) { - headers <- renv_bootstrap_download_custom_headers(url) - if (length(headers) && is.character(headers)) - args$headers <- headers - } - - do.call(utils::download.file, args) - - } - - renv_bootstrap_download_custom_headers <- function(url) { - - headers <- getOption("renv.download.headers") - if (is.null(headers)) - return(character()) - - if (!is.function(headers)) - stopf("'renv.download.headers' is not a function") - - headers <- headers(url) - if (length(headers) == 0L) - return(character()) - - if (is.list(headers)) - headers <- unlist(headers, recursive = FALSE, use.names = TRUE) - - ok <- - is.character(headers) && - is.character(names(headers)) && - all(nzchar(names(headers))) - - if (!ok) - stop("invocation of 'renv.download.headers' did not return a named character vector") - - headers - - } - - renv_bootstrap_download_cran_latest <- function(version) { - - spec <- renv_bootstrap_download_cran_latest_find(version) - type <- spec$type - repos <- spec$repos - - baseurl <- utils::contrib.url(repos = repos, type = type) - ext <- if (identical(type, "source")) - ".tar.gz" - else if (Sys.info()[["sysname"]] == "Windows") - ".zip" - else - ".tgz" - name <- sprintf("renv_%s%s", version, ext) - url <- paste(baseurl, name, sep = "/") - - destfile <- file.path(tempdir(), name) - status <- tryCatch( - renv_bootstrap_download_impl(url, destfile), - condition = identity - ) - - if (inherits(status, "condition")) - return(FALSE) - - # report success and return - destfile - - } - - renv_bootstrap_download_cran_latest_find <- function(version) { - - # check whether binaries are supported on this system - binary <- - getOption("renv.bootstrap.binary", default = TRUE) && - !identical(.Platform$pkgType, "source") && - !identical(getOption("pkgType"), "source") && - Sys.info()[["sysname"]] %in% c("Darwin", "Windows") - - types <- c(if (binary) "binary", "source") - - # iterate over types + repositories - for (type in types) { - for (repos in renv_bootstrap_repos()) { - - # build arguments for utils::available.packages() call - args <- list(type = type, repos = repos) - - # add custom headers if available -- note that - # utils::available.packages() will pass this to download.file() - if ("headers" %in% names(formals(utils::download.file))) { - headers <- renv_bootstrap_download_custom_headers(repos) - if (length(headers) && is.character(headers)) - args$headers <- headers - } - - # retrieve package database - db <- tryCatch( - as.data.frame( - do.call(utils::available.packages, args), - stringsAsFactors = FALSE - ), - error = identity - ) - - if (inherits(db, "error")) - next - - # check for compatible entry - entry <- db[db$Package %in% "renv" & db$Version %in% version, ] - if (nrow(entry) == 0) - next - - # found it; return spec to caller - spec <- list(entry = entry, type = type, repos = repos) - return(spec) - - } - } - - # if we got here, we failed to find renv - fmt <- "renv %s is not available from your declared package repositories" - stop(sprintf(fmt, version)) - - } - - renv_bootstrap_download_cran_archive <- function(version) { - - name <- sprintf("renv_%s.tar.gz", version) - repos <- renv_bootstrap_repos() - urls <- file.path(repos, "src/contrib/Archive/renv", name) - destfile <- file.path(tempdir(), name) - - for (url in urls) { - - status <- tryCatch( - renv_bootstrap_download_impl(url, destfile), - condition = identity - ) - - if (identical(status, 0L)) - return(destfile) - - } - - return(FALSE) - - } - - renv_bootstrap_download_tarball <- function(version) { - - # if the user has provided the path to a tarball via - # an environment variable, then use it - tarball <- Sys.getenv("RENV_BOOTSTRAP_TARBALL", unset = NA) - if (is.na(tarball)) - return() - - # allow directories - if (dir.exists(tarball)) { - name <- sprintf("renv_%s.tar.gz", version) - tarball <- file.path(tarball, name) - } - - # bail if it doesn't exist - if (!file.exists(tarball)) { - - # let the user know we weren't able to honour their request - fmt <- "- RENV_BOOTSTRAP_TARBALL is set (%s) but does not exist." - msg <- sprintf(fmt, tarball) - warning(msg) - - # bail - return() - - } - - catf("- Using local tarball '%s'.", tarball) - tarball - - } - - renv_bootstrap_github_token <- function() { - for (envvar in c("GITHUB_TOKEN", "GITHUB_PAT", "GH_TOKEN")) { - envval <- Sys.getenv(envvar, unset = NA) - if (!is.na(envval)) - return(envval) - } - } - - renv_bootstrap_download_github <- function(version) { - - enabled <- Sys.getenv("RENV_BOOTSTRAP_FROM_GITHUB", unset = "TRUE") - if (!identical(enabled, "TRUE")) - return(FALSE) - - # prepare download options - token <- renv_bootstrap_github_token() - if (is.null(token)) - token <- "" - - if (nzchar(Sys.which("curl")) && nzchar(token)) { - fmt <- "--location --fail --header \"Authorization: token %s\"" - extra <- sprintf(fmt, token) - saved <- options("download.file.method", "download.file.extra") - options(download.file.method = "curl", download.file.extra = extra) - on.exit(do.call(base::options, saved), add = TRUE) - } else if (nzchar(Sys.which("wget")) && nzchar(token)) { - fmt <- "--header=\"Authorization: token %s\"" - extra <- sprintf(fmt, token) - saved <- options("download.file.method", "download.file.extra") - options(download.file.method = "wget", download.file.extra = extra) - on.exit(do.call(base::options, saved), add = TRUE) - } - - url <- file.path("https://api.github.com/repos/rstudio/renv/tarball", version) - name <- sprintf("renv_%s.tar.gz", version) - destfile <- file.path(tempdir(), name) - - status <- tryCatch( - renv_bootstrap_download_impl(url, destfile), - condition = identity - ) - - if (!identical(status, 0L)) - return(FALSE) - - renv_bootstrap_download_augment(destfile) - - return(destfile) - - } - - # Add Sha to DESCRIPTION. This is stop gap until #890, after which we - # can use renv::install() to fully capture metadata. - renv_bootstrap_download_augment <- function(destfile) { - sha <- renv_bootstrap_git_extract_sha1_tar(destfile) - if (is.null(sha)) { - return() - } - - # Untar - tempdir <- tempfile("renv-github-") - on.exit(unlink(tempdir, recursive = TRUE), add = TRUE) - untar(destfile, exdir = tempdir) - pkgdir <- dir(tempdir, full.names = TRUE)[[1]] - - # Modify description - desc_path <- file.path(pkgdir, "DESCRIPTION") - desc_lines <- readLines(desc_path) - remotes_fields <- c( - "RemoteType: github", - "RemoteHost: api.github.com", - "RemoteRepo: renv", - "RemoteUsername: rstudio", - "RemotePkgRef: rstudio/renv", - paste("RemoteRef: ", sha), - paste("RemoteSha: ", sha) - ) - writeLines(c(desc_lines[desc_lines != ""], remotes_fields), con = desc_path) - - # Re-tar - local({ - old <- setwd(tempdir) - on.exit(setwd(old), add = TRUE) - - tar(destfile, compression = "gzip") - }) - invisible() - } - - # Extract the commit hash from a git archive. Git archives include the SHA1 - # hash as the comment field of the tarball pax extended header - # (see https://www.kernel.org/pub/software/scm/git/docs/git-archive.html) - # For GitHub archives this should be the first header after the default one - # (512 byte) header. - renv_bootstrap_git_extract_sha1_tar <- function(bundle) { - - # open the bundle for reading - # We use gzcon for everything because (from ?gzcon) - # > Reading from a connection which does not supply a 'gzip' magic - # > header is equivalent to reading from the original connection - conn <- gzcon(file(bundle, open = "rb", raw = TRUE)) - on.exit(close(conn)) - - # The default pax header is 512 bytes long and the first pax extended header - # with the comment should be 51 bytes long - # `52 comment=` (11 chars) + 40 byte SHA1 hash - len <- 0x200 + 0x33 - res <- rawToChar(readBin(conn, "raw", n = len)[0x201:len]) - - if (grepl("^52 comment=", res)) { - sub("52 comment=", "", res) - } else { - NULL - } - } - - renv_bootstrap_install <- function(version, tarball, library) { - - # attempt to install it into project library - dir.create(library, showWarnings = FALSE, recursive = TRUE) - output <- renv_bootstrap_install_impl(library, tarball) - - # check for successful install - status <- attr(output, "status") - if (is.null(status) || identical(status, 0L)) - return(status) - - # an error occurred; report it - header <- "installation of renv failed" - lines <- paste(rep.int("=", nchar(header)), collapse = "") - text <- paste(c(header, lines, output), collapse = "\n") - stop(text) - - } - - renv_bootstrap_install_impl <- function(library, tarball) { - - # invoke using system2 so we can capture and report output - bin <- R.home("bin") - exe <- if (Sys.info()[["sysname"]] == "Windows") "R.exe" else "R" - R <- file.path(bin, exe) - - args <- c( - "--vanilla", "CMD", "INSTALL", "--no-multiarch", - "-l", shQuote(path.expand(library)), - shQuote(path.expand(tarball)) - ) - - system2(R, args, stdout = TRUE, stderr = TRUE) - - } - - renv_bootstrap_platform_prefix <- function() { - - # construct version prefix - version <- paste(R.version$major, R.version$minor, sep = ".") - prefix <- paste("R", numeric_version(version)[1, 1:2], sep = "-") - - # include SVN revision for development versions of R - # (to avoid sharing platform-specific artefacts with released versions of R) - devel <- - identical(R.version[["status"]], "Under development (unstable)") || - identical(R.version[["nickname"]], "Unsuffered Consequences") - - if (devel) - prefix <- paste(prefix, R.version[["svn rev"]], sep = "-r") - - # build list of path components - components <- c(prefix, R.version$platform) - - # include prefix if provided by user - prefix <- renv_bootstrap_platform_prefix_impl() - if (!is.na(prefix) && nzchar(prefix)) - components <- c(prefix, components) - - # build prefix - paste(components, collapse = "/") - - } - - renv_bootstrap_platform_prefix_impl <- function() { - - # if an explicit prefix has been supplied, use it - prefix <- Sys.getenv("RENV_PATHS_PREFIX", unset = NA) - if (!is.na(prefix)) - return(prefix) - - # if the user has requested an automatic prefix, generate it - auto <- Sys.getenv("RENV_PATHS_PREFIX_AUTO", unset = NA) - if (is.na(auto) && getRversion() >= "4.4.0") - auto <- "TRUE" - - if (auto %in% c("TRUE", "True", "true", "1")) - return(renv_bootstrap_platform_prefix_auto()) - - # empty string on failure - "" - - } - - renv_bootstrap_platform_prefix_auto <- function() { - - prefix <- tryCatch(renv_bootstrap_platform_os(), error = identity) - if (inherits(prefix, "error") || prefix %in% "unknown") { - - msg <- paste( - "failed to infer current operating system", - "please file a bug report at https://github.com/rstudio/renv/issues", - sep = "; " - ) - - warning(msg) - - } - - prefix - - } - - renv_bootstrap_platform_os <- function() { - - sysinfo <- Sys.info() - sysname <- sysinfo[["sysname"]] - - # handle Windows + macOS up front - if (sysname == "Windows") - return("windows") - else if (sysname == "Darwin") - return("macos") - - # check for os-release files - for (file in c("/etc/os-release", "/usr/lib/os-release")) - if (file.exists(file)) - return(renv_bootstrap_platform_os_via_os_release(file, sysinfo)) - - # check for redhat-release files - if (file.exists("/etc/redhat-release")) - return(renv_bootstrap_platform_os_via_redhat_release()) - - "unknown" - - } - - renv_bootstrap_platform_os_via_os_release <- function(file, sysinfo) { - - # read /etc/os-release - release <- utils::read.table( - file = file, - sep = "=", - quote = c("\"", "'"), - col.names = c("Key", "Value"), - comment.char = "#", - stringsAsFactors = FALSE - ) - - vars <- as.list(release$Value) - names(vars) <- release$Key - - # get os name - os <- tolower(sysinfo[["sysname"]]) - - # read id - id <- "unknown" - for (field in c("ID", "ID_LIKE")) { - if (field %in% names(vars) && nzchar(vars[[field]])) { - id <- vars[[field]] - break - } - } - - # read version - version <- "unknown" - for (field in c("UBUNTU_CODENAME", "VERSION_CODENAME", "VERSION_ID", "BUILD_ID")) { - if (field %in% names(vars) && nzchar(vars[[field]])) { - version <- vars[[field]] - break - } - } - - # join together - paste(c(os, id, version), collapse = "-") - - } - - renv_bootstrap_platform_os_via_redhat_release <- function() { - - # read /etc/redhat-release - contents <- readLines("/etc/redhat-release", warn = FALSE) - - # infer id - id <- if (grepl("centos", contents, ignore.case = TRUE)) - "centos" - else if (grepl("redhat", contents, ignore.case = TRUE)) - "redhat" - else - "unknown" - - # try to find a version component (very hacky) - version <- "unknown" - - parts <- strsplit(contents, "[[:space:]]")[[1L]] - for (part in parts) { - - nv <- tryCatch(numeric_version(part), error = identity) - if (inherits(nv, "error")) - next - - version <- nv[1, 1] - break - - } - - paste(c("linux", id, version), collapse = "-") - - } - - renv_bootstrap_library_root_name <- function(project) { - - # use project name as-is if requested - asis <- Sys.getenv("RENV_PATHS_LIBRARY_ROOT_ASIS", unset = "FALSE") - if (asis) - return(basename(project)) - - # otherwise, disambiguate based on project's path - id <- substring(renv_bootstrap_hash_text(project), 1L, 8L) - paste(basename(project), id, sep = "-") - - } - - renv_bootstrap_library_root <- function(project) { - - prefix <- renv_bootstrap_profile_prefix() - - path <- Sys.getenv("RENV_PATHS_LIBRARY", unset = NA) - if (!is.na(path)) - return(paste(c(path, prefix), collapse = "/")) - - path <- renv_bootstrap_library_root_impl(project) - if (!is.null(path)) { - name <- renv_bootstrap_library_root_name(project) - return(paste(c(path, prefix, name), collapse = "/")) - } - - renv_bootstrap_paths_renv("library", project = project) - - } - - renv_bootstrap_library_root_impl <- function(project) { - - root <- Sys.getenv("RENV_PATHS_LIBRARY_ROOT", unset = NA) - if (!is.na(root)) - return(root) - - type <- renv_bootstrap_project_type(project) - if (identical(type, "package")) { - userdir <- renv_bootstrap_user_dir() - return(file.path(userdir, "library")) - } - - } - - renv_bootstrap_validate_version <- function(version, description = NULL) { - - # resolve description file - # - # avoid passing lib.loc to `packageDescription()` below, since R will - # use the loaded version of the package by default anyhow. note that - # this function should only be called after 'renv' is loaded - # https://github.com/rstudio/renv/issues/1625 - description <- description %||% packageDescription("renv") - - # check whether requested version 'version' matches loaded version of renv - sha <- attr(version, "sha", exact = TRUE) - valid <- if (!is.null(sha)) - renv_bootstrap_validate_version_dev(sha, description) - else - renv_bootstrap_validate_version_release(version, description) - - if (valid) - return(TRUE) - - # the loaded version of renv doesn't match the requested version; - # give the user instructions on how to proceed - dev <- identical(description[["RemoteType"]], "github") - remote <- if (dev) - paste("rstudio/renv", description[["RemoteSha"]], sep = "@") - else - paste("renv", description[["Version"]], sep = "@") - - # display both loaded version + sha if available - friendly <- renv_bootstrap_version_friendly( - version = description[["Version"]], - sha = if (dev) description[["RemoteSha"]] - ) - - fmt <- heredoc(" - renv %1$s was loaded from project library, but this project is configured to use renv %2$s. - - Use `renv::record(\"%3$s\")` to record renv %1$s in the lockfile. - - Use `renv::restore(packages = \"renv\")` to install renv %2$s into the project library. - ") - catf(fmt, friendly, renv_bootstrap_version_friendly(version), remote) - - FALSE - - } - - renv_bootstrap_validate_version_dev <- function(version, description) { - - expected <- description[["RemoteSha"]] - if (!is.character(expected)) - return(FALSE) - - pattern <- sprintf("^\\Q%s\\E", version) - grepl(pattern, expected, perl = TRUE) - - } - - renv_bootstrap_validate_version_release <- function(version, description) { - expected <- description[["Version"]] - is.character(expected) && identical(expected, version) - } - - renv_bootstrap_hash_text <- function(text) { - - hashfile <- tempfile("renv-hash-") - on.exit(unlink(hashfile), add = TRUE) - - writeLines(text, con = hashfile) - tools::md5sum(hashfile) - - } - - renv_bootstrap_load <- function(project, libpath, version) { - - # try to load renv from the project library - if (!requireNamespace("renv", lib.loc = libpath, quietly = TRUE)) - return(FALSE) - - # warn if the version of renv loaded does not match - renv_bootstrap_validate_version(version) - - # execute renv load hooks, if any - hooks <- getHook("renv::autoload") - for (hook in hooks) - if (is.function(hook)) - tryCatch(hook(), error = warnify) - - # load the project - renv::load(project) - - TRUE - - } - - renv_bootstrap_profile_load <- function(project) { - - # if RENV_PROFILE is already set, just use that - profile <- Sys.getenv("RENV_PROFILE", unset = NA) - if (!is.na(profile) && nzchar(profile)) - return(profile) - - # check for a profile file (nothing to do if it doesn't exist) - path <- renv_bootstrap_paths_renv("profile", profile = FALSE, project = project) - if (!file.exists(path)) - return(NULL) - - # read the profile, and set it if it exists - contents <- readLines(path, warn = FALSE) - if (length(contents) == 0L) - return(NULL) - - # set RENV_PROFILE - profile <- contents[[1L]] - if (!profile %in% c("", "default")) - Sys.setenv(RENV_PROFILE = profile) - - profile - - } - - renv_bootstrap_profile_prefix <- function() { - profile <- renv_bootstrap_profile_get() - if (!is.null(profile)) - return(file.path("profiles", profile, "renv")) - } - - renv_bootstrap_profile_get <- function() { - profile <- Sys.getenv("RENV_PROFILE", unset = "") - renv_bootstrap_profile_normalize(profile) - } - - renv_bootstrap_profile_set <- function(profile) { - profile <- renv_bootstrap_profile_normalize(profile) - if (is.null(profile)) - Sys.unsetenv("RENV_PROFILE") - else - Sys.setenv(RENV_PROFILE = profile) - } - - renv_bootstrap_profile_normalize <- function(profile) { - - if (is.null(profile) || profile %in% c("", "default")) - return(NULL) - - profile - - } - - renv_bootstrap_path_absolute <- function(path) { - - substr(path, 1L, 1L) %in% c("~", "/", "\\") || ( - substr(path, 1L, 1L) %in% c(letters, LETTERS) && - substr(path, 2L, 3L) %in% c(":/", ":\\") - ) - - } - - renv_bootstrap_paths_renv <- function(..., profile = TRUE, project = NULL) { - renv <- Sys.getenv("RENV_PATHS_RENV", unset = "renv") - root <- if (renv_bootstrap_path_absolute(renv)) NULL else project - prefix <- if (profile) renv_bootstrap_profile_prefix() - components <- c(root, renv, prefix, ...) - paste(components, collapse = "/") - } - - renv_bootstrap_project_type <- function(path) { - - descpath <- file.path(path, "DESCRIPTION") - if (!file.exists(descpath)) - return("unknown") - - desc <- tryCatch( - read.dcf(descpath, all = TRUE), - error = identity - ) - - if (inherits(desc, "error")) - return("unknown") - - type <- desc$Type - if (!is.null(type)) - return(tolower(type)) - - package <- desc$Package - if (!is.null(package)) - return("package") - - "unknown" - - } - - renv_bootstrap_user_dir <- function() { - dir <- renv_bootstrap_user_dir_impl() - path.expand(chartr("\\", "/", dir)) - } - - renv_bootstrap_user_dir_impl <- function() { - - # use local override if set - override <- getOption("renv.userdir.override") - if (!is.null(override)) - return(override) - - # use R_user_dir if available - tools <- asNamespace("tools") - if (is.function(tools$R_user_dir)) - return(tools$R_user_dir("renv", "cache")) - - # try using our own backfill for older versions of R - envvars <- c("R_USER_CACHE_DIR", "XDG_CACHE_HOME") - for (envvar in envvars) { - root <- Sys.getenv(envvar, unset = NA) - if (!is.na(root)) - return(file.path(root, "R/renv")) - } - - # use platform-specific default fallbacks - if (Sys.info()[["sysname"]] == "Windows") - file.path(Sys.getenv("LOCALAPPDATA"), "R/cache/R/renv") - else if (Sys.info()[["sysname"]] == "Darwin") - "~/Library/Caches/org.R-project.R/R/renv" - else - "~/.cache/R/renv" - - } - - renv_bootstrap_version_friendly <- function(version, shafmt = NULL, sha = NULL) { - sha <- sha %||% attr(version, "sha", exact = TRUE) - parts <- c(version, sprintf(shafmt %||% " [sha: %s]", substring(sha, 1L, 7L))) - paste(parts, collapse = "") - } - - renv_bootstrap_exec <- function(project, libpath, version) { - if (!renv_bootstrap_load(project, libpath, version)) - renv_bootstrap_run(project, libpath, version) - } - - renv_bootstrap_run <- function(project, libpath, version) { - - # perform bootstrap - bootstrap(version, libpath) - - # exit early if we're just testing bootstrap - if (!is.na(Sys.getenv("RENV_BOOTSTRAP_INSTALL_ONLY", unset = NA))) - return(TRUE) - - # try again to load - if (requireNamespace("renv", lib.loc = libpath, quietly = TRUE)) { - return(renv::load(project = project)) - } - - # failed to download or load renv; warn the user - msg <- c( - "Failed to find an renv installation: the project will not be loaded.", - "Use `renv::activate()` to re-initialize the project." - ) - - warning(paste(msg, collapse = "\n"), call. = FALSE) - - } - - renv_json_read <- function(file = NULL, text = NULL) { - - jlerr <- NULL - - # if jsonlite is loaded, use that instead - if ("jsonlite" %in% loadedNamespaces()) { - - json <- tryCatch(renv_json_read_jsonlite(file, text), error = identity) - if (!inherits(json, "error")) - return(json) - - jlerr <- json - - } - - # otherwise, fall back to the default JSON reader - json <- tryCatch(renv_json_read_default(file, text), error = identity) - if (!inherits(json, "error")) - return(json) - - # report an error - if (!is.null(jlerr)) - stop(jlerr) - else - stop(json) - - } - - renv_json_read_jsonlite <- function(file = NULL, text = NULL) { - text <- paste(text %||% readLines(file, warn = FALSE), collapse = "\n") - jsonlite::fromJSON(txt = text, simplifyVector = FALSE) - } - - renv_json_read_patterns <- function() { - - list( - - # objects - list("{", "\t\n\tobject(\t\n\t"), - list("}", "\t\n\t)\t\n\t"), - - # arrays - list("[", "\t\n\tarray(\t\n\t"), - list("]", "\n\t\n)\n\t\n"), - - # maps - list(":", "\t\n\t=\t\n\t") - - ) - - } - - renv_json_read_envir <- function() { - - envir <- new.env(parent = emptyenv()) - - envir[["+"]] <- `+` - envir[["-"]] <- `-` - - envir[["object"]] <- function(...) { - result <- list(...) - names(result) <- as.character(names(result)) - result - } - - envir[["array"]] <- list - - envir[["true"]] <- TRUE - envir[["false"]] <- FALSE - envir[["null"]] <- NULL - - envir - - } - - renv_json_read_remap <- function(object, patterns) { - - # repair names if necessary - if (!is.null(names(object))) { - - nms <- names(object) - for (pattern in patterns) - nms <- gsub(pattern[[2L]], pattern[[1L]], nms, fixed = TRUE) - names(object) <- nms - - } - - # repair strings if necessary - if (is.character(object)) { - for (pattern in patterns) - object <- gsub(pattern[[2L]], pattern[[1L]], object, fixed = TRUE) - } - - # recurse for other objects - if (is.recursive(object)) - for (i in seq_along(object)) - object[i] <- list(renv_json_read_remap(object[[i]], patterns)) - - # return remapped object - object - - } - - renv_json_read_default <- function(file = NULL, text = NULL) { - - # read json text - text <- paste(text %||% readLines(file, warn = FALSE), collapse = "\n") - - # convert into something the R parser will understand - patterns <- renv_json_read_patterns() - transformed <- text - for (pattern in patterns) - transformed <- gsub(pattern[[1L]], pattern[[2L]], transformed, fixed = TRUE) - - # parse it - rfile <- tempfile("renv-json-", fileext = ".R") - on.exit(unlink(rfile), add = TRUE) - writeLines(transformed, con = rfile) - json <- parse(rfile, keep.source = FALSE, srcfile = NULL)[[1L]] - - # evaluate in safe environment - result <- eval(json, envir = renv_json_read_envir()) - - # fix up strings if necessary - renv_json_read_remap(result, patterns) - - } - - - # load the renv profile, if any - renv_bootstrap_profile_load(project) - - # construct path to library root - root <- renv_bootstrap_library_root(project) - - # construct library prefix for platform - prefix <- renv_bootstrap_platform_prefix() - - # construct full libpath - libpath <- file.path(root, prefix) - - # run bootstrap code - renv_bootstrap_exec(project, libpath, version) - - invisible() - -}) diff --git a/renv/profile b/renv/profile deleted file mode 100644 index 6d4023b..0000000 --- a/renv/profile +++ /dev/null @@ -1 +0,0 @@ -lesson-requirements diff --git a/renv/profiles/lesson-requirements/renv/.gitignore b/renv/profiles/lesson-requirements/renv/.gitignore deleted file mode 100644 index 0ec0cbb..0000000 --- a/renv/profiles/lesson-requirements/renv/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -library/ -local/ -cellar/ -lock/ -python/ -sandbox/ -staging/ diff --git a/renv/profiles/lesson-requirements/renv/settings.json b/renv/profiles/lesson-requirements/renv/settings.json deleted file mode 100644 index ffdbb32..0000000 --- a/renv/profiles/lesson-requirements/renv/settings.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "bioconductor.version": null, - "external.libraries": [], - "ignored.packages": [], - "package.dependency.fields": [ - "Imports", - "Depends", - "LinkingTo" - ], - "ppm.enabled": null, - "ppm.ignored.urls": [], - "r.version": null, - "snapshot.type": "implicit", - "use.cache": true, - "vcs.ignore.cellar": true, - "vcs.ignore.library": true, - "vcs.ignore.local": true, - "vcs.manage.ignores": true -} diff --git a/learners/setup.md b/setup.md similarity index 100% rename from learners/setup.md rename to setup.md diff --git a/site/README.md b/site/README.md deleted file mode 100644 index 42997e3..0000000 --- a/site/README.md +++ /dev/null @@ -1,2 +0,0 @@ -This directory contains rendered lesson materials. Please do not edit files -here.