├── .editorconfig ├── .github ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── template.yml │ └── website.yml ├── .gitignore ├── 404.md ├── CODE_OF_CONDUCT.md ├── Gemfile ├── LICENSE.md ├── Makefile ├── _episodes └── .gitkeep ├── _episodes_rmd ├── .gitkeep └── data │ └── .gitkeep ├── _extras └── .gitkeep ├── _includes ├── aio-script.md ├── all_keypoints.html ├── base_path.html ├── carpentries.html ├── check_transition_variables.html ├── dc │ ├── intro.html │ ├── schedule.html │ ├── syllabus.html │ └── who.html ├── episode_break.html ├── episode_keypoints.html ├── episode_navbar.html ├── episode_overview.html ├── episode_title.html ├── favicons.html ├── gh_variables.html ├── javascript.html ├── lc │ ├── intro.html │ ├── schedule.html │ ├── syllabus.html │ └── who.html ├── lesson_footer.html ├── life_cycle.html ├── links.md ├── main_title.html ├── manual_episode_order.html ├── navbar.html ├── sc │ ├── intro.html │ ├── schedule.html │ ├── syllabus.html │ └── who.html ├── syllabus.html ├── workshop_ad.html ├── workshop_calendar.html └── workshop_footer.html ├── _layouts ├── base.html ├── break.html ├── episode.html ├── lesson.html ├── page.html ├── reference.html └── workshop.html ├── aio.md ├── assets ├── css │ ├── bootstrap-theme.css │ ├── bootstrap-theme.css.map │ ├── bootstrap.css │ ├── bootstrap.css.map │ ├── katex.min.css │ ├── lesson.scss │ └── syntax.css ├── favicons │ ├── cp │ │ ├── apple-touch-icon-114x114.png │ │ ├── apple-touch-icon-120x120.png │ │ ├── apple-touch-icon-144x144.png │ │ ├── apple-touch-icon-152x152.png │ │ ├── apple-touch-icon-57x57.png │ │ ├── apple-touch-icon-60x60.png │ │ ├── apple-touch-icon-72x72.png │ │ ├── apple-touch-icon-76x76.png │ │ ├── favicon-128.png │ │ ├── favicon-16x16.png │ │ ├── favicon-196x196.png │ │ ├── favicon-32x32.png │ │ ├── favicon-96x96.png │ │ ├── favicon.ico │ │ ├── mstile-144x144.png │ │ ├── mstile-150x150.png │ │ ├── mstile-310x150.png │ │ ├── mstile-310x310.png │ │ └── mstile-70x70.png │ ├── dc │ │ ├── apple-touch-icon-114x114.png │ │ ├── apple-touch-icon-120x120.png │ │ ├── apple-touch-icon-144x144.png │ │ ├── apple-touch-icon-152x152.png │ │ ├── apple-touch-icon-57x57.png │ │ ├── apple-touch-icon-60x60.png │ │ ├── apple-touch-icon-72x72.png │ │ ├── apple-touch-icon-76x76.png │ │ ├── favicon-128.png │ │ ├── favicon-16x16.png │ │ ├── favicon-196x196.png │ │ ├── favicon-32x32.png │ │ ├── favicon-96x96.png │ │ ├── favicon.ico │ │ ├── mstile-144x144.png │ │ ├── mstile-150x150.png │ │ ├── mstile-310x150.png │ │ ├── mstile-310x310.png │ │ └── mstile-70x70.png │ ├── lc │ │ ├── apple-touch-icon-114x114.png │ │ ├── apple-touch-icon-120x120.png │ │ ├── apple-touch-icon-144x144.png │ │ ├── apple-touch-icon-152x152.png │ │ ├── apple-touch-icon-57x57.png │ │ ├── apple-touch-icon-60x60.png │ │ ├── apple-touch-icon-72x72.png │ │ ├── apple-touch-icon-76x76.png │ │ ├── favicon-128.png │ │ ├── favicon-16x16.png │ │ ├── favicon-196x196.png │ │ ├── favicon-32x32.png │ │ ├── favicon-96x96.png │ │ ├── favicon.ico │ │ ├── mstile-144x144.png │ │ ├── mstile-150x150.png │ │ ├── mstile-310x150.png │ │ ├── mstile-310x310.png │ │ └── mstile-70x70.png │ └── swc │ │ ├── apple-touch-icon-114x114.png │ │ ├── apple-touch-icon-120x120.png │ │ ├── apple-touch-icon-144x144.png │ │ ├── apple-touch-icon-152x152.png │ │ ├── apple-touch-icon-57x57.png │ │ ├── apple-touch-icon-60x60.png │ │ ├── apple-touch-icon-72x72.png │ │ ├── apple-touch-icon-76x76.png │ │ ├── favicon-128.png │ │ ├── favicon-16x16.png │ │ ├── favicon-196x196.png │ │ ├── favicon-32x32.png │ │ ├── favicon-96x96.png │ │ ├── favicon.ico │ │ ├── mstile-144x144.png │ │ ├── mstile-150x150.png │ │ ├── mstile-310x150.png │ │ ├── mstile-310x310.png │ │ └── mstile-70x70.png ├── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.svg │ ├── glyphicons-halflings-regular.ttf │ ├── glyphicons-halflings-regular.woff │ └── glyphicons-halflings-regular.woff2 ├── img │ ├── carpentrieslab.svg │ ├── cp-logo-blue.svg │ ├── dc-icon-black.svg │ ├── dc-logo-black.svg │ ├── lc-icon-black.png │ ├── lc-icon-black.svg │ ├── lc-logo-black.png │ ├── lc-logo-black.svg │ ├── swc-icon-blue.svg │ ├── swc-logo-blue.png │ ├── swc-logo-blue.svg │ ├── swc-logo-white.png │ └── swc-logo-white.svg └── js │ ├── anchor.min.js │ ├── bootstrap.min.js │ ├── jquery.min.js │ ├── jquery.min.map │ ├── katex-auto-render.min.js │ ├── katex.min.js │ └── lesson.js ├── bin ├── boilerplate │ ├── AUTHORS │ ├── CITATION │ ├── CONTRIBUTING.md │ ├── README.md │ ├── _config.yml │ ├── _episodes │ │ └── 01-introduction.md │ ├── _extras │ │ ├── about.md │ │ ├── discuss.md │ │ ├── figures.md │ │ └── guide.md │ ├── index.md │ ├── reference.md │ └── setup.md ├── chunk-options.R ├── dependencies.R ├── generate_md_episodes.R ├── install_r_deps.sh ├── knit_lessons.sh ├── lesson_check.py ├── lesson_initialize.py ├── markdown_ast.rb ├── repo_check.py ├── reporter.py ├── run-make-docker-serve.sh ├── test_lesson_check.py ├── util.py └── workshop_check.py ├── code └── .gitkeep ├── data └── .gitkeep ├── fig └── .gitkeep └── files └── .gitkeep /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | insert_final_newline = true 6 | trim_trailing_whitespace = true 7 | 8 | [*.md] 9 | indent_size = 2 10 | indent_style = space 11 | max_line_length = 100 # Please keep this in sync with bin/lesson_check.py! 12 | trim_trailing_whitespace = false # keep trailing spaces in markdown - 2+ spaces are translated to a hard break (
) 13 | 14 | [*.r] 15 | max_line_length = 80 16 | 17 | [*.py] 18 | indent_size = 4 19 | indent_style = space 20 | max_line_length = 79 21 | 22 | [*.sh] 23 | end_of_line = lf 24 | 25 | [Makefile] 26 | indent_style = tab 27 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 |
2 | Instructions 3 | 4 | Thanks for contributing! :heart: 5 | 6 | If this contribution is for instructor training, please email the link to this contribution to 7 | checkout@carpentries.org so we can record your progress. You've completed your contribution 8 | step for instructor checkout by submitting this contribution! 9 | 10 | If this issue is about a specific episode within a lesson, please provide its link or filename. 11 | 12 | Keep in mind that **lesson maintainers are volunteers** and it may take them some time to 13 | respond to your contribution. Although not all contributions can be incorporated into the lesson 14 | materials, we appreciate your time and effort to improve the curriculum. If you have any questions 15 | about the lesson maintenance process or would like to volunteer your time as a contribution 16 | reviewer, please contact The Carpentries Team at team@carpentries.org. 17 | 18 | You may delete these instructions from your comment. 19 | 20 | \- The Carpentries 21 |
22 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 |
2 | Instructions 3 | 4 | Thanks for contributing! :heart: 5 | 6 | If this contribution is for instructor training, please email the link to this contribution to 7 | instructor.training@carpentries.org so we can record your progress. You've completed your contribution 8 | step for instructor checkout by submitting this contribution! 9 | 10 | Keep in mind that **lesson maintainers are volunteers** and it may take them some time to 11 | respond to your contribution. Although not all contributions can be incorporated into the lesson 12 | materials, we appreciate your time and effort to improve the curriculum. If you have any questions 13 | about the lesson maintenance process or would like to volunteer your time as a contribution 14 | reviewer, please contact The Carpentries Team at team@carpentries.org. 15 | 16 | You may delete these instructions from your comment. 17 | 18 | \- The Carpentries 19 |
20 | -------------------------------------------------------------------------------- /.github/workflows/template.yml: -------------------------------------------------------------------------------- 1 | name: Test template 2 | on: 3 | push: 4 | branches: gh-pages 5 | pull_request: 6 | jobs: 7 | check-template: 8 | name: ${{ matrix.lesson-name }} (${{ matrix.os-name }}) 9 | if: github.repository == 'carpentries/styles' 10 | runs-on: ${{ matrix.os }} 11 | continue-on-error: ${{ matrix.experimental }} 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | lesson: [swcarpentry/shell-novice, datacarpentry/r-intro-geospatial, librarycarpentry/lc-git] 16 | os: [ubuntu-20.04, macos-latest, windows-latest] 17 | experimental: [false] 18 | include: 19 | - os: ubuntu-20.04 20 | os-name: Linux 21 | - os: macos-latest 22 | os-name: macOS 23 | - os: windows-latest 24 | os-name: Windows 25 | - lesson: swcarpentry/shell-novice 26 | lesson-name: (SWC) Shell novice 27 | - lesson: datacarpentry/r-intro-geospatial 28 | lesson-name: (DC) R Intro Geospatial 29 | - lesson: librarycarpentry/lc-git 30 | lesson-name: (LC) Intro to Git 31 | - lesson: datacarpentry/astronomy-python 32 | lesson-name: (DC) Foundations of Astronomical Data Science 33 | experimental: true 34 | os: ubuntu-20.04 35 | os-name: Linux 36 | - lesson: carpentries/lesson-example 37 | lesson-name: (CP) Lesson Example 38 | experimental: false 39 | os: ubuntu-20.04 40 | os-name: Linux 41 | defaults: 42 | run: 43 | shell: bash # forces 'Git for Windows' on Windows 44 | env: 45 | RSPM: 'https://packagemanager.rstudio.com/cran/__linux__/focal/latest' 46 | steps: 47 | - name: Set up Ruby 48 | uses: ruby/setup-ruby@v1 49 | with: 50 | ruby-version: '2.7' 51 | bundler-cache: true 52 | 53 | - name: Set up Python 54 | uses: actions/setup-python@v2 55 | with: 56 | python-version: '3.x' 57 | 58 | - name: Install GitHub Pages, Bundler, and kramdown gems 59 | run: | 60 | gem install github-pages bundler kramdown kramdown-parser-gfm 61 | 62 | - name: Install Python modules 63 | run: | 64 | if [[ $RUNNER_OS == macOS || $RUNNER_OS == Linux ]]; then 65 | python3 -m pip install --upgrade pip setuptools wheel pyyaml==5.3.1 requests 66 | elif [[ $RUNNER_OS == Windows ]]; then 67 | python -m pip install --upgrade pip setuptools wheel pyyaml==5.3.1 requests 68 | fi 69 | 70 | - name: Checkout the ${{ matrix.lesson }} lesson 71 | uses: actions/checkout@master 72 | with: 73 | repository: ${{ matrix.lesson }} 74 | path: lesson 75 | fetch-depth: 0 76 | 77 | - name: Sync lesson with carpentries/styles 78 | working-directory: lesson 79 | run: | 80 | echo "::group::Fetch Styles" 81 | if [[ -n "${{ github.event.pull_request.number }}" ]] 82 | then 83 | ref="refs/pull/${{ github.event.pull_request.number }}/head" 84 | else 85 | ref="gh-pages" 86 | fi 87 | 88 | git config --global user.email "team@carpentries.org" 89 | git config --global user.name "The Carpentries Bot" 90 | 91 | git remote add styles https://github.com/carpentries/styles.git 92 | git fetch styles $ref:styles-ref 93 | echo "::endgroup::" 94 | echo "::group::Synchronize Styles" 95 | # Sync up only if necessary 96 | if [[ $(git rev-list --count HEAD..styles-ref) != 0 ]] 97 | then 98 | 99 | # The merge command below might fail for lessons that use remote theme 100 | # https://github.com/carpentries/carpentries-theme 101 | echo "Testing merge using recursive strategy, accepting upstream changes without committing" 102 | if ! git merge -s recursive -Xtheirs --no-commit styles-ref 103 | then 104 | 105 | # Remove "deleted by us, unmerged" files from the staging area. 106 | # these are the files that were removed from the lesson 107 | # but are still present in the carpentries/styles repo 108 | echo "Removing previously deleted files" 109 | git rm $(git diff --name-only --diff-filter=DU) 110 | 111 | # If there are still "unmerged" files, 112 | # let's raise an error and look into this more closely 113 | if [[ -n $(git diff --name-only --diff-filter=U) ]] 114 | then 115 | echo "There were unmerged files in ${{ matrix.lesson-name }}:" 116 | echo "$(git diff --compact-summary --diff-filter=U)" 117 | exit 1 118 | fi 119 | fi 120 | 121 | echo "Committing changes" 122 | git commit -m "Sync lesson with carpentries/styles" 123 | fi 124 | echo "::endgroup::" 125 | 126 | - name: Look for R-markdown files 127 | id: check-rmd 128 | working-directory: lesson 129 | run: | 130 | echo "count=$(shopt -s nullglob; files=($(find . -iname '*.Rmd')); echo ${#files[@]})" >> $GITHUB_OUTPUT 131 | 132 | - name: Set up R 133 | if: steps.check-rmd.outputs.count != 0 134 | uses: r-lib/actions/setup-r@v2 135 | with: 136 | use-public-rspm: true 137 | install-r: false 138 | 139 | - name: Install needed packages 140 | if: steps.check-rmd.outputs.count != 0 141 | working-directory: lesson 142 | run: | 143 | source('bin/dependencies.R') 144 | install_required_packages(.libPaths()[1]) 145 | shell: Rscript {0} 146 | 147 | - name: Query dependencies 148 | if: steps.check-rmd.outputs.count != 0 149 | working-directory: lesson 150 | run: | 151 | source('bin/dependencies.R') 152 | deps <- identify_dependencies() 153 | create_description(deps) 154 | use_bioc_repos() 155 | saveRDS(remotes::dev_package_deps(dependencies = TRUE), ".github/depends.Rds", version = 2) 156 | writeLines(sprintf("R-%i.%i", getRversion()$major, getRversion()$minor), ".github/R-version") 157 | shell: Rscript {0} 158 | 159 | - name: Restore Package Cache 160 | if: runner.os != 'Windows' && steps.check-rmd.outputs.count != 0 161 | uses: actions/cache@v2 162 | with: 163 | path: ${{ env.R_LIBS_USER }} 164 | key: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-${{ hashFiles('.github/depends.Rds') }} 165 | restore-keys: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1- 166 | 167 | - name: Install stringi from source 168 | if: runner.os == 'Linux' && steps.check-rmd.outputs.count != 0 169 | run: install.packages('stringi', repos='https://cloud.r-project.org') 170 | shell: Rscript {0} 171 | 172 | - name: Install system dependencies for R packages 173 | if: runner.os == 'Linux' && steps.check-rmd.outputs.count != 0 174 | working-directory: lesson 175 | run: | 176 | while read -r cmd 177 | do 178 | eval sudo $cmd || echo "Nothing to update" 179 | done < <(Rscript -e 'cat(remotes::system_requirements("ubuntu", "20.04"), sep = "\n")') 180 | 181 | - run: make site 182 | working-directory: lesson 183 | 184 | - run: make lesson-check-all 185 | working-directory: lesson 186 | -------------------------------------------------------------------------------- /.github/workflows/website.yml: -------------------------------------------------------------------------------- 1 | name: Website 2 | on: 3 | push: 4 | branches: 5 | - gh-pages 6 | - main 7 | pull_request: [] 8 | jobs: 9 | build-website: 10 | if: ${{ !endsWith(github.repository, '/styles') }} 11 | runs-on: ubuntu-20.04 12 | env: 13 | RSPM: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest" 14 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 15 | defaults: 16 | run: 17 | shell: bash 18 | steps: 19 | - name: Set up Ruby 20 | uses: ruby/setup-ruby@v1 21 | with: 22 | ruby-version: '2.7' 23 | bundler-cache: true 24 | 25 | - name: Set up Python 26 | uses: actions/setup-python@v2 27 | with: 28 | python-version: '3.x' 29 | 30 | - name: Install GitHub Pages, Bundler, and kramdown gems 31 | run: | 32 | gem install github-pages bundler kramdown kramdown-parser-gfm 33 | 34 | - name: Install Python modules 35 | run: | 36 | python3 -m pip install --upgrade pip setuptools wheel pyyaml==5.3.1 requests 37 | 38 | - name: Checkout the lesson 39 | uses: actions/checkout@master 40 | with: 41 | fetch-depth: 0 42 | ref: ${{ github.event.pull_request.head.sha }} 43 | 44 | - name: Look for R-markdown files 45 | id: check-rmd 46 | run: | 47 | echo "count=$(shopt -s nullglob; files=($(find . -iname '*.Rmd')); echo ${#files[@]})" >> $GITHUB_OUTPUT 48 | 49 | - name: Set up R 50 | if: steps.check-rmd.outputs.count != 0 51 | uses: r-lib/actions/setup-r@v2 52 | with: 53 | use-public-rspm: true 54 | install-r: false 55 | 56 | - name: Restore R Cache 57 | if: steps.check-rmd.outputs.count != 0 58 | uses: actions/cache@v2 59 | with: 60 | path: ${{ env.R_LIBS_USER }} 61 | key: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-${{ hashFiles('.github/depends.Rds') }} 62 | restore-keys: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1- 63 | 64 | - name: Install needed packages 65 | if: steps.check-rmd.outputs.count != 0 66 | run: | 67 | source('bin/dependencies.R') 68 | install_required_packages() 69 | shell: Rscript {0} 70 | 71 | - name: Query dependencies 72 | if: steps.check-rmd.outputs.count != 0 73 | run: | 74 | source('bin/dependencies.R') 75 | deps <- identify_dependencies() 76 | create_description(deps) 77 | use_bioc_repos() 78 | saveRDS(remotes::dev_package_deps(dependencies = TRUE), ".github/depends.Rds", version = 2) 79 | writeLines(sprintf("R-%i.%i", getRversion()$major, getRversion()$minor), ".github/R-version") 80 | shell: Rscript {0} 81 | 82 | 83 | - name: Install system dependencies for R packages 84 | if: steps.check-rmd.outputs.count != 0 85 | run: | 86 | while read -r cmd 87 | do 88 | eval sudo $cmd || echo "Nothing to update" 89 | done < <(Rscript -e 'cat(remotes::system_requirements("ubuntu", "20.04"), sep = "\n")') 90 | 91 | - name: Render the markdown and confirm that the site can be built 92 | run: make site 93 | 94 | - name: Checkout github pages 95 | if: ${{ github.event_name == 'push' && steps.check-rmd.outputs.count != 0 && github.ref != 'refs/heads/gh-pages'}} 96 | uses: actions/checkout@master 97 | with: 98 | ref: gh-pages 99 | path: gh-pages 100 | 101 | - name: Commit and Push 102 | if: ${{ github.event_name == 'push' && steps.check-rmd.outputs.count != 0 && github.ref != 'refs/heads/gh-pages'}} 103 | run: | 104 | # clean up gh-pages 105 | cd gh-pages 106 | git rm -rf . # remove all previous files 107 | git restore --staged . # remove things from the stage 108 | cd .. 109 | # copy everything into gh-pages site 110 | cp -r `ls -A | grep -v 'gh-pages' | grep -v '.git' | grep -v '.bundle/' | grep -v '_site'` gh-pages 111 | # move into gh-pages, add, commit, and push 112 | cd gh-pages 113 | # setup git 114 | git config --local user.email "actions@github.com" 115 | git config --local user.name "GitHub Actions" 116 | git add -A . 117 | git commit --allow-empty -m "[Github Actions] render website (via ${{ github.sha }})" 118 | git push origin gh-pages 119 | # return 120 | cd .. 121 | 122 | - run: make lesson-check-all 123 | if: always() 124 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *~ 3 | .DS_Store 4 | .ipynb_checkpoints 5 | .sass-cache 6 | .jekyll-cache/ 7 | .jekyll-metadata 8 | __pycache__ 9 | _site 10 | .Rproj.user 11 | .Rhistory 12 | .RData 13 | .bundle/ 14 | .vendor/ 15 | vendor/ 16 | .docker-vendor/ 17 | Gemfile.lock 18 | .*history 19 | -------------------------------------------------------------------------------- /404.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: base 3 | root: . 4 | permalink: 404.html 5 | title: "Page not found" 6 | --- 7 | 8 | # Oops! We cannot find that page. 9 | {: style="text-align: center;"} 10 | 11 | > ## Our apologies! 12 | > 13 | > We cannot seem to find the page you are looking for. 14 | > Try going back to the previous page or 15 | > navigate to any other page using the navigation bar above 16 | > {%- if site.kind == "lesson" -%} or the schedule below {%- endif -%}. 17 | > If you got here by clicking on a link in the 18 | > {%- if site.kind == "lesson" -%} lesson {%- else -%} workshop {%- endif -%}, 19 | > please report this link to the 20 | > {%- if site.kind == "lesson" -%} lesson developers {%- else -%} workshop organizers {%- endif -%}. 21 | {: .caution} 22 | 23 | {% if site.kind == "lesson" %} 24 | {% include syllabus.html %} 25 | {% endif%} 26 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: "Contributor Code of Conduct" 4 | --- 5 | As contributors and maintainers of this project, 6 | we pledge to follow the [Carpentry Code of Conduct][coc]. 7 | 8 | Instances of abusive, harassing, or otherwise unacceptable behavior 9 | may be reported by following our [reporting guidelines][coc-reporting]. 10 | 11 | [coc]: https://docs.carpentries.org/topic_folders/policies/code-of-conduct.html 12 | [coc-reporting]: https://docs.carpentries.org/topic_folders/policies/incident-reporting.html 13 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source 'https://rubygems.org' 4 | 5 | git_source(:github) { |repo_name| "https://github.com/#{repo_name}" } 6 | 7 | # Synchronize with https://pages.github.com/versions 8 | ruby '>=2.7.1' 9 | 10 | gem 'github-pages', group: :jekyll_plugins 11 | 12 | if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.0.0') 13 | gem 'webrick', '>= 1.6.1' 14 | end -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: "Licenses" 4 | root: . 5 | --- 6 | ## Instructional Material 7 | 8 | All Software Carpentry, Data Carpentry, and Library Carpentry instructional material is 9 | made available under the [Creative Commons Attribution 10 | license][cc-by-human]. The following is a human-readable summary of 11 | (and not a substitute for) the [full legal text of the CC BY 4.0 12 | license][cc-by-legal]. 13 | 14 | You are free: 15 | 16 | * to **Share**---copy and redistribute the material in any medium or format 17 | * to **Adapt**---remix, transform, and build upon the material 18 | 19 | for any purpose, even commercially. 20 | 21 | The licensor cannot revoke these freedoms as long as you follow the 22 | license terms. 23 | 24 | Under the following terms: 25 | 26 | * **Attribution**---You must give appropriate credit by: 27 | - mentioning that your work is derived from work that is 28 | Copyright © Software Carpentry, Data Carpentry, Library Carpentry, 29 | or The Carpentries. 30 | - where practical, linking to the respective lesson program website 31 | (https://software-carpentry.org/, https://datacarpentry.org, https://librarycarpentry.org, or 32 | https://carpentries.org), provide a [link to the license][cc-by-human] 33 | - and indicate if changes were made. You may do so in any reasonable manner, but not in any way 34 | that suggests the licensor endorses you or your use. 35 | 36 | **No additional restrictions**---You may not apply legal terms or 37 | technological measures that legally restrict others from doing 38 | anything the license permits. With the understanding that: 39 | 40 | Notices: 41 | 42 | * You do not have to comply with the license for elements of the 43 | material in the public domain or where your use is permitted by an 44 | applicable exception or limitation. 45 | * No warranties are given. The license may not give you all of the 46 | permissions necessary for your intended use. For example, other 47 | rights such as publicity, privacy, or moral rights may limit how you 48 | use the material. 49 | 50 | ## Software 51 | 52 | Except where otherwise noted, the example programs and other software 53 | provided by Software Carpentry and Data Carpentry are made available under the 54 | [OSI][osi]-approved 55 | [MIT license][mit-license]. 56 | 57 | Permission is hereby granted, free of charge, to any person obtaining 58 | a copy of this software and associated documentation files (the 59 | "Software"), to deal in the Software without restriction, including 60 | without limitation the rights to use, copy, modify, merge, publish, 61 | distribute, sublicense, and/or sell copies of the Software, and to 62 | permit persons to whom the Software is furnished to do so, subject to 63 | the following conditions: 64 | 65 | The above copyright notice and this permission notice shall be 66 | included in all copies or substantial portions of the Software. 67 | 68 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 69 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 70 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 71 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 72 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 73 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 74 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 75 | 76 | ## Trademark 77 | 78 | "The Carpentries", "Software Carpentry" and "Data Carpentry" and their respective logos are 79 | registered trademarks of [Community Initiatives][CI]. 80 | 81 | [cc-by-human]: https://creativecommons.org/licenses/by/4.0/ 82 | [cc-by-legal]: https://creativecommons.org/licenses/by/4.0/legalcode 83 | [mit-license]: https://opensource.org/licenses/mit-license.html 84 | [ci]: http://communityin.org/ 85 | [osi]: https://opensource.org 86 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ## ======================================== 2 | ## Commands for both workshop and lesson websites. 3 | 4 | # Settings 5 | MAKEFILES=Makefile $(wildcard *.mk) 6 | JEKYLL=bundle config set --local path .vendor/bundle && bundle install && bundle update && bundle exec jekyll 7 | PARSER=bin/markdown_ast.rb 8 | DST=_site 9 | 10 | # Find Docker 11 | DOCKER := $(shell which docker 2>/dev/null) 12 | 13 | # Check Python 3 is installed and determine if it's called via python3 or python 14 | # (https://stackoverflow.com/a/4933395) 15 | PYTHON3_EXE := $(shell which python3 2>/dev/null) 16 | ifneq (, $(PYTHON3_EXE)) 17 | ifeq (,$(findstring Microsoft/WindowsApps/python3,$(subst \,/,$(PYTHON3_EXE)))) 18 | PYTHON := $(PYTHON3_EXE) 19 | endif 20 | endif 21 | 22 | ifeq (,$(PYTHON)) 23 | PYTHON_EXE := $(shell which python 2>/dev/null) 24 | ifneq (, $(PYTHON_EXE)) 25 | PYTHON_VERSION_FULL := $(wordlist 2,4,$(subst ., ,$(shell python --version 2>&1))) 26 | PYTHON_VERSION_MAJOR := $(word 1,${PYTHON_VERSION_FULL}) 27 | ifeq (3, ${PYTHON_VERSION_MAJOR}) 28 | PYTHON := $(PYTHON_EXE) 29 | else 30 | PYTHON_NOTE = "Your system does not appear to have Python 3 installed." 31 | endif 32 | else 33 | PYTHON_NOTE = "Your system does not appear to have any Python installed." 34 | endif 35 | endif 36 | 37 | 38 | # Default target 39 | .DEFAULT_GOAL := commands 40 | 41 | ## I. Commands for both workshop and lesson websites 42 | ## ================================================= 43 | 44 | .PHONY: site docker-serve repo-check clean clean-rmd 45 | 46 | ## * serve : render website and run a local server 47 | serve : lesson-md index.md 48 | ${JEKYLL} serve 49 | 50 | ## * site : build website but do not run a server 51 | site : lesson-md index.md 52 | ${JEKYLL} build 53 | 54 | ## * docker-serve : use Docker to serve the site 55 | docker-serve : 56 | ifeq (, $(DOCKER)) 57 | $(error Your system does not appear to have Docker installed) 58 | else 59 | @$(DOCKER) pull carpentries/lesson-docker:latest 60 | @$(DOCKER) run --rm -it \ 61 | -v $${PWD}:/home/rstudio \ 62 | -p 4000:4000 \ 63 | -p 8787:8787 \ 64 | -e USERID=$$(id -u) \ 65 | -e GROUPID=$$(id -g) \ 66 | carpentries/lesson-docker:latest 67 | endif 68 | 69 | ## * repo-check : check repository settings 70 | repo-check : python 71 | @${PYTHON} bin/repo_check.py -s . 72 | 73 | ## * clean : clean up junk files 74 | clean : 75 | @rm -rf ${DST} 76 | @rm -rf .sass-cache 77 | @rm -rf bin/__pycache__ 78 | @rm -rf .vendor 79 | @rm -rf .bundle 80 | @rm -f Gemfile.lock 81 | @find . -name .DS_Store -exec rm {} \; 82 | @find . -name '*~' -exec rm {} \; 83 | @find . -name '*.pyc' -exec rm {} \; 84 | 85 | ## * clean-rmd : clean intermediate R files (that need to be committed to the repo) 86 | clean-rmd : 87 | @rm -rf ${RMD_DST} 88 | @rm -rf fig/rmd-* 89 | 90 | 91 | ## 92 | ## II. Commands specific to workshop websites 93 | ## ================================================= 94 | 95 | .PHONY : workshop-check 96 | 97 | ## * workshop-check : check workshop homepage 98 | workshop-check : python 99 | @${PYTHON} bin/workshop_check.py . 100 | 101 | 102 | ## 103 | ## III. Commands specific to lesson websites 104 | ## ================================================= 105 | 106 | .PHONY : lesson-check lesson-md lesson-files lesson-fixme install-rmd-deps 107 | 108 | # RMarkdown files 109 | RMD_SRC = $(wildcard _episodes_rmd/*.Rmd) 110 | RMD_DST = $(patsubst _episodes_rmd/%.Rmd,_episodes/%.md,$(RMD_SRC)) 111 | 112 | # Lesson source files in the order they appear in the navigation menu. 113 | MARKDOWN_SRC = \ 114 | index.md \ 115 | CODE_OF_CONDUCT.md \ 116 | setup.md \ 117 | $(sort $(wildcard _episodes/*.md)) \ 118 | reference.md \ 119 | $(sort $(wildcard _extras/*.md)) \ 120 | LICENSE.md 121 | 122 | # Generated lesson files in the order they appear in the navigation menu. 123 | HTML_DST = \ 124 | ${DST}/index.html \ 125 | ${DST}/conduct/index.html \ 126 | ${DST}/setup/index.html \ 127 | $(patsubst _episodes/%.md,${DST}/%/index.html,$(sort $(wildcard _episodes/*.md))) \ 128 | ${DST}/reference.html \ 129 | $(patsubst _extras/%.md,${DST}/%/index.html,$(sort $(wildcard _extras/*.md))) \ 130 | ${DST}/license/index.html 131 | 132 | ## * install-rmd-deps : Install R packages dependencies to build the RMarkdown lesson 133 | install-rmd-deps: 134 | @${SHELL} bin/install_r_deps.sh 135 | 136 | ## * lesson-md : convert Rmarkdown files to markdown 137 | lesson-md : ${RMD_DST} 138 | 139 | _episodes/%.md: _episodes_rmd/%.Rmd install-rmd-deps 140 | @mkdir -p _episodes 141 | @$(SHELL) bin/knit_lessons.sh $< $@ 142 | 143 | ## * lesson-check : validate lesson Markdown 144 | lesson-check : python lesson-fixme 145 | @${PYTHON} bin/lesson_check.py -s . -p ${PARSER} -r _includes/links.md 146 | 147 | ## * lesson-check-all : validate lesson Markdown, checking line lengths and trailing whitespace 148 | lesson-check-all : python 149 | @${PYTHON} bin/lesson_check.py -s . -p ${PARSER} -r _includes/links.md -l -w --permissive 150 | 151 | ## * unittest : run unit tests on checking tools 152 | unittest : python 153 | @${PYTHON} bin/test_lesson_check.py 154 | 155 | ## * lesson-files : show expected names of generated files for debugging 156 | lesson-files : 157 | @echo 'RMD_SRC:' ${RMD_SRC} 158 | @echo 'RMD_DST:' ${RMD_DST} 159 | @echo 'MARKDOWN_SRC:' ${MARKDOWN_SRC} 160 | @echo 'HTML_DST:' ${HTML_DST} 161 | 162 | ## * lesson-fixme : show FIXME markers embedded in source files 163 | lesson-fixme : 164 | @grep --fixed-strings --word-regexp --line-number --no-messages FIXME ${MARKDOWN_SRC} || true 165 | 166 | ## 167 | ## IV. Auxililary (plumbing) commands 168 | ## ================================================= 169 | 170 | .PHONY : commands python 171 | 172 | ## * commands : show all commands. 173 | commands : 174 | @sed -n -e '/^##/s|^##[[:space:]]*||p' $(MAKEFILE_LIST) 175 | 176 | python : 177 | ifeq (, $(PYTHON)) 178 | $(error $(PYTHON_NOTE)) 179 | else 180 | @: 181 | endif 182 | 183 | index.md : 184 | ifeq (, $(wildcard index.md)) 185 | $(error index.md not found) 186 | else 187 | @: 188 | endif 189 | -------------------------------------------------------------------------------- /_episodes/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/_episodes/.gitkeep -------------------------------------------------------------------------------- /_episodes_rmd/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/_episodes_rmd/.gitkeep -------------------------------------------------------------------------------- /_episodes_rmd/data/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/_episodes_rmd/data/.gitkeep -------------------------------------------------------------------------------- /_extras/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/_extras/.gitkeep -------------------------------------------------------------------------------- /_includes/aio-script.md: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | As a maintainer, you don't need to edit this file. 3 | If you notice that something doesn't work, please 4 | open an issue: https://github.com/carpentries/styles/issues/new 5 | {% endcomment %} 6 | 7 | {% include manual_episode_order.html %} 8 | 9 | {% for lesson_episode in lesson_episodes %} 10 | 11 | {% if site.episode_order %} 12 | {% assign e = site.episodes | where: "slug", lesson_episode | first %} 13 | {% else %} 14 | {% assign e = lesson_episode %} 15 | {% endif %} 16 | 17 |

{{ e.title }}

18 | 19 | {% include episode_overview.html teaching_time=e.teaching exercise_time=e.exercises episode_questions=e.questions episode_objectives=e.objectives %} 20 | 21 | {{ e.content }} 22 | 23 | {% include episode_keypoints.html episode_keypoints=e.keypoints %} 24 |
25 | {% endfor %} 26 | -------------------------------------------------------------------------------- /_includes/all_keypoints.html: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | Display key points of all episodes for reference. 3 | {% endcomment %} 4 | 5 | {% include base_path.html %} 6 | {% include manual_episode_order.html %} 7 | 8 |

Key Points

9 | 10 | {% for lesson_episode in lesson_episodes %} 11 | {% if site.episode_order %} 12 | {% assign episode = site.episodes | where: "slug", lesson_episode | first %} 13 | {% else %} 14 | {% assign episode = lesson_episode %} 15 | {% endif %} 16 | {% unless episode.break %} 17 | 18 | 21 | 28 | 29 | {% endunless %} 30 | {% endfor %} 31 |
19 | {{ episode.title }} 20 | 22 |
    23 | {% for keypoint in episode.keypoints %} 24 |
  • {{ keypoint|markdownify }}
  • 25 | {% endfor %} 26 |
27 |
32 | -------------------------------------------------------------------------------- /_includes/base_path.html: -------------------------------------------------------------------------------- 1 | {%- comment -%} 2 | When the website is built by GitHub Pages, 3 | 'site.url' is set to 'https://username.github.io' 4 | 'site.baseurl' is set to '/lesson-name' 5 | 6 | When we start a local server using `jekyll serve`, 7 | 'site.url' is set to 'http://localhost:4000' and 8 | 'site.baseurl' is empty. 9 | 10 | In both of the above cases we set 'relative_root_path' to 'site.baseurl'. 11 | 12 | When we build a website locally with `jekyll build`, 13 | both 'site.url' and 'site.baseurl' are empty. 14 | This case is handled by the last 'else' in the code below. 15 | The logic there follows the (adapted) instructions found at: 16 | https://ricostacruz.com/til/relative-paths-in-jekyll 17 | 18 | `page.url` gives the URL of the current page with a leading /: 19 | 20 | - when the URL ends with an extension (e.g., /foo/bar.html), 21 | we can get the 'depth' of the page by counting the number of 22 | forward slashes ('/') and subtracting 1 23 | - when the URL ends with a forward slash (e.g. /foo/bar/), 24 | we can get the depth of the page by counting the number of / 25 | {%- endcomment -%} 26 | 27 | {% if site.url %} 28 | {% assign relative_root_path = site.baseurl %} 29 | {% else %} 30 | {% assign last_char = page.url | slice: -1 %} 31 | {% if last_char == "/" %} 32 | {% assign offset = 0 %} 33 | {% else %} 34 | {% assign offset = 1 %} 35 | {% endif %} 36 | {% assign depth = page.url | split: '/' | size | minus: offset %} 37 | {% if depth <= 1 %}{% assign relative_root_path = '.' %} 38 | {% elsif depth == 2 %}{% assign relative_root_path = '..' %} 39 | {% else %}{% capture relative_root_path %}..{% for i in (3..depth) %}/..{% endfor %}{% endcapture %} 40 | {% endif %} 41 | {% endif %} 42 | -------------------------------------------------------------------------------- /_includes/carpentries.html: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | General description of Software, Data, and Library Carpentry. 3 | {% endcomment %} 4 | 5 | {% include base_path.html %} 6 | 7 |
8 |
9 | The Carpentries logo 10 |
11 |
12 |

The Carpentries comprises 13 | Software Carpentry, Data Carpentry, and Library Carpentry communities of Instructors, Trainers, 14 | Maintainers, helpers, and supporters who share a mission to teach 15 | foundational coding and data science skills to researchers and people 16 | working in library- and information-related roles. In January, 17 | 2018, The Carpentries was formed by the merger of Software Carpentry and 18 | Data Carpentry. Library Carpentry became an official Carpentries Lesson Program in November 2018.

19 | 20 |

While individual lessons and workshops continue to be run under each 21 | lesson project, The Carpentries provide overall staffing and governance, as 22 | well as support for assessment, instructor training and mentoring. 23 | Memberships are joint, and the Carpentries project maintains a shared Code 24 | of Conduct. The Carpentries is a fiscally sponsored project of Community 25 | Initiatives, a registered 501(c)3 non-profit based in California, USA.

26 |
27 |
28 |
29 |
30 | Software Carpentry logo 31 |
32 |
33 |

Since 1998, Software Carpentry has 34 | been teaching researchers across all disciplines the foundational coding 35 | skills they need to get more done in less time and with less pain. Its 36 | volunteer instructors have run hundreds of events for thousands of learners 37 | around the world. Now that all research involves some degree of 38 | computational work, whether with big data, cloud computing, or simple task 39 | automation, these skills are needed more than ever.

40 |
41 |
42 |
43 |
44 |
45 | Data Carpentry logo 46 |
47 |
48 |

Data Carpentry develops and teaches 49 | workshops on the fundamental data skills needed to conduct research. Its 50 | target audience is researchers who have little to no prior computational 51 | experience, and its lessons are domain specific, building on learners' 52 | existing knowledge to enable them to quickly apply skills learned to their 53 | own research. Data Carpentry workshops take researchers through the entire 54 | data life cycle.

55 |
56 |
57 |
58 |
59 |
60 | Library Carpentry logo 61 |
62 |
63 |

Library Carpentry develops lessons and 64 | teaches workshops for and with people working in library- and 65 | information-related roles. Its goal is to create an on-ramp to empower this 66 | community to use software and data in their own work, as well as be 67 | advocates for and train others in efficient, effective and reproducible data 68 | and software practices.

69 |
70 |
71 | -------------------------------------------------------------------------------- /_includes/check_transition_variables.html: -------------------------------------------------------------------------------- 1 | {% assign date = include.need_transition_date %} 2 | 3 | {% if date == "true" %} 4 | {% unless site.transition_date_prebeta %} 5 |
6 | you need to specify the variable transition_date_prebeta 7 | in _config.yml. 8 |
9 | {% endunless %} 10 | {% unless site.transition_date_beta %} 11 |
12 | you need to specify the variable transition_date_beta 13 | in _config.yml. 14 |
15 | {% endunless %} 16 | {% unless site.transition_date_prerelease %} 17 |
18 | you need to specify the variable transition_date_prerelease 19 | in _config.yml. 20 |
21 | {% endunless %} 22 | {% endif %} 23 | -------------------------------------------------------------------------------- /_includes/dc/intro.html: -------------------------------------------------------------------------------- 1 |

2 | Data Carpentry 3 | aims to help researchers get their work done 4 | in less time and with less pain 5 | by teaching them basic research computing skills. 6 | This hands-on workshop will cover basic concepts and tools, 7 | including program design, version control, data management, 8 | and task automation. 9 | Participants will be encouraged to help one another 10 | and to apply what they have learned to their own research problems. 11 |

12 |

13 | 14 | For more information on what we teach and why, 15 | please see our paper 16 | "Best Practices for Scientific Computing". 17 | 18 |

19 | -------------------------------------------------------------------------------- /_includes/dc/schedule.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Day 1

4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
09:00 Automating tasks with the Unix shell
10:30 Coffee
12:00 Lunch break
13:00 Building programs with Python
14:30 Coffee
16:00 Wrap-up
12 |
13 |
14 |

Day 2

15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 |
09:00 Version control with Git
10:30 Coffee
12:00 Lunch break
13:00 Managing data with SQL
14:30 Coffee
16:00 Wrap-up
23 |
24 |
25 | -------------------------------------------------------------------------------- /_includes/dc/syllabus.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

The Unix Shell

4 | 13 |
14 |
15 |

Programming in Python

16 | 26 |
27 | 40 | 53 |
54 | 55 |
56 |
57 |

Version Control with Git

58 | 69 |
70 | 86 |
87 |

Open Refine

88 | 95 |
96 |
97 | -------------------------------------------------------------------------------- /_includes/dc/who.html: -------------------------------------------------------------------------------- 1 |

2 | Who: 3 | The course is aimed at graduate students and other researchers. 4 | 5 | You don't need to have any previous knowledge of the tools 6 | that will be presented at the workshop. 7 | 8 |

9 | -------------------------------------------------------------------------------- /_includes/episode_break.html: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | Display a break's timings in a box similar to a learning episode's. 3 | {% endcomment %} 4 |
5 |

Overview

6 | 7 |
8 |
9 | Break: {{ page.break }} min 10 |
11 |
12 |
13 |
14 | 15 |
16 | -------------------------------------------------------------------------------- /_includes/episode_keypoints.html: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | Display key points for an episode. 3 | {% endcomment %} 4 | 5 | {% if page.keypoints == nil %} 6 | {% assign episode_keypoints = include.episode_keypoints %} 7 | {% else %} 8 | {% assign episode_keypoints = page.keypoints %} 9 | {% endif %} 10 | 11 |
12 |

Key Points

13 | 18 |
19 | -------------------------------------------------------------------------------- /_includes/episode_navbar.html: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | For some reason, the relative_root_path seems out of scope in this file, so we 3 | need to re-assign it here 4 | {% endcomment %} 5 | 6 | {% include base_path.html %} 7 | 8 | {% comment %} 9 | Navigation bar for an episode. 10 | {% endcomment %} 11 | 12 | {% include manual_episode_order.html %} 13 | {% comment %} 14 | 'previous_episode' and 'next_episodes' are defined in 'manual_episode_order.html'. 15 | These replace 'page.previous' and 'page.next' objects, correspondingly. 16 | {% endcomment %} 17 | 18 |
19 |
20 |

21 | {% if previous_episode %} 22 | previous episode 23 | {% else %} 24 | lesson home 25 | {% endif %} 26 |

27 |
28 |
29 | {% if include.episode_navbar_title %} 30 |

{{ site.title }}

31 | {% endif %} 32 |
33 |
34 |

35 | {% if next_episode %} 36 | next episode 37 | {% else %} 38 | lesson home 39 | {% endif %} 40 |

41 |
42 |
43 | -------------------------------------------------------------------------------- /_includes/episode_overview.html: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | Display episode's timings and learning objectives. 3 | 4 | Regarding the `if page.*** == nil` below: 5 | all-in-one page combines all episodes into one. 6 | It, therefore, does not define its own objectives, exercises, 7 | and questions, which 'normal' episodes define in the front matter. 8 | 9 | To display episodes' teaching and exercise times, as well as episode 10 | questions and objectives, we pass them as parameters to the Liquid's 11 | `include` statement when we generate the page: 12 | 13 | include episode_overview.html teaching_time=e.teaching ... 14 | 15 | Here we obtain the information we need either from the episode itself or 16 | from the parameters passed in. 17 | {% endcomment %} 18 | 19 | {% if page.teaching == nil %} 20 | {% assign teaching_time = include.teaching_time %} 21 | {% else %} 22 | {% assign teaching_time = page.teaching %} 23 | {% endif %} 24 | 25 | {% if page.exercises == nil %} 26 | {% assign exercise_time = include.exercise_time %} 27 | {% else %} 28 | {% assign exercise_time = page.exercises %} 29 | {% endif %} 30 | 31 | {% if page.questions == nil %} 32 | {% assign episode_questions = include.episode_questions %} 33 | {% else %} 34 | {% assign episode_questions = page.questions %} 35 | {% endif %} 36 | 37 | {% if page.objectives == nil %} 38 | {% assign episode_objectives = include.episode_objectives %} 39 | {% else %} 40 | {% assign episode_objectives = page.objectives %} 41 | {% endif %} 42 | 43 | 44 |
45 |

Overview

46 | 47 |
48 |
49 | Teaching: {{ teaching_time }} min 50 |
51 | Exercises: {{ exercise_time }} min 52 |
53 |
54 | Questions 55 |
    56 | {% for question in episode_questions %} 57 |
  • {{ question|markdownify }}
  • 58 | {% endfor %} 59 |
60 |
61 |
62 | 63 |
64 |
65 |
66 |
67 | Objectives 68 |
    69 | {% for objective in episode_objectives %} 70 |
  • {{ objective|markdownify }}
  • 71 | {% endfor %} 72 |
73 |
74 |
75 | 76 |
77 | -------------------------------------------------------------------------------- /_includes/episode_title.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |

{{ page.title }}

6 |
7 |
8 |
9 |
10 | -------------------------------------------------------------------------------- /_includes/favicons.html: -------------------------------------------------------------------------------- 1 | {% assign favicon_url = relative_root_path | append: '/assets/favicons/' | append: site.carpentry %} 2 | 3 | {% if site.carpentry == 'swc' %} 4 | {% assign carpentry = 'Software Carpentry' %} 5 | {% elsif site.carpentry == 'dc' %} 6 | {% assign carpentry = 'Data Carpentry' %} 7 | {% elsif site.carpentry == 'lc' %} 8 | {% assign carpentry = 'Library Carpentry' %} 9 | {% elsif site.carpentry == 'cp' %} 10 | {% assign carpentry = 'The Carpentries' %} 11 | {% endif %} 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /_includes/gh_variables.html: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | When rendering websites locally, `site.github.url` doesn't get resolved properly 3 | unless a GitHub Personal Access Token is set up and available in the 4 | environment. This leads to warnings and errors when trying to serve the site 5 | locally. To work around this, we use the `jekyll.environment` variable which is 6 | set to `development` when rendering the site locally, and set to `production` on 7 | GitHub where `site.github.url` is defined. 8 | {% endcomment %} 9 | 10 | {% if jekyll.environment == "production" %} 11 | 12 | {% comment %} 13 | First, get the name of the repository 14 | {% endcomment %} 15 | {% assign repo_name = site.github.repository_name %} 16 | 17 | {% comment %} 18 | `site.github.public_repositories` contains comprehensive information for all public repositories for the organization. We use `where` to extract the part 19 | of the metadata that is relevant to the present repository. 20 | {% endcomment %} 21 | {% assign repo_info = site.github.public_repositories | where: "name", repo_name %} 22 | 23 | {% comment %} 24 | Now, we can extract the default branch for the repo 25 | {% endcomment %} 26 | {% assign default_branch = repo_info[0].default_branch %} 27 | 28 | {% comment %} 29 | Other variables requested by the template 30 | {% endcomment %} 31 | {% assign repo_url = site.github.repository_url %} 32 | {% assign search_domain_url = site.github.url %} 33 | {% assign project_title = site.github.project_title %} 34 | {% assign source_branch = site.github.source.branch %} 35 | 36 | {% elsif jekyll.environment == "development" %} 37 | 38 | {% assign repo_name = "" %} 39 | {% assign repo_url = "" %} 40 | {% assign default_branch = "" %} 41 | {% assign search_domain_url = "" %} 42 | {% assign project_title = "" %} 43 | {% assign source_branch = "" %} 44 | 45 | {% endif %} 46 | -------------------------------------------------------------------------------- /_includes/javascript.html: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | JavaScript used in lesson and workshop pages. 3 | {% endcomment %} 4 | 5 | 6 | 7 | 8 | {% if site.kind == "lesson" %} 9 | 10 | 27 | 28 | {% endif %} 29 | 30 | {% if page.math %} 31 | 32 | 43 | 44 | {% endif %} 45 | 46 | {%- comment -%} 47 | AnchorJS: A JavaScript utility for adding deep anchor links 48 | https://github.com/bryanbraun/anchorjs 49 | https://cdn.jsdelivr.net/npm/anchor-js/anchor.min.js 50 | {%- endcomment -%} 51 | 52 | 53 | 56 | -------------------------------------------------------------------------------- /_includes/lc/intro.html: -------------------------------------------------------------------------------- 1 |

2 | Library Carpentry 3 | is made by people working in library- and information-related roles to help you: 4 |

5 | 12 |

13 | 14 | Library Carpentry introduces you to the fundamentals of computing 15 | and provides you with a platform for further self-directed learning. 16 | For more information on what we teach and why, please see our paper 17 | "Library Carpentry: software skills training for library professionals". 18 | 19 |

20 | -------------------------------------------------------------------------------- /_includes/lc/schedule.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Day 1

4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
09:00 Data Intro for Librarians
10:30 Coffee
12:00 Lunch break
13:00 Shell Lessons for Libraries
14:30 Coffee
16:00 Wrap-up
12 |
13 |
14 |

Day 2

15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 |
09:00 Git Intro for Librarians
10:30 Coffee
12:00 Lunch break
13:00 OpenRefine for Librarians
14:30 Coffee
16:00 Wrap-up
23 |
24 |
25 | -------------------------------------------------------------------------------- /_includes/lc/syllabus.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Data Intro

4 | 13 |
14 |
15 |

The Unix Shell

16 | 24 |
25 | 26 |
27 | 28 |
29 |
30 |

Version Control with Git

31 | 40 |
41 |
42 |
43 |

Open Refine

44 |
    45 |
  • Introduction to OpenRefine
  • 46 |
  • Importing data
  • 47 |
  • Basic functions
  • 48 |
  • Advanced Functions
  • 49 |
  • Reference...
  • 50 |
51 |
52 |
53 |
54 | 70 | -------------------------------------------------------------------------------- /_includes/lc/who.html: -------------------------------------------------------------------------------- 1 |

2 | Who: 3 | The course is for people working in library- and information-related roles. 4 | 5 | You don't need to have any previous knowledge of the tools that 6 | will be presented at the workshop. 7 | 8 |

9 | -------------------------------------------------------------------------------- /_includes/lesson_footer.html: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | Footer for lesson pages. 3 | {% endcomment %} 4 | 5 | {% include gh_variables.html %} 6 | 7 | 58 | -------------------------------------------------------------------------------- /_includes/life_cycle.html: -------------------------------------------------------------------------------- 1 | 2 | {% if site.life_cycle == "pre-alpha" %} 3 | 4 |
5 |
6 | This lesson is still being designed and assembled (Pre-Alpha version) 7 |
8 |
9 | 10 | 11 | {% elsif site.life_cycle == "alpha" %} 12 | 13 |
14 |
15 | This lesson is in the early stages of development (Alpha version) 16 |
17 |
18 | 19 | 20 | {% elsif site.life_cycle == "beta" %} 21 | 22 |
23 |
24 | This lesson is being piloted (Beta version) 25 |
26 |
27 | 28 | {% elsif site.life_cycle == "stable" %} 29 | 30 | {% comment %} 31 | We do not do anything special for lessons in stable 32 | {% endcomment %} 33 | 34 | 35 | {% comment %} 36 | Below we cover the 2 phases of lesson transition towards the Carpentries Workbench: 37 | Variables needed: 38 | - transition_date_prebeta: the date of the prebeta stage 39 | - transition_date_beta: the date of the beta stage 40 | - transition_date_prerelease: the date of the prerelease stage 41 | 42 | - transition-step-1: We notify that there is a snapshot of the lesson available for testing, and that it will supersede this version. 43 | - transition-step-2 We indicate that this version of the lesson is a snapshot and a new version of the lesson is avaiable and will supersede this version at a given date. 44 | {% endcomment %} 45 | 46 | {% elsif site.life_cycle == "transition-step-1" %} 47 | {% include check_transition_variables.html need_transition_date = 'true' %} 48 | 49 |
50 | A snapshot of this lesson from {{ site.transition_date_prebeta }} is being tested on 51 | The Carpentries Workbench: 52 | https://preview.carpentries.org/{{ repo_name }}. 53 |
54 | The Workbench version of this lesson will become default on {{ site.transition_date_prerelease }}. 55 | 58 |
59 | 60 | {% elsif site.life_cycle == "transition-step-2" %} 61 | {% include check_transition_variables.html need_transition_date = 'true' %} 62 | 63 | 73 | 74 | {% endif %} 75 | 76 | 77 | 78 | {% comment %} 79 | For Carpentries Lab lessons we add a banner about the review status 80 | {% endcomment %} 81 | 82 | {% if site.carpentry == "lab" %} 83 | {% if site.doi contains "zenodo" %}{% assign listing=" on Zenodo" %} 84 | {% elsif site.doi contains "jose" %}{% assign listing=" in JOSE" %} 85 | {% else %}{% assign listing="none" %} 86 | {% endif %} 87 | 88 |
89 |
90 | This lesson has passed peer-review! {% if site.doi != "" %}See the publication{{ listing }}.{% endif %} 91 |
92 |
93 | {% endif %} 94 | -------------------------------------------------------------------------------- /_includes/links.md: -------------------------------------------------------------------------------- 1 | {% include base_path.html %} 2 | [cc-by-human]: https://creativecommons.org/licenses/by/4.0/ 3 | [cc-by-legal]: https://creativecommons.org/licenses/by/4.0/legalcode 4 | [ci]: http://communityin.org/ 5 | [coc-reporting]: https://docs.carpentries.org/topic_folders/policies/incident-reporting.html 6 | [coc]: https://docs.carpentries.org/topic_folders/policies/code-of-conduct.html 7 | [concept-maps]: https://carpentries.github.io/instructor-training/05-memory/ 8 | [contrib-covenant]: https://contributor-covenant.org/ 9 | [contributing]: {{ repo_url }}/blob/{{ source_branch }}/CONTRIBUTING.md 10 | [cran-checkpoint]: https://cran.r-project.org/package=checkpoint 11 | [cran-knitr]: https://cran.r-project.org/package=knitr 12 | [cran-stringr]: https://cran.r-project.org/package=stringr 13 | [dc-lessons]: http://www.datacarpentry.org/lessons/ 14 | [email]: mailto:team@carpentries.org 15 | [github-importer]: https://import2.github.com/ 16 | [importer]: https://github.com/new/import 17 | [jekyll-collection]: https://jekyllrb.com/docs/collections/ 18 | [jekyll-install]: https://jekyllrb.com/docs/installation/ 19 | [jekyll-windows]: http://jekyll-windows.juthilo.com/ 20 | [jekyll]: https://jekyllrb.com/ 21 | [jupyter]: https://jupyter.org/ 22 | [kramdown]: https://kramdown.gettalong.org/ 23 | [lc-lessons]: https://librarycarpentry.org/lessons/ 24 | [lesson-aio]: {{ relative_root_path }}{% link aio.md %} 25 | [lesson-coc]: {{ relative_root_path }}{% link CODE_OF_CONDUCT.md %} 26 | [lesson-example]: https://carpentries.github.io/lesson-example/ 27 | [lesson-license]: {{ relative_root_path }}{% link LICENSE.md %} 28 | [lesson-mainpage]: {{ relative_root_path }}{% link index.md %} 29 | [lesson-reference]: {{ relative_root_path }}{% link reference.md %} 30 | [lesson-setup]: {{ relative_root_path }}{% link setup.md %} 31 | [mit-license]: https://opensource.org/licenses/mit-license.html 32 | [morea]: https://morea-framework.github.io/ 33 | [numfocus]: https://numfocus.org/ 34 | [osi]: https://opensource.org 35 | [pandoc]: https://pandoc.org/ 36 | [paper-now]: https://github.com/PeerJ/paper-now 37 | [python-gapminder]: https://swcarpentry.github.io/python-novice-gapminder/ 38 | [pyyaml]: https://pypi.org/project/PyYAML/ 39 | [r-markdown]: https://rmarkdown.rstudio.com/ 40 | [rstudio]: https://www.rstudio.com/ 41 | [ruby-install-guide]: https://www.ruby-lang.org/en/downloads/ 42 | [ruby-installer]: https://rubyinstaller.org/ 43 | [rubygems]: https://rubygems.org/pages/download/ 44 | [styles]: https://github.com/carpentries/styles/ 45 | [swc-lessons]: https://software-carpentry.org/lessons/ 46 | [swc-releases]: https://github.com/swcarpentry/swc-releases 47 | [training]: https://carpentries.github.io/instructor-training/ 48 | [workshop-repo]: {{ site.workshop_repo }} 49 | [yaml]: http://yaml.org/ 50 | -------------------------------------------------------------------------------- /_includes/main_title.html: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | Main title for lesson pages. 3 | {% endcomment %} 4 | 5 | {% include base_path.html %} 6 | 7 | {% if site.kind == "lesson" %} 8 |

{{ site.title }}{% if page.title %}: {{ page.title }}{% endif %}

9 | 10 | {% else %} 11 | 12 |

{{ page.title }}

13 | 14 | {% endif %} 15 | -------------------------------------------------------------------------------- /_includes/manual_episode_order.html: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | This file enables manual episode ordering until 3 | GitHub Pages switches to Jekyll that supports it 4 | without any major hackery. Note, some logic will 5 | be required even when this transition happens 6 | but it will not be as involved as what we have to do 7 | in this file. 8 | 9 | To order lesson episodes or extras manually 10 | (instead of the default alpha-numerical order), 11 | create array variables 'episode_order' and 12 | 'extras_order' in `_config.yml` like so: 13 | 14 | episode_order: 15 | - episodeA 16 | - episodeB 17 | 18 | extras_order: 19 | - extraA 20 | - extraB 21 | 22 | Note that "Reference" page is currently always 23 | added to "Extras" as the first item. 24 | 25 | The main outcomes of the code in this file are: 26 | - 'lesson_episodes' variable that replaces 27 | 'site.episodes' variable when manual episode 28 | order is defined. 29 | - 'lesson_extras' variable that replaces 30 | 'site.extras' variable when manual ordering of 31 | files in '_extras' is used 32 | - 'previous_episode' and 'next_episode' objects 33 | that replace 'page.previous' and 'page.next' variables, 34 | correspondingly, and that have such properties 35 | as 'url' and 'title' and that are used in 36 | 'episode_navbar.html'. 37 | 38 | When episode order is specified manually, the 'lesson_episodes' 39 | variable contains a list of episode names ("slugs", to be precise; 40 | "slug" is the episode name without '.md'). Therefore, when we 41 | iterate over 'lesson_episodes' (in syllabus.html and navbar.html) , 42 | we have to check whether we use manual episode ordering and, if so, 43 | find the corresponding episode object. This is what we do with the 44 | following code in every loop over 'lesson_episodes': 45 | 46 | {% if site.episode_order %} 47 | {% assign episode = site.episodes | where: "slug", lesson_episode | first %} 48 | {% else %} 49 | {% assign episode = lesson_episode %} 50 | {% endif %} 51 | {% endcomment %} 52 | 53 | {% comment %} 54 | Manual ordering of Episodes begins here 55 | {% endcomment %} 56 | 57 | {% if site.episode_order %} 58 | {% assign lesson_episodes = site.episode_order %} 59 | {% else %} 60 | {% assign lesson_episodes = site.episodes %} 61 | {% endif %} 62 | 63 | 64 | {% comment %} 65 | If 'episode_order' is defined, we need to determine 66 | - previous episode object ('previous_episode') 67 | - and next episode object ('next_episode') 68 | {% endcomment %} 69 | 70 | 71 | {% if site.episode_order %} 72 | {% for lesson_episode in lesson_episodes %} 73 | 74 | {% comment %} 75 | We iterate over the specified lesson episodes using 76 | a 'for' loop because we can use 77 | 'forloop.first', 'forloop.last', and 'forloop.index0'. 78 | {% endcomment %} 79 | 80 | {% unless lesson_episode == page.slug %} {% continue %} {% endunless %} 81 | 82 | {% if forloop.first %} 83 | {% assign previous_episode = nil %} 84 | {% else %} 85 | {% assign p_idx = forloop.index0 | minus: 1 %} 86 | {% assign p_name = lesson_episodes[p_idx] %} 87 | {% assign previous_episode = site.episodes | where: "slug", p_name | first %} 88 | {% endif %} 89 | 90 | {% if forloop.last == true %} 91 | {% assign next_episode = nil %} 92 | {% else %} 93 | {% assign n_idx = forloop.index0 | plus: 1 %} 94 | {% assign n_name = lesson_episodes[n_idx] %} 95 | {% assign next_episode = site.episodes | where: "slug", n_name | first %} 96 | {% endif %} 97 | {% endfor %} 98 | {% else %} 99 | {% assign previous_episode = page.previous %} 100 | {% assign next_episode = page.next %} 101 | {% endif %} 102 | 103 | 104 | {% comment %} 105 | Manual ordering of Extras begins here 106 | {% endcomment %} 107 | 108 | {% if site.extras_order %} 109 | {% assign lesson_extras = site.extras_order %} 110 | {% else %} 111 | {% assign lesson_extras = site.extras %} 112 | {% endif %} 113 | 114 | {% comment %} 115 | We do not need to determine "previous" or "next" extra. 116 | {% endcomment %} 117 | -------------------------------------------------------------------------------- /_includes/navbar.html: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | Lesson navigation bar. 3 | {% endcomment %} 4 | 5 | {% include gh_variables.html %} 6 | {% include manual_episode_order.html %} 7 | 8 | 117 | -------------------------------------------------------------------------------- /_includes/sc/intro.html: -------------------------------------------------------------------------------- 1 |

2 | Software Carpentry 3 | aims to help researchers get their work done 4 | in less time and with less pain 5 | by teaching them basic research computing skills. 6 | This hands-on workshop will cover basic concepts and tools, 7 | including program design, version control, data management, 8 | and task automation. 9 | Participants will be encouraged to help one another 10 | and to apply what they have learned to their own research problems. 11 |

12 |

13 | 14 | For more information on what we teach and why, 15 | please see our paper 16 | "Best Practices for Scientific Computing". 17 | 18 |

19 | -------------------------------------------------------------------------------- /_includes/sc/schedule.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Day 1

4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
09:00 Automating tasks with the Unix shell
10:30 Coffee
12:00 Lunch break
13:00 Building programs with Python
14:30 Coffee
16:00 Wrap-up
12 |
13 |
14 |

Day 2

15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 |
09:00 Version control with Git
10:30 Coffee
12:00 Lunch break
13:00 Managing data with SQL
14:30 Coffee
16:00 Wrap-up
23 |
24 |
25 | -------------------------------------------------------------------------------- /_includes/sc/syllabus.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

The Unix Shell

4 | 13 |
14 |
15 |

Programming in Python

16 | 26 |
27 | 40 | 53 |
54 | 55 |
56 |
57 |

Version Control with Git

58 | 69 |
70 | 86 |
87 |

Open Refine

88 | 95 |
96 |
97 | -------------------------------------------------------------------------------- /_includes/sc/who.html: -------------------------------------------------------------------------------- 1 |

2 | Who: 3 | The course is aimed at graduate students and other researchers. 4 | 5 | You don't need to have any previous knowledge of the tools 6 | that will be presented at the workshop. 7 | 8 |

9 | -------------------------------------------------------------------------------- /_includes/syllabus.html: -------------------------------------------------------------------------------- 1 | {% include base_path.html %} 2 | 3 | {% comment %} 4 | Display syllabus in tabular form. 5 | Days are displayed if at least one episode has 'start = true'. 6 | {% endcomment %} 7 | 8 | {% include manual_episode_order.html %} 9 | 10 |
11 |

Schedule

12 | 13 | {% assign lesson_number = 0 %} 14 | {% assign day = 0 %} 15 | {% assign multiday = false %} 16 | {% for lesson_episode in lesson_episodes %} 17 | {% if site.episode_order %} 18 | {% assign episode = site.episodes | where: "slug", lesson_episode | first %} 19 | {% else %} 20 | {% assign episode = lesson_episode %} 21 | {% endif %} 22 | {% if episode.start %}{% assign multiday = true %}{% break %}{% endif %} 23 | {% endfor %} 24 | {% assign current = site.start_time %} 25 | 26 | 27 | 28 | {% if multiday %}{% endif %} 29 | 30 | 31 | 32 | 33 | {% if site.instructor_training %} 34 | 35 | {% if multiday %}{% endif %} 36 | 37 | 38 | 39 | 40 | {% endif %} 41 | {% for lesson_episode in lesson_episodes %} 42 | {% if site.episode_order %} 43 | {% assign episode = site.episodes | where: "slug", lesson_episode | first %} 44 | {% else %} 45 | {% assign episode = lesson_episode %} 46 | {% endif %} 47 | {% if episode.start %} {% comment %} Starting a new day? {% endcomment %} 48 | {% assign day = day | plus: 1 %} 49 | {% if day > 1 %} {% comment %} If about to start day 2 or later, show finishing time for previous day {% endcomment %} 50 | {% assign hours = current | divided_by: 60 %} 51 | {% assign minutes = current | modulo: 60 %} 52 | 53 | {% if multiday %}{% endif %} 54 | 55 | 56 | 57 | 58 | {% endif %} 59 | {% assign current = site.start_time %} {% comment %}Re-set start time of this episode to general daily start time {% endcomment %} 60 | {% endif %} 61 | {% assign hours = current | divided_by: 60 %} 62 | {% assign minutes = current | modulo: 60 %} 63 | 64 | {% if multiday %}{% endif %} 65 | 66 | 70 | 84 | 85 | {% assign current = current | plus: episode.teaching | plus: episode.exercises | plus: episode.break %} 86 | {% endfor %} 87 | {% assign hours = current | divided_by: 60 %} 88 | {% assign minutes = current | modulo: 60 %} 89 | {% if site.instructor_training %} 90 | 91 | {% if multiday %}{% endif %} 92 | 93 | 94 | 95 | 96 | {% assign current = current | plus: 15 %} 97 | {% assign hours = current | divided_by: 60 %} 98 | {% assign minutes = current | modulo: 60 %} 99 | {% endif %} 100 | 101 | {% if multiday %}{% endif %} 102 | 103 | 104 | 105 | 106 |
SetupDownload files required for the lesson
Pre-training surveyPlease fill out our pre-training survey before the start of the course.
{% if hours < 10 %}0{% endif %}{{ hours }}:{% if minutes < 10 %}0{% endif %}{{ minutes }}Finish
{% if episode.start %}Day {{ day }}{% endif %}{% if hours < 10 %}0{% endif %}{{ hours }}:{% if minutes < 10 %}0{% endif %}{{ minutes }} 67 | {% assign lesson_number = lesson_number | plus: 1 %} 68 | {{ lesson_number }}. {{ episode.title }} 69 | 71 | {% if episode.break %} 72 | Break 73 | {% else %} 74 | {% if episode.questions %} 75 | {% for question in episode.questions %} 76 | {{question|markdownify|strip_html}} 77 | {% unless forloop.last %} 78 |
79 | {% endunless %} 80 | {% endfor %} 81 | {% endif %} 82 | {% endif %} 83 |
{% if hours < 10 %}0{% endif %}{{ hours }}:{% if minutes < 10 %}0{% endif +++ %}{{ minutes }}Post-training surveyPlease fill out our post-training survey after the course.
{% if hours < 10 %}0{% endif %}{{ hours }}:{% if minutes < 10 %}0{% endif %}{{ minutes }}Finish
107 | 108 |

109 | The actual schedule may vary slightly depending on the topics and exercises chosen by the instructor. 110 |

111 | 112 |
113 | -------------------------------------------------------------------------------- /_includes/workshop_ad.html: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | Advertising box at the top of a workshop website home page. 3 | {% endcomment %} 4 |
5 |
6 |
7 |

{{page.venue}}

8 |
9 |
10 |

{{page.humandate}}

11 |

{% if page.humantime %}{{page.humantime}}{% endif %}

12 |
13 |
14 |

15 | Instructors: 16 | {% if page.instructor %} 17 | {{page.instructor | join: ', ' %}} 18 | {% else %} 19 | to be announced. 20 | {% endif %} 21 |

22 | {% if page.helper %} 23 |

24 | Helpers: 25 | {{page.helper | join: ', ' %}} 26 |

27 | {% endif %} 28 |
29 |
30 |
31 |
32 |
33 | -------------------------------------------------------------------------------- /_includes/workshop_calendar.html: -------------------------------------------------------------------------------- 1 | Add to your Google Calendar. 2 | -------------------------------------------------------------------------------- /_includes/workshop_footer.html: -------------------------------------------------------------------------------- 1 | {% comment %} 2 | Footer for a standard workshop. 3 | {% endcomment %} 4 | 27 | -------------------------------------------------------------------------------- /_layouts/base.html: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | {% include base_path.html %} 4 | {% include gh_variables.html %} 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | {% if page.math %} 20 | 21 | {% endif %} 22 | 23 | 24 | {% include favicons.html %} 25 | 26 | 27 | 28 | 32 | 33 | 34 | {% if page.title %}{{ page.title }}{% endif %}{% if page.title and site.title %} – {% endif %}{% if site.title %}{{ site.title }}{% endif %} 35 | 36 | 37 | 38 | 39 | 40 | {% include life_cycle.html %} 41 | 42 |
43 | {% include navbar.html %} 44 | {{ content }} 45 | {% if site.kind == "workshop" %} 46 | {% include workshop_footer.html %} 47 | {% else %} 48 | {% include lesson_footer.html %} 49 | {% endif %} 50 |
51 | {% include javascript.html %} 52 | 53 | 54 | -------------------------------------------------------------------------------- /_layouts/break.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: base 3 | --- 4 | {% include episode_navbar.html episode_navbar_title=true %} 5 |
6 | {% include episode_title.html %} 7 | {% include episode_break.html %} 8 | {{content}} 9 |
10 | {% include episode_navbar.html episode_navbar_title=false %} 11 | -------------------------------------------------------------------------------- /_layouts/episode.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: base 3 | --- 4 | {% include episode_navbar.html episode_navbar_title=true %} 5 |
6 | {% include episode_title.html %} 7 | {% include episode_overview.html %} 8 | {{content}} 9 | {% include episode_keypoints.html %} 10 |
11 | {% include episode_navbar.html episode_navbar_title=false %} 12 | -------------------------------------------------------------------------------- /_layouts/lesson.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: base 3 | --- 4 | {% include main_title.html %} 5 |
6 | {{ content }} 7 |
8 | {% include syllabus.html %} 9 | -------------------------------------------------------------------------------- /_layouts/page.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: base 3 | --- 4 | {% include main_title.html %} 5 |
6 | {{content}} 7 |
8 | -------------------------------------------------------------------------------- /_layouts/reference.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: page 3 | title: "Reference" 4 | --- 5 | {% include all_keypoints.html %} 6 | {{content}} 7 | -------------------------------------------------------------------------------- /_layouts/workshop.html: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | {% include base_path.html %} 4 | {% include gh_variables.html %} 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 26 | {% endif %} 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | {% include favicons.html %} 38 | 39 | 40 | 41 | 45 | {{ page.venue }}: {{ page.humandate }} 46 | 47 | 48 |
49 | {% include navbar.html %} 50 | {% include workshop_ad.html %} 51 | {{ content }} 52 | {% include workshop_footer.html %} 53 |
54 | {% include javascript.html %} 55 | 56 | 57 | -------------------------------------------------------------------------------- /aio.md: -------------------------------------------------------------------------------- 1 | --- 2 | permalink: /aio/index.html 3 | --- 4 | 5 | {% comment %} 6 | As a maintainer, you do not need to edit this file. 7 | If you notice that something does not work, please 8 | open an issue: https://github.com/carpentries/styles/issues/new 9 | {% endcomment %} 10 | 11 | {% include base_path.html %} 12 | 13 | {% include aio-script.md %} 14 | -------------------------------------------------------------------------------- /assets/css/syntax.css: -------------------------------------------------------------------------------- 1 | .highlight .hll { background-color: #ffffcc } 2 | .highlight { background: #f8f8f8; } 3 | .highlight .c { color: #387d7d; font-style: italic } /* Comment */ 4 | .highlight .err { border: 1px solid #FF0000 } /* Error */ 5 | .highlight .k { color: #008000; font-weight: bold } /* Keyword */ 6 | .highlight .o { color: #666666 } /* Operator */ 7 | .highlight .ch { color: #387d7d; font-style: italic } /* Comment.Hashbang */ 8 | .highlight .cm { color: #387d7d; font-style: italic } /* Comment.Multiline */ 9 | .highlight .cp { color: #BC7A00 } /* Comment.Preproc */ 10 | .highlight .cpf { color: #387d7d; font-style: italic } /* Comment.PreprocFile */ 11 | .highlight .c1 { color: #387d7d; font-style: italic } /* Comment.Single */ 12 | .highlight .cs { color: #387d7d; font-style: italic } /* Comment.Special */ 13 | .highlight .gd { color: #A00000 } /* Generic.Deleted */ 14 | .highlight .ge { font-style: italic } /* Generic.Emph */ 15 | .highlight .gr { color: #FF0000 } /* Generic.Error */ 16 | .highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ 17 | .highlight .gi { color: #00A000 } /* Generic.Inserted */ 18 | .highlight .go { color: #888888 } /* Generic.Output */ 19 | .highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ 20 | .highlight .gs { font-weight: bold } /* Generic.Strong */ 21 | .highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ 22 | .highlight .gt { color: #0044DD } /* Generic.Traceback */ 23 | .highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */ 24 | .highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */ 25 | .highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */ 26 | .highlight .kp { color: #008000 } /* Keyword.Pseudo */ 27 | .highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */ 28 | .highlight .kt { color: #B00040 } /* Keyword.Type */ 29 | .highlight .m { color: #666666 } /* Literal.Number */ 30 | .highlight .s { color: #BA2121 } /* Literal.String */ 31 | .highlight .na { color: #7D9029 } /* Name.Attribute */ 32 | .highlight .nb { color: #008000 } /* Name.Builtin */ 33 | .highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */ 34 | .highlight .no { color: #880000 } /* Name.Constant */ 35 | .highlight .nd { color: #AA22FF } /* Name.Decorator */ 36 | .highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */ 37 | .highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ 38 | .highlight .nf { color: #0000FF } /* Name.Function */ 39 | .highlight .nl { color: #A0A000 } /* Name.Label */ 40 | .highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ 41 | .highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */ 42 | .highlight .nv { color: #19177C } /* Name.Variable */ 43 | .highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ 44 | .highlight .w { color: #bbbbbb } /* Text.Whitespace */ 45 | .highlight .mb { color: #666666 } /* Literal.Number.Bin */ 46 | .highlight .mf { color: #666666 } /* Literal.Number.Float */ 47 | .highlight .mh { color: #666666 } /* Literal.Number.Hex */ 48 | .highlight .mi { color: #666666 } /* Literal.Number.Integer */ 49 | .highlight .mo { color: #666666 } /* Literal.Number.Oct */ 50 | .highlight .sa { color: #BA2121 } /* Literal.String.Affix */ 51 | .highlight .sb { color: #BA2121 } /* Literal.String.Backtick */ 52 | .highlight .sc { color: #BA2121 } /* Literal.String.Char */ 53 | .highlight .dl { color: #BA2121 } /* Literal.String.Delimiter */ 54 | .highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */ 55 | .highlight .s2 { color: #BA2121 } /* Literal.String.Double */ 56 | .highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ 57 | .highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */ 58 | .highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ 59 | .highlight .sx { color: #008000 } /* Literal.String.Other */ 60 | .highlight .sr { color: #BB6688 } /* Literal.String.Regex */ 61 | .highlight .s1 { color: #BA2121 } /* Literal.String.Single */ 62 | .highlight .ss { color: #19177C } /* Literal.String.Symbol */ 63 | .highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */ 64 | .highlight .fm { color: #0000FF } /* Name.Function.Magic */ 65 | .highlight .vc { color: #19177C } /* Name.Variable.Class */ 66 | .highlight .vg { color: #19177C } /* Name.Variable.Global */ 67 | .highlight .vi { color: #19177C } /* Name.Variable.Instance */ 68 | .highlight .vm { color: #19177C } /* Name.Variable.Magic */ 69 | .highlight .il { color: #666666 } /* Literal.Number.Integer.Long */ 70 | -------------------------------------------------------------------------------- /assets/favicons/cp/apple-touch-icon-114x114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/cp/apple-touch-icon-114x114.png -------------------------------------------------------------------------------- /assets/favicons/cp/apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/cp/apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /assets/favicons/cp/apple-touch-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/cp/apple-touch-icon-144x144.png -------------------------------------------------------------------------------- /assets/favicons/cp/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/cp/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /assets/favicons/cp/apple-touch-icon-57x57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/cp/apple-touch-icon-57x57.png -------------------------------------------------------------------------------- /assets/favicons/cp/apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/cp/apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /assets/favicons/cp/apple-touch-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/cp/apple-touch-icon-72x72.png -------------------------------------------------------------------------------- /assets/favicons/cp/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/cp/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /assets/favicons/cp/favicon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/cp/favicon-128.png -------------------------------------------------------------------------------- /assets/favicons/cp/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/cp/favicon-16x16.png -------------------------------------------------------------------------------- /assets/favicons/cp/favicon-196x196.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/cp/favicon-196x196.png -------------------------------------------------------------------------------- /assets/favicons/cp/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/cp/favicon-32x32.png -------------------------------------------------------------------------------- /assets/favicons/cp/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/cp/favicon-96x96.png -------------------------------------------------------------------------------- /assets/favicons/cp/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/cp/favicon.ico -------------------------------------------------------------------------------- /assets/favicons/cp/mstile-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/cp/mstile-144x144.png -------------------------------------------------------------------------------- /assets/favicons/cp/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/cp/mstile-150x150.png -------------------------------------------------------------------------------- /assets/favicons/cp/mstile-310x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/cp/mstile-310x150.png -------------------------------------------------------------------------------- /assets/favicons/cp/mstile-310x310.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/cp/mstile-310x310.png -------------------------------------------------------------------------------- /assets/favicons/cp/mstile-70x70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/cp/mstile-70x70.png -------------------------------------------------------------------------------- /assets/favicons/dc/apple-touch-icon-114x114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/dc/apple-touch-icon-114x114.png -------------------------------------------------------------------------------- /assets/favicons/dc/apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/dc/apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /assets/favicons/dc/apple-touch-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/dc/apple-touch-icon-144x144.png -------------------------------------------------------------------------------- /assets/favicons/dc/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/dc/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /assets/favicons/dc/apple-touch-icon-57x57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/dc/apple-touch-icon-57x57.png -------------------------------------------------------------------------------- /assets/favicons/dc/apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/dc/apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /assets/favicons/dc/apple-touch-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/dc/apple-touch-icon-72x72.png -------------------------------------------------------------------------------- /assets/favicons/dc/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/dc/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /assets/favicons/dc/favicon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/dc/favicon-128.png -------------------------------------------------------------------------------- /assets/favicons/dc/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/dc/favicon-16x16.png -------------------------------------------------------------------------------- /assets/favicons/dc/favicon-196x196.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/dc/favicon-196x196.png -------------------------------------------------------------------------------- /assets/favicons/dc/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/dc/favicon-32x32.png -------------------------------------------------------------------------------- /assets/favicons/dc/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/dc/favicon-96x96.png -------------------------------------------------------------------------------- /assets/favicons/dc/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/dc/favicon.ico -------------------------------------------------------------------------------- /assets/favicons/dc/mstile-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/dc/mstile-144x144.png -------------------------------------------------------------------------------- /assets/favicons/dc/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/dc/mstile-150x150.png -------------------------------------------------------------------------------- /assets/favicons/dc/mstile-310x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/dc/mstile-310x150.png -------------------------------------------------------------------------------- /assets/favicons/dc/mstile-310x310.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/dc/mstile-310x310.png -------------------------------------------------------------------------------- /assets/favicons/dc/mstile-70x70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/dc/mstile-70x70.png -------------------------------------------------------------------------------- /assets/favicons/lc/apple-touch-icon-114x114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/lc/apple-touch-icon-114x114.png -------------------------------------------------------------------------------- /assets/favicons/lc/apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/lc/apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /assets/favicons/lc/apple-touch-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/lc/apple-touch-icon-144x144.png -------------------------------------------------------------------------------- /assets/favicons/lc/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/lc/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /assets/favicons/lc/apple-touch-icon-57x57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/lc/apple-touch-icon-57x57.png -------------------------------------------------------------------------------- /assets/favicons/lc/apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/lc/apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /assets/favicons/lc/apple-touch-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/lc/apple-touch-icon-72x72.png -------------------------------------------------------------------------------- /assets/favicons/lc/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/lc/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /assets/favicons/lc/favicon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/lc/favicon-128.png -------------------------------------------------------------------------------- /assets/favicons/lc/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/lc/favicon-16x16.png -------------------------------------------------------------------------------- /assets/favicons/lc/favicon-196x196.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/lc/favicon-196x196.png -------------------------------------------------------------------------------- /assets/favicons/lc/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/lc/favicon-32x32.png -------------------------------------------------------------------------------- /assets/favicons/lc/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/lc/favicon-96x96.png -------------------------------------------------------------------------------- /assets/favicons/lc/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/lc/favicon.ico -------------------------------------------------------------------------------- /assets/favicons/lc/mstile-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/lc/mstile-144x144.png -------------------------------------------------------------------------------- /assets/favicons/lc/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/lc/mstile-150x150.png -------------------------------------------------------------------------------- /assets/favicons/lc/mstile-310x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/lc/mstile-310x150.png -------------------------------------------------------------------------------- /assets/favicons/lc/mstile-310x310.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/lc/mstile-310x310.png -------------------------------------------------------------------------------- /assets/favicons/lc/mstile-70x70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/lc/mstile-70x70.png -------------------------------------------------------------------------------- /assets/favicons/swc/apple-touch-icon-114x114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/swc/apple-touch-icon-114x114.png -------------------------------------------------------------------------------- /assets/favicons/swc/apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/swc/apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /assets/favicons/swc/apple-touch-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/swc/apple-touch-icon-144x144.png -------------------------------------------------------------------------------- /assets/favicons/swc/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/swc/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /assets/favicons/swc/apple-touch-icon-57x57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/swc/apple-touch-icon-57x57.png -------------------------------------------------------------------------------- /assets/favicons/swc/apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/swc/apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /assets/favicons/swc/apple-touch-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/swc/apple-touch-icon-72x72.png -------------------------------------------------------------------------------- /assets/favicons/swc/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/swc/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /assets/favicons/swc/favicon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/swc/favicon-128.png -------------------------------------------------------------------------------- /assets/favicons/swc/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/swc/favicon-16x16.png -------------------------------------------------------------------------------- /assets/favicons/swc/favicon-196x196.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/swc/favicon-196x196.png -------------------------------------------------------------------------------- /assets/favicons/swc/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/swc/favicon-32x32.png -------------------------------------------------------------------------------- /assets/favicons/swc/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/swc/favicon-96x96.png -------------------------------------------------------------------------------- /assets/favicons/swc/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/swc/favicon.ico -------------------------------------------------------------------------------- /assets/favicons/swc/mstile-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/swc/mstile-144x144.png -------------------------------------------------------------------------------- /assets/favicons/swc/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/swc/mstile-150x150.png -------------------------------------------------------------------------------- /assets/favicons/swc/mstile-310x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/swc/mstile-310x150.png -------------------------------------------------------------------------------- /assets/favicons/swc/mstile-310x310.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/swc/mstile-310x310.png -------------------------------------------------------------------------------- /assets/favicons/swc/mstile-70x70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/favicons/swc/mstile-70x70.png -------------------------------------------------------------------------------- /assets/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /assets/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /assets/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /assets/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /assets/img/carpentrieslab.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 24 | 46 | 48 | 49 | 51 | image/svg+xml 52 | 54 | 55 | 56 | 57 | 58 | 63 | 66 | 72 | 75 | 80 | 85 | 90 | 95 | 96 | 97 | 104 | 112 | 120 | 128 | 134 | 137 | 142 | 147 | 152 | 157 | 158 | 164 | 167 | 172 | 177 | 182 | 187 | 188 | 194 | 197 | 202 | 207 | 212 | 217 | 218 | 224 | 227 | 232 | 237 | 242 | 247 | 248 | 249 | 250 | -------------------------------------------------------------------------------- /assets/img/cp-logo-blue.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /assets/img/dc-icon-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 16 | 18 | 19 | 21 | image/svg+xml 22 | 24 | 25 | 26 | 27 | 28 | 30 | 54 | 59 | 64 | 69 | 74 | 75 | -------------------------------------------------------------------------------- /assets/img/dc-logo-black.svg: -------------------------------------------------------------------------------- 1 | 2 | 16 | 18 | 19 | 21 | image/svg+xml 22 | 24 | 25 | 26 | 27 | 28 | 30 | 54 | 59 | 64 | 69 | 74 | 75 | -------------------------------------------------------------------------------- /assets/img/lc-icon-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/img/lc-icon-black.png -------------------------------------------------------------------------------- /assets/img/lc-logo-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/img/lc-logo-black.png -------------------------------------------------------------------------------- /assets/img/swc-icon-blue.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /assets/img/swc-logo-blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/img/swc-logo-blue.png -------------------------------------------------------------------------------- /assets/img/swc-logo-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/assets/img/swc-logo-white.png -------------------------------------------------------------------------------- /assets/js/anchor.min.js: -------------------------------------------------------------------------------- 1 | // @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt Expat 2 | // 3 | // AnchorJS - v4.3.1 - 2021-04-17 4 | // https://www.bryanbraun.com/anchorjs/ 5 | // Copyright (c) 2021 Bryan Braun; Licensed MIT 6 | // 7 | // @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt Expat 8 | !function(A,e){"use strict";"function"==typeof define&&define.amd?define([],e):"object"==typeof module&&module.exports?module.exports=e():(A.AnchorJS=e(),A.anchors=new A.AnchorJS)}(this,function(){"use strict";return function(A){function d(A){A.icon=Object.prototype.hasOwnProperty.call(A,"icon")?A.icon:"",A.visible=Object.prototype.hasOwnProperty.call(A,"visible")?A.visible:"hover",A.placement=Object.prototype.hasOwnProperty.call(A,"placement")?A.placement:"right",A.ariaLabel=Object.prototype.hasOwnProperty.call(A,"ariaLabel")?A.ariaLabel:"Anchor",A.class=Object.prototype.hasOwnProperty.call(A,"class")?A.class:"",A.base=Object.prototype.hasOwnProperty.call(A,"base")?A.base:"",A.truncate=Object.prototype.hasOwnProperty.call(A,"truncate")?Math.floor(A.truncate):64,A.titleText=Object.prototype.hasOwnProperty.call(A,"titleText")?A.titleText:""}function w(A){var e;if("string"==typeof A||A instanceof String)e=[].slice.call(document.querySelectorAll(A));else{if(!(Array.isArray(A)||A instanceof NodeList))throw new TypeError("The selector provided to AnchorJS was invalid.");e=[].slice.call(A)}return e}this.options=A||{},this.elements=[],d(this.options),this.isTouchDevice=function(){return Boolean("ontouchstart"in window||window.TouchEvent||window.DocumentTouch&&document instanceof DocumentTouch)},this.add=function(A){var e,t,o,i,n,s,a,c,r,l,h,u,p=[];if(d(this.options),"touch"===(l=this.options.visible)&&(l=this.isTouchDevice()?"always":"hover"),0===(e=w(A=A||"h2, h3, h4, h5, h6")).length)return this;for(null===document.head.querySelector("style.anchorjs")&&((u=document.createElement("style")).className="anchorjs",u.appendChild(document.createTextNode("")),void 0===(A=document.head.querySelector('[rel="stylesheet"],style'))?document.head.appendChild(u):document.head.insertBefore(u,A),u.sheet.insertRule(".anchorjs-link{opacity:0;text-decoration:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}",u.sheet.cssRules.length),u.sheet.insertRule(":hover>.anchorjs-link,.anchorjs-link:focus{opacity:1}",u.sheet.cssRules.length),u.sheet.insertRule("[data-anchorjs-icon]::after{content:attr(data-anchorjs-icon)}",u.sheet.cssRules.length),u.sheet.insertRule('@font-face{font-family:anchorjs-icons;src:url(data:n/a;base64,AAEAAAALAIAAAwAwT1MvMg8yG2cAAAE4AAAAYGNtYXDp3gC3AAABpAAAAExnYXNwAAAAEAAAA9wAAAAIZ2x5ZlQCcfwAAAH4AAABCGhlYWQHFvHyAAAAvAAAADZoaGVhBnACFwAAAPQAAAAkaG10eASAADEAAAGYAAAADGxvY2EACACEAAAB8AAAAAhtYXhwAAYAVwAAARgAAAAgbmFtZQGOH9cAAAMAAAAAunBvc3QAAwAAAAADvAAAACAAAQAAAAEAAHzE2p9fDzz1AAkEAAAAAADRecUWAAAAANQA6R8AAAAAAoACwAAAAAgAAgAAAAAAAAABAAADwP/AAAACgAAA/9MCrQABAAAAAAAAAAAAAAAAAAAAAwABAAAAAwBVAAIAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAMCQAGQAAUAAAKZAswAAACPApkCzAAAAesAMwEJAAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAAAAQAAg//0DwP/AAEADwABAAAAAAQAAAAAAAAAAAAAAIAAAAAAAAAIAAAACgAAxAAAAAwAAAAMAAAAcAAEAAwAAABwAAwABAAAAHAAEADAAAAAIAAgAAgAAACDpy//9//8AAAAg6cv//f///+EWNwADAAEAAAAAAAAAAAAAAAAACACEAAEAAAAAAAAAAAAAAAAxAAACAAQARAKAAsAAKwBUAAABIiYnJjQ3NzY2MzIWFxYUBwcGIicmNDc3NjQnJiYjIgYHBwYUFxYUBwYGIwciJicmNDc3NjIXFhQHBwYUFxYWMzI2Nzc2NCcmNDc2MhcWFAcHBgYjARQGDAUtLXoWOR8fORYtLTgKGwoKCjgaGg0gEhIgDXoaGgkJBQwHdR85Fi0tOAobCgoKOBoaDSASEiANehoaCQkKGwotLXoWOR8BMwUFLYEuehYXFxYugC44CQkKGwo4GkoaDQ0NDXoaShoKGwoFBe8XFi6ALjgJCQobCjgaShoNDQ0NehpKGgobCgoKLYEuehYXAAAADACWAAEAAAAAAAEACAAAAAEAAAAAAAIAAwAIAAEAAAAAAAMACAAAAAEAAAAAAAQACAAAAAEAAAAAAAUAAQALAAEAAAAAAAYACAAAAAMAAQQJAAEAEAAMAAMAAQQJAAIABgAcAAMAAQQJAAMAEAAMAAMAAQQJAAQAEAAMAAMAAQQJAAUAAgAiAAMAAQQJAAYAEAAMYW5jaG9yanM0MDBAAGEAbgBjAGgAbwByAGoAcwA0ADAAMABAAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAH//wAP) format("truetype")}',u.sheet.cssRules.length)),u=document.querySelectorAll("[id]"),t=[].map.call(u,function(A){return A.id}),i=0;i\]./()*\\\n\t\b\v\u00A0]/g,"-").replace(/-{2,}/g,"-").substring(0,this.options.truncate).replace(/^-+|-+$/gm,"").toLowerCase()},this.hasAnchorJSLink=function(A){var e=A.firstChild&&-1<(" "+A.firstChild.className+" ").indexOf(" anchorjs-link "),A=A.lastChild&&-1<(" "+A.lastChild.className+" ").indexOf(" anchorjs-link ");return e||A||!1}}}); 9 | // @license-end -------------------------------------------------------------------------------- /assets/js/katex-auto-render.min.js: -------------------------------------------------------------------------------- 1 | !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("katex")):"function"==typeof define&&define.amd?define(["katex"],t):"object"==typeof exports?exports.renderMathInElement=t(require("katex")):e.renderMathInElement=t(e.katex)}("undefined"!=typeof self?self:this,(function(e){return function(){"use strict";var t={974:function(t){t.exports=e}},r={};function n(e){var a=r[e];if(void 0!==a)return a.exports;var i=r[e]={exports:{}};return t[e](i,i.exports,n),i.exports}n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,{a:t}),t},n.d=function(e,t){for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)};var a={};return function(){n.d(a,{default:function(){return s}});var e=n(974),t=n.n(e),r=function(e,t,r){for(var n=r,a=0,i=e.length;n0&&(a.push({type:"text",data:e.slice(0,n)}),e=e.slice(n));var l=t.findIndex((function(t){return e.startsWith(t.left)}));if(-1===(n=r(t[l].right,e,t[l].left.length)))break;var d=e.slice(0,n+t[l].right.length),s=i.test(d)?d:e.slice(t[l].left.length,n);a.push({type:"math",data:s,rawData:d,display:t[l].display}),e=e.slice(n+t[l].right.length)}return""!==e&&a.push({type:"text",data:e}),a},l=function(e,r){var n=o(e,r.delimiters);if(1===n.length&&"text"===n[0].type)return null;for(var a=document.createDocumentFragment(),i=0;i 0 8 | || $(event.target).filter(".fold-unfold").length > 0; 9 | if (trigger) { 10 | $(">*:not(h2)", this).toggle(400); 11 | $(">h2>span.fold-unfold", this).toggleClass("glyphicon-collapse-down glyphicon-collapse-up"); 12 | event.stopPropagation(); 13 | } 14 | }); 15 | $(".solution").each(function() { 16 | $(">*:not(h2)", this).toggle(); 17 | var h2 = $("h2:first", this); 18 | h2.append(""); 19 | }); 20 | 21 | 22 | // Handle searches. 23 | // Relies on document having 'meta' element with name 'search-domain'. 24 | function google_search() { 25 | var query = document.getElementById("google-search").value; 26 | var domain = $("meta[name=search-domain]").attr("value"); 27 | window.open("https://www.google.com/search?q=" + query + "+site:" + domain); 28 | } 29 | 30 | // function to shrink the life cycle bar when scrolling 31 | $(function(){ 32 | $('#life-cycle').data('size','big'); 33 | }); 34 | 35 | $(window).scroll(function(){ 36 | if($(document).scrollTop() > 0) 37 | { 38 | if($('#life-cycle').data('size') == 'big') 39 | { 40 | $('#life-cycle').data('size','small'); 41 | $('#life-cycle').stop().animate({ 42 | padding: '5px' 43 | },100); 44 | } 45 | } 46 | else 47 | { 48 | if($('#life-cycle').data('size') == 'small') 49 | { 50 | $('#life-cycle').data('size','big'); 51 | $('#life-cycle').stop().animate({ 52 | padding: '15px' 53 | },100); 54 | } 55 | } 56 | }); 57 | -------------------------------------------------------------------------------- /bin/boilerplate/AUTHORS: -------------------------------------------------------------------------------- 1 | FIXME: list authors' names and email addresses. -------------------------------------------------------------------------------- /bin/boilerplate/CITATION: -------------------------------------------------------------------------------- 1 | FIXME: describe how to cite this lesson. -------------------------------------------------------------------------------- /bin/boilerplate/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | [The Carpentries][c-site] ([Software Carpentry][swc-site], [Data Carpentry][dc-site], and [Library Carpentry][lc-site]) are open source projects, 4 | and we welcome contributions of all kinds: 5 | new lessons, 6 | fixes to existing material, 7 | bug reports, 8 | and reviews of proposed changes are all welcome. 9 | 10 | ## Contributor Agreement 11 | 12 | By contributing, 13 | you agree that we may redistribute your work under [our license](LICENSE.md). 14 | In exchange, 15 | we will address your issues and/or assess your change proposal as promptly as we can, 16 | and help you become a member of our community. 17 | Everyone involved in [The Carpentries][c-site] 18 | agrees to abide by our [code of conduct](CODE_OF_CONDUCT.md). 19 | 20 | ## How to Contribute 21 | 22 | The easiest way to get started is to file an issue 23 | to tell us about a spelling mistake, 24 | some awkward wording, 25 | or a factual error. 26 | This is a good way to introduce yourself 27 | and to meet some of our community members. 28 | 29 | 1. If you do not have a [GitHub][github] account, 30 | you can [send us comments by email][email]. 31 | However, 32 | we will be able to respond more quickly if you use one of the other methods described below. 33 | 34 | 2. If you have a [GitHub][github] account, 35 | or are willing to [create one][github-join], 36 | but do not know how to use Git, 37 | you can report problems or suggest improvements by [creating an issue][issues]. 38 | This allows us to assign the item to someone 39 | and to respond to it in a threaded discussion. 40 | 41 | 3. If you are comfortable with Git, 42 | and would like to add or change material, 43 | you can submit a pull request (PR). 44 | Instructions for doing this are [included below](#using-github). 45 | 46 | ## Where to Contribute 47 | 48 | 1. If you wish to change this lesson, 49 | please work in , 50 | which can be viewed at . 51 | 52 | 2. If you wish to change the example lesson, 53 | please work in , 54 | which documents the format of our lessons 55 | and can be viewed at . 56 | 57 | 3. If you wish to change the template used for workshop websites, 58 | please work in . 59 | The home page of that repository explains how to set up workshop websites, 60 | while the extra pages in 61 | provide more background on our design choices. 62 | 63 | 4. If you wish to change CSS style files, tools, 64 | or HTML boilerplate for lessons or workshops stored in `_includes` or `_layouts`, 65 | please work in . 66 | 67 | ## What to Contribute 68 | 69 | There are many ways to contribute, 70 | from writing new exercises and improving existing ones 71 | to updating or filling in the documentation 72 | and submitting [bug reports][issues] 73 | about things that do not work, are not clear, or are missing. 74 | If you are looking for ideas, please see the 'Issues' tab for 75 | a list of issues associated with this repository, 76 | or you may also look at the issues for [Data Carpentry][dc-issues], 77 | [Software Carpentry][swc-issues], and [Library Carpentry][lc-issues] projects. 78 | 79 | Comments on issues and reviews of pull requests are just as welcome: 80 | we are smarter together than we are on our own. 81 | Reviews from novices and newcomers are particularly valuable: 82 | it is easy for people who have been using these lessons for a while 83 | to forget how impenetrable some of this material can be, 84 | so fresh eyes are always welcome. 85 | 86 | ## What *Not* to Contribute 87 | 88 | Our lessons already contain more material than we can cover in a typical workshop, 89 | so we are usually *not* looking for more concepts or tools to add to them. 90 | As a rule, 91 | if you want to introduce a new idea, 92 | you must (a) estimate how long it will take to teach 93 | and (b) explain what you would take out to make room for it. 94 | The first encourages contributors to be honest about requirements; 95 | the second, to think hard about priorities. 96 | 97 | We are also not looking for exercises or other material that will only run on one platform. 98 | Our workshops typically contain a mixture of Windows, macOS, and Linux users; 99 | in order to be usable, 100 | our lessons must run equally well on all three. 101 | 102 | ## Using GitHub 103 | 104 | If you choose to contribute via GitHub, you may want to look at 105 | [How to Contribute to an Open Source Project on GitHub][how-contribute]. 106 | To manage changes, we follow [GitHub flow][github-flow]. 107 | Each lesson has at least two maintainers who review issues and pull requests or encourage others to do so. 108 | The maintainers are community volunteers and have final say over what gets merged into the lesson. 109 | To use the web interface for contributing to a lesson: 110 | 111 | 1. Fork the originating repository to your GitHub profile. 112 | 2. Within your version of the forked repository, move to the `gh-pages` branch and 113 | create a new branch for each significant change being made. 114 | 3. Navigate to the file(s) you wish to change within the new branches and make revisions as required. 115 | 4. Commit all changed files within the appropriate branches. 116 | 5. Create individual pull requests from each of your changed branches 117 | to the `gh-pages` branch within the originating repository. 118 | 6. If you receive feedback, make changes using your issue-specific branches of the forked 119 | repository and the pull requests will update automatically. 120 | 7. Repeat as needed until all feedback has been addressed. 121 | 122 | When starting work, please make sure your clone of the originating `gh-pages` branch is up-to-date 123 | before creating your own revision-specific branch(es) from there. 124 | Additionally, please only work from your newly-created branch(es) and *not* 125 | your clone of the originating `gh-pages` branch. 126 | Lastly, published copies of all the lessons are available in the `gh-pages` branch of the originating 127 | repository for reference while revising. 128 | 129 | ## Other Resources 130 | 131 | General discussion of [Software Carpentry][swc-site], [Data Carpentry][dc-site], and [Library Carpentry][lc-site] 132 | happens on the [discussion mailing list][discuss-list], 133 | which everyone is welcome to join. 134 | You can also [reach us by email][email]. 135 | 136 | [email]: mailto:team@carpentries.org 137 | [dc-issues]: https://github.com/issues?q=user%3Adatacarpentry 138 | [dc-lessons]: http://datacarpentry.org/lessons/ 139 | [dc-site]: http://datacarpentry.org/ 140 | [discuss-list]: https://carpentries.topicbox.com/groups/discuss 141 | [github]: https://github.com 142 | [github-flow]: https://guides.github.com/introduction/flow/ 143 | [github-join]: https://github.com/join 144 | [how-contribute]: https://app.egghead.io/playlists/how-to-contribute-to-an-open-source-project-on-github 145 | [issues]: https://guides.github.com/features/issues/ 146 | [swc-issues]: https://github.com/issues?q=user%3Aswcarpentry 147 | [swc-lessons]: https://software-carpentry.org/lessons/ 148 | [swc-site]: https://software-carpentry.org/ 149 | [c-site]: https://carpentries.org/ 150 | [lc-site]: https://librarycarpentry.org/ 151 | [lc-issues]: https://github.com/issues?q=user%3Alibrarycarpentry 152 | -------------------------------------------------------------------------------- /bin/boilerplate/README.md: -------------------------------------------------------------------------------- 1 | # FIXME Lesson title 2 | 3 | [![Create a Slack Account with us](https://img.shields.io/badge/Create_Slack_Account-The_Carpentries-071159.svg)](https://swc-slack-invite.herokuapp.com/) 4 | 5 | This repository generates the corresponding lesson website from [The Carpentries](https://carpentries.org/) repertoire of lessons. 6 | 7 | ## Contributing 8 | 9 | We welcome all contributions to improve the lesson! Maintainers will do their best to help you if you have any 10 | questions, concerns, or experience any difficulties along the way. 11 | 12 | We'd like to ask you to familiarize yourself with our [Contribution Guide](CONTRIBUTING.md) and have a look at 13 | the [more detailed guidelines][lesson-example] on proper formatting, ways to render the lesson locally, and even 14 | how to write new episodes. 15 | 16 | Please see the current list of [issues][FIXME] for ideas for contributing to this 17 | repository. For making your contribution, we use the GitHub flow, which is 18 | nicely explained in the chapter [Contributing to a Project](http://git-scm.com/book/en/v2/GitHub-Contributing-to-a-Project) in Pro Git 19 | by Scott Chacon. 20 | 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. 21 | 22 | 23 | ## Maintainer(s) 24 | 25 | Current maintainers of this lesson are 26 | 27 | * FIXME 28 | * FIXME 29 | * FIXME 30 | 31 | 32 | ## Authors 33 | 34 | A list of contributors to the lesson can be found in [AUTHORS](AUTHORS) 35 | 36 | ## Citation 37 | 38 | To cite this lesson, please consult with [CITATION](CITATION) 39 | 40 | [lesson-example]: https://carpentries.github.io/lesson-example 41 | -------------------------------------------------------------------------------- /bin/boilerplate/_config.yml: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------ 2 | # Values for this lesson. 3 | #------------------------------------------------------------ 4 | 5 | # Which carpentry is this ("swc", "dc", "lc", or "cp")? 6 | # swc: Software Carpentry 7 | # dc: Data Carpentry 8 | # lc: Library Carpentry 9 | # cp: Carpentries (to use for instructor traning for instance) 10 | # incubator: Carpentries Incubator 11 | carpentry: "swc" 12 | 13 | # Overall title for pages. 14 | title: "Lesson Title" 15 | 16 | # Life cycle stage of the lesson 17 | # See this page for more details: https://cdh.carpentries.org/the-lesson-life-cycle.html 18 | # Possible values: "pre-alpha", "alpha", "beta", "stable" 19 | # 20 | # Lessons that are going through the transition to the 21 | # Carpentries Workbench will go through 3 steps: 22 | # 'transition-step-1': notice indicating a new version 23 | # 'transition-step-2': notice encouraging to use new version 24 | # 'transition-step-3': notice indicating the lesson is deprecated, 25 | # with automated redirect 26 | life_cycle: "pre-alpha" 27 | 28 | # For lessons in the life stages in 'transition-step-1' or later: 29 | # - 'transition_url' holds the URL for the version of the lesson that 30 | # uses the Workbench (needed for all 3 steps) 31 | # - 'transition_date' (in yyyy-mm-dd format) is the date when the lesson 32 | # will transition to being deprecated. The date only needs to be decided 33 | # when the lesson is in 'transition-step-2'. 34 | transition_url: 35 | transition_date: 36 | 37 | #------------------------------------------------------------ 38 | # Generic settings (should not need to change). 39 | #------------------------------------------------------------ 40 | 41 | # What kind of thing is this ("workshop" or "lesson")? 42 | kind: "lesson" 43 | 44 | # Magic to make URLs resolve both locally and on GitHub. 45 | # See https://help.github.com/articles/repository-metadata-on-github-pages/. 46 | # Please don't change it: / is correct. 47 | repository: / 48 | 49 | # Email address, no mailto: 50 | email: "team@carpentries.org" 51 | 52 | # Sites. 53 | coc: "https://docs.carpentries.org/topic_folders/policies/code-of-conduct.html" 54 | amy_site: "https://amy.carpentries.org/" 55 | carpentries_github: "https://github.com/carpentries" 56 | carpentries_pages: "https://carpentries.github.io" 57 | carpentries_site: "https://carpentries.org/" 58 | dc_site: "https://datacarpentry.org" 59 | example_repo: "https://github.com/carpentries/lesson-example" 60 | example_site: "https://carpentries.github.io/lesson-example" 61 | lc_site: "https://librarycarpentry.org/" 62 | swc_github: "https://github.com/swcarpentry" 63 | swc_pages: "https://swcarpentry.github.io" 64 | swc_site: "https://software-carpentry.org" 65 | template_repo: "https://github.com/carpentries/styles" 66 | training_site: "https://carpentries.github.io/instructor-training" 67 | workshop_repo: "https://github.com/carpentries/workshop-template" 68 | workshop_site: "https://carpentries.github.io/workshop-template" 69 | cc_by_human: "https://creativecommons.org/licenses/by/4.0/" 70 | 71 | # Surveys. 72 | pre_survey: "https://carpentries.typeform.com/to/wi32rS#slug=" 73 | post_survey: "https://carpentries.typeform.com/to/UgVdRQ#slug=" 74 | instructor_pre_survey: "https://carpentries.typeform.com/to/QVOarK#slug=" 75 | instructor_post_survey: "https://carpentries.typeform.com/to/cjJ9UP#slug=" 76 | 77 | # Set to 'true' for instructor training websites only. 78 | instructor_training: false 79 | 80 | # Start time in minutes (0 to be clock-independent, 540 to show a start at 09:00 am). 81 | start_time: 0 82 | 83 | # Specify that things in the episodes collection should be output. 84 | collections: 85 | episodes: 86 | output: true 87 | permalink: /:path/index.html 88 | extras: 89 | output: true 90 | permalink: /:path/index.html 91 | 92 | # Set the default layout for things in the episodes collection. 93 | defaults: 94 | - values: 95 | root: . 96 | layout: page 97 | - scope: 98 | path: "" 99 | type: episodes 100 | values: 101 | root: .. 102 | layout: episode 103 | - scope: 104 | path: "" 105 | type: extras 106 | values: 107 | root: .. 108 | layout: page 109 | 110 | # Files and directories that are not to be copied. 111 | exclude: 112 | - Makefile 113 | - bin/ 114 | - .Rproj.user/ 115 | - .vendor/ 116 | - vendor/ 117 | - .docker-vendor/ 118 | 119 | # Turn on built-in syntax highlighting. 120 | highlighter: rouge 121 | -------------------------------------------------------------------------------- /bin/boilerplate/_episodes/01-introduction.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Introduction" 3 | teaching: 0 4 | exercises: 0 5 | questions: 6 | - "Key question (FIXME)" 7 | objectives: 8 | - "First learning objective. (FIXME)" 9 | keypoints: 10 | - "First key point. Brief Answer to questions. (FIXME)" 11 | --- 12 | FIXME 13 | 14 | {% include links.md %} 15 | 16 | -------------------------------------------------------------------------------- /bin/boilerplate/_extras/about.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: About 3 | --- 4 | {% include carpentries.html %} 5 | {% include links.md %} 6 | -------------------------------------------------------------------------------- /bin/boilerplate/_extras/discuss.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Discussion 3 | --- 4 | FIXME 5 | 6 | {% include links.md %} 7 | -------------------------------------------------------------------------------- /bin/boilerplate/_extras/figures.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Figures 3 | --- 4 | 5 | {% include base_path.html %} 6 | {% include manual_episode_order.html %} 7 | 8 | 67 | 68 | {% comment %} Create anchor for each one of the episodes. {% endcomment %} 69 | 70 | {% for lesson_episode in lesson_episodes %} 71 | {% if site.episode_order %} 72 | {% assign episode = site.episodes | where: "slug", lesson_episode | first %} 73 | {% else %} 74 | {% assign episode = lesson_episode %} 75 | {% endif %} 76 |
77 | {% endfor %} 78 | 79 | {% include links.md %} 80 | -------------------------------------------------------------------------------- /bin/boilerplate/_extras/guide.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Instructor Notes" 3 | --- 4 | FIXME 5 | 6 | {% include links.md %} 7 | -------------------------------------------------------------------------------- /bin/boilerplate/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: lesson 3 | root: . # Is the only page that doesn't follow the pattern /:path/index.html 4 | permalink: index.html # Is the only page that doesn't follow the pattern /:path/index.html 5 | --- 6 | FIXME: home page introduction 7 | 8 | 9 | 10 | {% comment %} This is a comment in Liquid {% endcomment %} 11 | 12 | > ## Prerequisites 13 | > 14 | > FIXME 15 | {: .prereq} 16 | 17 | {% include links.md %} 18 | -------------------------------------------------------------------------------- /bin/boilerplate/reference.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: reference 3 | --- 4 | 5 | ## Glossary 6 | 7 | FIXME 8 | 9 | {% include links.md %} 10 | -------------------------------------------------------------------------------- /bin/boilerplate/setup.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Setup 3 | --- 4 | FIXME 5 | 6 | 7 | {% include links.md %} 8 | -------------------------------------------------------------------------------- /bin/chunk-options.R: -------------------------------------------------------------------------------- 1 | # These settings control the behavior of all chunks in the novice R materials. 2 | # For example, to generate the lessons with all the output hidden, simply change 3 | # `results` from "markup" to "hide". 4 | # For more information on available chunk options, see 5 | # http://yihui.name/knitr/options#chunk_options 6 | 7 | library("knitr") 8 | 9 | fix_fig_path <- function(pth) file.path("..", pth) 10 | 11 | 12 | ## We set the path for the figures globally below, so if we want to 13 | ## customize it for individual episodes, we can append a prefix to the 14 | ## global path. For instance, if we call knitr_fig_path("01-") in the 15 | ## first episode of the lesson, it will generate the figures in 16 | ## `fig/rmd-01-` 17 | knitr_fig_path <- function(prefix) { 18 | new_path <- paste0(opts_chunk$get("fig.path"), 19 | prefix) 20 | opts_chunk$set(fig.path = new_path) 21 | } 22 | 23 | ## We use the rmd- prefix for the figures generated by the lessons so 24 | ## they can be easily identified and deleted by `make clean-rmd`. The 25 | ## working directory when the lessons are generated is the root so the 26 | ## figures need to be saved in fig/, but when the site is generated, 27 | ## the episodes will be one level down. We fix the path using the 28 | ## `fig.process` option. 29 | 30 | opts_chunk$set(tidy = FALSE, results = "markup", comment = NA, 31 | fig.align = "center", fig.path = "fig/rmd-", 32 | fig.process = fix_fig_path, 33 | fig.width = 8.5, fig.height = 8.5, 34 | fig.retina = 2) 35 | 36 | # The hooks below add html tags to the code chunks and their output so that they 37 | # are properly formatted when the site is built. 38 | 39 | hook_in <- function(x, options) { 40 | lg <- tolower(options$engine) 41 | style <- paste0(".language-", lg) 42 | 43 | stringr::str_c("\n\n~~~\n", 44 | paste0(x, collapse="\n"), 45 | "\n~~~\n{: ", style, "}\n\n") 46 | } 47 | 48 | hook_out <- function(x, options) { 49 | x <- gsub("\n$", "", x) 50 | stringr::str_c("\n\n~~~\n", 51 | paste0(x, collapse="\n"), 52 | "\n~~~\n{: .output}\n\n") 53 | } 54 | 55 | hook_error <- function(x, options) { 56 | x <- gsub("\n$", "", x) 57 | stringr::str_c("\n\n~~~\n", 58 | paste0(x, collapse="\n"), 59 | "\n~~~\n{: .error}\n\n") 60 | } 61 | 62 | hook_warning <- function(x, options) { 63 | x <- gsub("\n$", "", x) 64 | stringr::str_c("\n\n~~~\n", 65 | paste0(x, collapse = "\n"), 66 | "\n~~~\n{: .warning}\n\n") 67 | } 68 | 69 | knit_hooks$set(source = hook_in, output = hook_out, warning = hook_warning, 70 | error = hook_error, message = hook_out) 71 | -------------------------------------------------------------------------------- /bin/dependencies.R: -------------------------------------------------------------------------------- 1 | install_required_packages <- function(lib = NULL, repos = getOption("repos", default = c(CRAN = "https://cran.rstudio.com/"))) { 2 | 3 | if (is.null(lib)) { 4 | lib <- .libPaths()[[1]] 5 | } 6 | 7 | message("lib paths: ", paste(lib, collapse = ", ")) 8 | # Note: RMarkdown is needed for renv to detect packages in Rmd documents. 9 | required_pkgs <- c("rprojroot", "desc", "remotes", "renv", "BiocManager", "rmarkdown") 10 | installed_pkgs <- rownames(installed.packages(lib.loc = lib)) 11 | missing_pkgs <- setdiff(required_pkgs, installed_pkgs) 12 | 13 | # The default installation of R will have "@CRAN@" as the default repository, 14 | # which directs contrib.url() to either force the user to choose a mirror if 15 | # interactive or fail if not. Since we are not interactve, we need to force 16 | # the mirror here. 17 | if ("@CRAN@" %in% repos) { 18 | repos <- c(CRAN = "https://cran.rstudio.com/") 19 | } 20 | 21 | if (length(missing_pkgs) != 0) { 22 | install.packages(missing_pkgs, lib = lib, repos = repos) 23 | } 24 | } 25 | 26 | find_root <- function() { 27 | 28 | cfg <- rprojroot::has_file_pattern("^_config.y*ml$") 29 | root <- rprojroot::find_root(cfg) 30 | 31 | root 32 | } 33 | 34 | # set the BiocManager repositories and return a function that resets the default 35 | # repositories. 36 | # 37 | # @example 38 | # bioc_repos_example <- function() { 39 | # message("User repos") 40 | # as.data.frame(getOption("repos")) 41 | # reset_repos <- use_bioc_repos() 42 | # on.exit(reset_repos()) 43 | # message("Bioc repos") 44 | # as.data.frame(getOption("repos")) 45 | # } 46 | # bioc_repos_example() 47 | # as.data.frame(getOption("repos") 48 | use_bioc_repos <- function() { 49 | repos <- getOption("repos") 50 | suppressMessages(options(repos = BiocManager::repositories())) 51 | function() { 52 | options(repos = repos) 53 | } 54 | } 55 | 56 | identify_dependencies <- function() { 57 | 58 | root <- find_root() 59 | 60 | reset_repos <- use_bioc_repos() 61 | on.exit(reset_repos(), add = TRUE) 62 | eps <- file.path(root, "_episodes_rmd") 63 | bin <- file.path(root, "bin") 64 | 65 | required_pkgs <- unique(c( 66 | ## Packages for episodes 67 | renv::dependencies(eps, progress = FALSE, error = "ignored")$Package, 68 | ## Packages for tools 69 | renv::dependencies(bin, progress = FALSE, error = "ignored")$Package 70 | )) 71 | 72 | required_pkgs 73 | } 74 | 75 | create_description <- function(required_pkgs) { 76 | d <- desc::description$new("!new") 77 | d$set_deps(data.frame(type = "Imports", package = required_pkgs, version = "*")) 78 | d$write("DESCRIPTION") 79 | # We have to write the description twice to get the hidden dependencies 80 | # because renv only considers explicit dependencies. 81 | # 82 | # This is needed because some of the hidden dependencis will require system 83 | # libraries to be configured. 84 | suppressMessages(repo <- BiocManager::repositories()) 85 | deps <- remotes::dev_package_deps(dependencies = TRUE, repos = repo) 86 | deps <- deps$package[deps$diff < 0] 87 | if (length(deps)) { 88 | # only create new DESCRIPTION file if there are dependencies to install 89 | d$set_deps(data.frame(type = "Imports", package = deps, version = "*")) 90 | d$write("DESCRIPTION") 91 | } 92 | } 93 | 94 | install_dependencies <- function(required_pkgs, ...) { 95 | 96 | reset_repos <- use_bioc_repos() 97 | on.exit(reset_repos(), add = TRUE) 98 | 99 | create_description(required_pkgs) 100 | on.exit(file.remove("DESCRIPTION"), add = TRUE) 101 | remotes::install_deps(dependencies = TRUE, ...) 102 | 103 | if (require("knitr") && packageVersion("knitr") < '1.9.19') { 104 | stop("knitr must be version 1.9.20 or higher") 105 | } 106 | 107 | } 108 | -------------------------------------------------------------------------------- /bin/generate_md_episodes.R: -------------------------------------------------------------------------------- 1 | generate_md_episodes <- function() { 2 | 3 | # avoid ansi color characters from being printed in the output 4 | op <- options() 5 | on.exit(options(op), add = TRUE) 6 | options(crayon.enabled = FALSE) 7 | ## get the Rmd file to process from the command line, and generate the path 8 | ## for their respective outputs 9 | args <- commandArgs(trailingOnly = TRUE) 10 | if (!identical(length(args), 2L)) { 11 | stop("input and output file must be passed to the script") 12 | } 13 | 14 | src_rmd <- args[1] 15 | dest_md <- args[2] 16 | 17 | ## knit the Rmd into markdown 18 | knitr::knit(src_rmd, output = dest_md) 19 | 20 | # Read the generated md files and add comments advising not to edit them 21 | add_no_edit_comment <- function(y) { 22 | con <- file(y) 23 | mdfile <- readLines(con) 24 | if (mdfile[1] != "---") 25 | stop("Input file does not have a valid header") 26 | mdfile <- append( 27 | mdfile, 28 | "# Please do not edit this file directly; it is auto generated.", 29 | after = 1 30 | ) 31 | mdfile <- append( 32 | mdfile, 33 | paste("# Instead, please edit", basename(y), "in _episodes_rmd/"), 34 | after = 2 35 | ) 36 | writeLines(mdfile, con) 37 | close(con) 38 | return(paste("Warning added to YAML header of", y)) 39 | } 40 | 41 | vapply(dest_md, add_no_edit_comment, character(1)) 42 | } 43 | 44 | generate_md_episodes() 45 | -------------------------------------------------------------------------------- /bin/install_r_deps.sh: -------------------------------------------------------------------------------- 1 | Rscript -e "source(file.path('bin', 'dependencies.R')); install_required_packages(); install_dependencies(identify_dependencies())" 2 | -------------------------------------------------------------------------------- /bin/knit_lessons.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Only try running R to translate files if there are some files present. 4 | # The Makefile passes in the names of files. 5 | 6 | if [ $# -eq 2 ] ; then 7 | Rscript -e "source('bin/generate_md_episodes.R')" "$@" 8 | fi 9 | -------------------------------------------------------------------------------- /bin/lesson_initialize.py: -------------------------------------------------------------------------------- 1 | """Initialize a newly-created repository.""" 2 | 3 | 4 | import sys 5 | import os 6 | import shutil 7 | 8 | BOILERPLATE = ( 9 | 'AUTHORS', 10 | 'CITATION', 11 | 'CONTRIBUTING.md', 12 | 'README.md', 13 | '_config.yml', 14 | os.path.join('_episodes', '01-introduction.md'), 15 | os.path.join('_extras', 'about.md'), 16 | os.path.join('_extras', 'discuss.md'), 17 | os.path.join('_extras', 'figures.md'), 18 | os.path.join('_extras', 'guide.md'), 19 | 'index.md', 20 | 'reference.md', 21 | 'setup.md', 22 | ) 23 | 24 | 25 | def main(): 26 | """Check for collisions, then create.""" 27 | 28 | # Check. 29 | errors = False 30 | for path in BOILERPLATE: 31 | if os.path.exists(path): 32 | print('Warning: {0} already exists.'.format(path), file=sys.stderr) 33 | errors = True 34 | if errors: 35 | print('**Exiting without creating files.**', file=sys.stderr) 36 | sys.exit(1) 37 | 38 | # Create. 39 | for path in BOILERPLATE: 40 | shutil.copyfile( 41 | os.path.join('bin', 'boilerplate', path), 42 | path 43 | ) 44 | 45 | 46 | if __name__ == '__main__': 47 | main() 48 | -------------------------------------------------------------------------------- /bin/markdown_ast.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # Use Kramdown parser to produce AST for Markdown document. 5 | 6 | require 'kramdown' 7 | require 'kramdown-parser-gfm' 8 | require 'json' 9 | 10 | markdown = $stdin.read 11 | doc = Kramdown::Document.new(markdown, input: 'GFM', hard_wrap: false) 12 | tree = doc.to_hash_a_s_t 13 | puts JSON.pretty_generate(tree) 14 | -------------------------------------------------------------------------------- /bin/repo_check.py: -------------------------------------------------------------------------------- 1 | """ 2 | Check repository settings. 3 | """ 4 | 5 | 6 | import sys 7 | import os 8 | from subprocess import Popen, PIPE 9 | import re 10 | from argparse import ArgumentParser 11 | 12 | from util import require 13 | from reporter import Reporter 14 | 15 | # Import this way to produce a more useful error message. 16 | try: 17 | import requests 18 | except ImportError: 19 | print('Unable to import requests module: please install requests', file=sys.stderr) 20 | sys.exit(1) 21 | 22 | 23 | # Pattern to match Git command-line output for remotes => (user name, project name). 24 | P_GIT_REMOTE = re.compile(r'upstream\s+(?:https://|git@)github.com[:/]([^/]+)/([^.]+)(\.git)?\s+\(fetch\)') 25 | 26 | # Repository URL format string. 27 | F_REPO_URL = 'https://github.com/{0}/{1}/' 28 | 29 | # Pattern to match repository URLs => (user name, project name) 30 | P_REPO_URL = re.compile(r'https?://github\.com/([^.]+)/([^/]+)/?') 31 | 32 | # API URL format string. 33 | F_API_URL = 'https://api.github.com/repos/{0}/{1}/labels' 34 | 35 | # Expected labels and colors. 36 | EXPECTED = { 37 | 'help wanted': 'dcecc7', 38 | 'status:in progress': '9bcc65', 39 | 'status:changes requested': '679f38', 40 | 'status:wait': 'fff2df', 41 | 'status:refer to cac': 'ffdfb2', 42 | 'status:need more info': 'ee6c00', 43 | 'status:blocked': 'e55100', 44 | 'status:out of scope': 'eeeeee', 45 | 'status:duplicate': 'bdbdbd', 46 | 'type:typo text': 'f8bad0', 47 | 'type:bug': 'eb3f79', 48 | 'type:formatting': 'ac1357', 49 | 'type:template and tools': '7985cb', 50 | 'type:instructor guide': '00887a', 51 | 'type:discussion': 'b2e5fc', 52 | 'type:enhancement': '7fdeea', 53 | 'type:clarification': '00acc0', 54 | 'type:teaching example': 'ced8dc', 55 | 'good first issue': 'ffeb3a', 56 | 'high priority': 'd22e2e' 57 | } 58 | 59 | 60 | def main(): 61 | """ 62 | Main driver. 63 | """ 64 | 65 | args = parse_args() 66 | reporter = Reporter() 67 | repo_url = get_repo_url(args.repo_url) 68 | check_labels(reporter, repo_url) 69 | reporter.report() 70 | 71 | 72 | def parse_args(): 73 | """ 74 | Parse command-line arguments. 75 | """ 76 | 77 | parser = ArgumentParser(description="""Check repository settings.""") 78 | parser.add_argument('-r', '--repo', 79 | default=None, 80 | dest='repo_url', 81 | help='repository URL') 82 | parser.add_argument('-s', '--source', 83 | default=os.curdir, 84 | dest='source_dir', 85 | help='source directory') 86 | 87 | args, extras = parser.parse_known_args() 88 | require(not extras, 89 | 'Unexpected trailing command-line arguments "{0}"'.format(extras)) 90 | 91 | return args 92 | 93 | 94 | def get_repo_url(repo_url): 95 | """ 96 | Figure out which repository to query. 97 | """ 98 | 99 | # Explicitly specified. 100 | if repo_url is not None: 101 | return repo_url 102 | 103 | # Guess. 104 | cmd = 'git remote -v' 105 | p = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, 106 | close_fds=True, universal_newlines=True, encoding='utf-8') 107 | stdout_data, stderr_data = p.communicate() 108 | stdout_data = stdout_data.split('\n') 109 | matches = [P_GIT_REMOTE.match(line) for line in stdout_data] 110 | matches = [m for m in matches if m is not None] 111 | require(len(matches) == 1, 112 | 'Unexpected output from git remote command: "{0}"'.format(matches)) 113 | 114 | username = matches[0].group(1) 115 | require( 116 | username, 'empty username in git remote output {0}'.format(matches[0])) 117 | 118 | project_name = matches[0].group(2) 119 | require( 120 | username, 'empty project name in git remote output {0}'.format(matches[0])) 121 | 122 | url = F_REPO_URL.format(username, project_name) 123 | return url 124 | 125 | 126 | def check_labels(reporter, repo_url): 127 | """ 128 | Check labels in repository. 129 | """ 130 | 131 | actual = get_labels(repo_url) 132 | extra = set(actual.keys()) - set(EXPECTED.keys()) 133 | 134 | reporter.check(not extra, 135 | None, 136 | 'Extra label(s) in repository {0}: {1}', 137 | repo_url, ', '.join(sorted(extra))) 138 | 139 | missing = set(EXPECTED.keys()) - set(actual.keys()) 140 | reporter.check(not missing, 141 | None, 142 | 'Missing label(s) in repository {0}: {1}', 143 | repo_url, ', '.join(sorted(missing))) 144 | 145 | overlap = set(EXPECTED.keys()).intersection(set(actual.keys())) 146 | for name in sorted(overlap): 147 | reporter.check(EXPECTED[name].lower() == actual[name].lower(), 148 | None, 149 | 'Color mis-match for label {0} in {1}: expected {2}, found {3}', 150 | name, repo_url, EXPECTED[name], actual[name]) 151 | 152 | 153 | def get_labels(repo_url): 154 | """ 155 | Get actual labels from repository. 156 | """ 157 | 158 | m = P_REPO_URL.match(repo_url) 159 | require( 160 | m, 'repository URL {0} does not match expected pattern'.format(repo_url)) 161 | 162 | username = m.group(1) 163 | require(username, 'empty username in repository URL {0}'.format(repo_url)) 164 | 165 | project_name = m.group(2) 166 | require( 167 | username, 'empty project name in repository URL {0}'.format(repo_url)) 168 | 169 | url = F_API_URL.format(username, project_name) 170 | r = requests.get(url) 171 | require(r.status_code == 200, 172 | 'Request for {0} failed with {1}'.format(url, r.status_code)) 173 | 174 | result = {} 175 | for entry in r.json(): 176 | result[entry['name']] = entry['color'] 177 | return result 178 | 179 | 180 | if __name__ == '__main__': 181 | main() 182 | -------------------------------------------------------------------------------- /bin/reporter.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | class Reporter: 4 | """Collect and report errors.""" 5 | 6 | # Marker to show that an expected value hasn't been provided. 7 | # (Can't use 'None' because that might be a legitimate value.) 8 | _DEFAULT_REPORTER = [] 9 | 10 | def __init__(self): 11 | """Constructor.""" 12 | self.messages = [] 13 | 14 | def check_field(self, filename, name, values, key, expected=_DEFAULT_REPORTER): 15 | """Check that a dictionary has an expected value.""" 16 | 17 | if key not in values: 18 | self.add(filename, '{0} does not contain {1}', name, key) 19 | elif expected is self._DEFAULT_REPORTER: 20 | pass 21 | elif type(expected) in (tuple, set, list): 22 | if values[key] not in expected: 23 | self.add( 24 | filename, '{0} {1} value {2} is not in {3}', name, key, values[key], expected) 25 | elif values[key] != expected: 26 | self.add(filename, '{0} {1} is {2} not {3}', 27 | name, key, values[key], expected) 28 | 29 | def check(self, condition, location, fmt, *args): 30 | """Append error if condition not met.""" 31 | 32 | if not condition: 33 | self.add(location, fmt, *args) 34 | 35 | def add(self, location, fmt, *args): 36 | """Append error unilaterally.""" 37 | 38 | self.messages.append((location, fmt.format(*args))) 39 | 40 | @staticmethod 41 | def pretty(item): 42 | location, message = item 43 | if isinstance(location, type(None)): 44 | return message 45 | elif isinstance(location, str): 46 | return location + ': ' + message 47 | elif isinstance(location, tuple): 48 | return '{0}:{1}: '.format(*location) + message 49 | 50 | print('Unknown item "{0}"'.format(item), file=sys.stderr) 51 | return NotImplemented 52 | 53 | @staticmethod 54 | def key(item): 55 | location, message = item 56 | if isinstance(location, type(None)): 57 | return ('', -1, message) 58 | elif isinstance(location, str): 59 | return (location, -1, message) 60 | elif isinstance(location, tuple): 61 | return (location[0], location[1], message) 62 | 63 | print('Unknown item "{0}"'.format(item), file=sys.stderr) 64 | return NotImplemented 65 | 66 | def report(self, stream=sys.stdout): 67 | """Report all messages in order.""" 68 | 69 | if not self.messages: 70 | return 71 | 72 | for m in sorted(self.messages, key=self.key): 73 | print(self.pretty(m), file=stream) 74 | 75 | 76 | -------------------------------------------------------------------------------- /bin/run-make-docker-serve.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -o errexit 4 | set -o pipefail 5 | set -o nounset 6 | 7 | 8 | bundle install 9 | bundle update 10 | exec bundle exec jekyll serve --host 0.0.0.0 11 | -------------------------------------------------------------------------------- /bin/test_lesson_check.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | import lesson_check 4 | import reporter 5 | 6 | 7 | class TestFileList(unittest.TestCase): 8 | def setUp(self): 9 | self.reporter = reporter.Reporter() # TODO: refactor reporter class. 10 | 11 | def test_file_list_has_expected_entries(self): 12 | # For first pass, simply assume that all required files are present 13 | 14 | lesson_check.check_fileset('', self.reporter, lesson_check.REQUIRED_FILES) 15 | self.assertEqual(len(self.reporter.messages), 0) 16 | 17 | 18 | if __name__ == "__main__": 19 | unittest.main() 20 | -------------------------------------------------------------------------------- /bin/util.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | import json 4 | from subprocess import Popen, PIPE 5 | 6 | # Import this way to produce a more useful error message. 7 | try: 8 | import yaml 9 | except ImportError: 10 | print('Unable to import YAML module: please install PyYAML', file=sys.stderr) 11 | sys.exit(1) 12 | 13 | __all__ = ['check_unwanted_files', 'load_yaml', 'read_markdown', 'require'] 14 | 15 | # Files that shouldn't be present. 16 | UNWANTED_FILES = [ 17 | '.nojekyll' 18 | ] 19 | 20 | def read_markdown(parser, path): 21 | """ 22 | Get YAML and AST for Markdown file, returning 23 | {'metadata':yaml, 'metadata_len':N, 'text':text, 'lines':[(i, line, len)], 'doc':doc}. 24 | """ 25 | 26 | # Split and extract YAML (if present). 27 | with open(path, 'r', encoding='utf-8') as reader: 28 | body = reader.read() 29 | metadata_raw, metadata_yaml, body = split_metadata(path, body) 30 | 31 | # Split into lines. 32 | metadata_len = 0 if metadata_raw is None else metadata_raw.count('\n') 33 | lines = [(metadata_len+i+1, line, len(line)) 34 | for (i, line) in enumerate(body.split('\n'))] 35 | 36 | # Parse Markdown. 37 | cmd = 'bundle exec ruby {0}'.format(parser) 38 | p = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, 39 | close_fds=True, universal_newlines=True, encoding='utf-8') 40 | stdout_data, stderr_data = p.communicate(body) 41 | doc = json.loads(stdout_data) 42 | 43 | return { 44 | 'metadata': metadata_yaml, 45 | 'metadata_len': metadata_len, 46 | 'text': body, 47 | 'lines': lines, 48 | 'doc': doc 49 | } 50 | 51 | 52 | def split_metadata(path, text): 53 | """ 54 | Get raw (text) metadata, metadata as YAML, and rest of body. 55 | If no metadata, return (None, None, body). 56 | """ 57 | 58 | metadata_raw = None 59 | metadata_yaml = None 60 | 61 | pieces = text.split('---', 2) 62 | if len(pieces) == 3: 63 | metadata_raw = pieces[1] 64 | text = pieces[2] 65 | try: 66 | metadata_yaml = yaml.load(metadata_raw, Loader=yaml.SafeLoader) 67 | except yaml.YAMLError as e: 68 | message = 'Unable to parse YAML header in {0}:\n{1}' 69 | print(message.format(path, e), file=sys.stderr) 70 | 71 | return metadata_raw, metadata_yaml, text 72 | 73 | 74 | def load_yaml(filename): 75 | """ 76 | Wrapper around YAML loading so that 'import yaml' is only needed 77 | in one file. 78 | """ 79 | 80 | try: 81 | with open(filename, 'r', encoding='utf-8') as reader: 82 | return yaml.load(reader, Loader=yaml.SafeLoader) 83 | except yaml.YAMLError as e: 84 | message = 'ERROR: Unable to load YAML file {0}:\n{1}' 85 | print(message.format(filename, e), file=sys.stderr) 86 | except (FileNotFoundError, IOError): 87 | message = 'ERROR: File {} not found' 88 | print(message.format(filename), file=sys.stderr) 89 | 90 | return {} 91 | 92 | def check_unwanted_files(dir_path, reporter): 93 | """ 94 | Check that unwanted files are not present. 95 | """ 96 | 97 | for filename in UNWANTED_FILES: 98 | path = os.path.join(dir_path, filename) 99 | reporter.check(not os.path.exists(path), 100 | path, 101 | "Unwanted file found") 102 | 103 | 104 | def require(condition, message, fatal=False): 105 | """Fail if condition not met.""" 106 | 107 | if not condition: 108 | print(message, file=sys.stderr) 109 | 110 | if fatal: 111 | sys.exit(1) 112 | -------------------------------------------------------------------------------- /code/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/code/.gitkeep -------------------------------------------------------------------------------- /data/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/data/.gitkeep -------------------------------------------------------------------------------- /fig/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/fig/.gitkeep -------------------------------------------------------------------------------- /files/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carpentries/styles/7bcdf5091ceb681ea3a239c83f3351fde09c1580/files/.gitkeep --------------------------------------------------------------------------------