From 1d32319046085f4d3e7c663e25de8c8e19749bb5 Mon Sep 17 00:00:00 2001 From: Toby Hodges Date: Thu, 5 Nov 2020 11:10:40 +0100 Subject: [PATCH 001/113] add image-with-shadow class --- assets/css/lesson.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/assets/css/lesson.scss b/assets/css/lesson.scss index 182fe3b7..bf345243 100644 --- a/assets/css/lesson.scss +++ b/assets/css/lesson.scss @@ -299,6 +299,10 @@ span.fold-unfold { } +img.image-with-shadow { + box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.2), 0 6px 24px 0 rgba(0, 0, 0, 0.19); +} + //---------------------------------------- // Life cycle box //---------------------------------------- From ca16e0be7110e18c1cef47544698141fefdb53af Mon Sep 17 00:00:00 2001 From: "Zhian N. Kamvar" Date: Wed, 2 Dec 2020 09:35:13 -0800 Subject: [PATCH 002/113] set CRAN url if default is "@CRAN@" This will fix #526 --- bin/dependencies.R | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/bin/dependencies.R b/bin/dependencies.R index ad5afe78..640b3e24 100644 --- a/bin/dependencies.R +++ b/bin/dependencies.R @@ -9,6 +9,12 @@ install_required_packages <- function(lib = NULL, repos = getOption("repos", def c("rprojroot", "desc", "remotes", "renv"), rownames(installed.packages(lib.loc = lib)) ) + # The default installation of R will have "@CRAN@" as the default repository, which directs contrib.url() to either + # force the user to choose a mirror if interactive or fail if not. Since we are not interactve, we need to force the + # mirror here. + if ("@CRAN@" %in% repos) { + repos <- c(CRAN = "https://cran.rstudio.com/") + } install.packages(missing_pkgs, lib = lib, repos = repos) From 32ab0d162a0fb2bac0d2da2d38825ba4b19295fc Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Tue, 24 Nov 2020 16:41:26 -0600 Subject: [PATCH 003/113] Fix Ruby style --- Gemfile | 2 +- bin/markdown_ast.rb | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Gemfile b/Gemfile index 46eedf74..41c97a9a 100644 --- a/Gemfile +++ b/Gemfile @@ -2,7 +2,7 @@ source 'https://rubygems.org' -git_source(:github) {|repo_name| "https://github.com/#{repo_name}" } +git_source(:github) { |repo_name| "https://github.com/#{repo_name}" } # Synchronize with https://pages.github.com/versions ruby '>=2.7.1' diff --git a/bin/markdown_ast.rb b/bin/markdown_ast.rb index c3fd0b5e..4fdb6843 100755 --- a/bin/markdown_ast.rb +++ b/bin/markdown_ast.rb @@ -1,11 +1,12 @@ #!/usr/bin/env ruby +# frozen_string_literal: true # Use Kramdown parser to produce AST for Markdown document. -require "kramdown" -require "json" +require 'kramdown' +require 'json' -markdown = STDIN.read() +markdown = $stdin.read doc = Kramdown::Document.new(markdown) tree = doc.to_hash_a_s_t puts JSON.pretty_generate(tree) From fdb264a33b7255fbad31dd1e847f4e94f8193191 Mon Sep 17 00:00:00 2001 From: Toby Hodges Date: Tue, 8 Dec 2020 19:09:16 +0100 Subject: [PATCH 004/113] accept any base filename for Rmd episodes --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 1eac375e..60bd888b 100644 --- a/Makefile +++ b/Makefile @@ -96,7 +96,7 @@ workshop-check : .PHONY : lesson-check lesson-md lesson-files lesson-fixme install-rmd-deps # RMarkdown files -RMD_SRC = $(wildcard _episodes_rmd/??-*.Rmd) +RMD_SRC = $(wildcard _episodes_rmd/*.Rmd) RMD_DST = $(patsubst _episodes_rmd/%.Rmd,_episodes/%.md,$(RMD_SRC)) # Lesson source files in the order they appear in the navigation menu. From ce79a4b69be1780640278b9971be56d70ee3c0e1 Mon Sep 17 00:00:00 2001 From: "Zhian N. Kamvar" Date: Mon, 7 Dec 2020 09:47:46 -0800 Subject: [PATCH 005/113] run R-based lessons in forks This is a modification for #501 --- .github/workflows/website.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index fbc51c97..c5ba1417 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/website.yml @@ -5,7 +5,7 @@ on: pull_request: [] jobs: build-website: - if: github.repository != 'carpentries/styles' && (github.repository_owner == 'swcarpentry' || github.repository_owner == 'datacarpentry' || github.repository_owner == 'librarycarpentry' || github.repository_owner == 'carpentries') + if: !endsWith(github.repository, '/styles') runs-on: ubuntu-latest defaults: run: From 423bf579d94b67be87bc2f8e68761134fb32bedd Mon Sep 17 00:00:00 2001 From: "Zhian N. Kamvar" Date: Mon, 7 Dec 2020 09:54:36 -0800 Subject: [PATCH 006/113] add control structure --- .github/workflows/website.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index c5ba1417..ea095431 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/website.yml @@ -5,7 +5,7 @@ on: pull_request: [] jobs: build-website: - if: !endsWith(github.repository, '/styles') + if: ${{ !endsWith(github.repository, '/styles') }} runs-on: ubuntu-latest defaults: run: From d8f93f065ec7d4fb24c087b5d7ff3ddec63bedac Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Tue, 24 Nov 2020 15:06:38 -0600 Subject: [PATCH 007/113] 404 page for better learner experience --- 404.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 404.md diff --git a/404.md b/404.md new file mode 100644 index 00000000..2038a508 --- /dev/null +++ b/404.md @@ -0,0 +1,25 @@ +--- +layout: base +root: . +permalink: 404.html +title: "Page not found" +--- + +# Oops! We can't find that page. +{: style="text-align: center;"} + +> ## Our apologies! +> +> We can't seem to find the page you're looking for. +> Try going back to the previous page or +> navigate to any other page using the navigation bar above +> {%- if site.kind == "lesson" -%} or the schedule below {%- endif -%}. +> If you got here by clicking on a link in the +> {%- if site.kind == "lesson" -%} lesson {%- else -%} workshop {%- endif -%}, +> please report this link to the +> {%- if site.kind == "lesson" -%} lesson developers {%- else -%} workshop organizers {%- endif -%}. +{: .caution} + +{% if site.kind == "lesson" %} + {% include syllabus.html %} +{% endif%} From 2b523bcc7b2178e0b6af6ec71fe4422483e61d1f Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Fri, 20 Nov 2020 08:42:26 -0600 Subject: [PATCH 008/113] lesson.scss: wildcard selectors for code blocks --- assets/css/lesson.scss | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/assets/css/lesson.scss b/assets/css/lesson.scss index 839ce200..9334e372 100644 --- a/assets/css/lesson.scss +++ b/assets/css/lesson.scss @@ -38,44 +38,31 @@ $color-testimonial: #fc8dc1 !default; border-radius: 4px 0 0 4px; } +// Generic setup. Has to come before .error, .warning, and .output +div[class^='language-'] { @include cdSetup($color-source); } + +div.source { @include cdSetup($color-source); } div.error { @include cdSetup($color-error); } div.warning { @include cdSetup($color-warning); } div.output { @include cdSetup($color-output); } -div.source { @include cdSetup($color-source); } - -div.language-bash { @include cdSetup($color-source); } -div.language-c { @include cdSetup($color-source); } -div.language-cmake { @include cdSetup($color-source); } -div.language-cpp { @include cdSetup($color-source); } -div.language-make { @include cdSetup($color-source); } -div.language-matlab { @include cdSetup($color-source); } -div.language-python { @include cdSetup($color-source); } -div.language-r { @include cdSetup($color-source); } -div.language-sql { @include cdSetup($color-source); } div.error::before, div.warning:before, div.output::before, div.source::before, -div.language-bash::before, -div.language-c::before, -div.language-cmake::before, -div.language-cpp::before, -div.language-make::before, -div.language-matlab::before, -div.language-python::before, -div.language-r::before, -div.language-sql::before { +div[class^='language-']::before { background-color: #f2eff6; display: block; font-weight: bold; padding: 5px 10px; } +div[class^='language-']::before, +div.source::before { content: "Code"; } + div.error::before { background-color: #ffebe6; content: "Error"; } div.warning:before { background-color: #f8f4e8; content:" Warning"; } div.output::before { background-color: #efefef; content: "Output"; } -div.source::before { content: "Code"; } div.language-bash::before { content: "Bash"; } div.language-c::before { content: "C"; } From 3efe66951f3f8bd10d6548c1df766e4e2f34af74 Mon Sep 17 00:00:00 2001 From: Kilian Date: Thu, 17 Dec 2020 12:03:48 +0100 Subject: [PATCH 009/113] Ignore .jekyll-metatada --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 1a9eadf0..e3ce3b79 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ .ipynb_checkpoints .sass-cache .jekyll-cache/ +.jekyll-metadata __pycache__ _site .Rproj.user From da99378ec7b96713c45d904ab0695718909178ed Mon Sep 17 00:00:00 2001 From: "Zhian N. Kamvar" Date: Thu, 17 Dec 2020 11:46:31 -0800 Subject: [PATCH 010/113] Speed up builds of R-based lessons R-based lessons might take a while to build because packages need to be compiled from source. RStudio Package Manager has compiled versions of packages for ubuntu distros starting with 16.04: https://packagemanager.rstudio.com/client/#/repos/1/overview I've added the necessary magic in the actions yaml to make it work. --- .github/workflows/website.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index ea095431..2ec7dfb4 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/website.yml @@ -7,6 +7,9 @@ jobs: build-website: if: ${{ !endsWith(github.repository, '/styles') }} runs-on: ubuntu-latest + env: + RSPM: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest" + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} defaults: run: shell: bash @@ -45,6 +48,7 @@ jobs: uses: r-lib/actions/setup-r@master with: r-version: 'release' + http-user-agent: "R/4.0.0 (ubuntu-16.04) R (4.0.0 x86_64-pc-linux-gnu x86_64 linux-gnu) on GitHub Actions" - name: Install needed packages if: steps.check-rmd.outputs.count != 0 From a60a74ac49001844dfa57d75188c4b871f59c7da Mon Sep 17 00:00:00 2001 From: "Zhian N. Kamvar" Date: Thu, 17 Dec 2020 15:46:52 -0800 Subject: [PATCH 011/113] No need for User Agent string --- .github/workflows/website.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index 2ec7dfb4..f58e9c80 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/website.yml @@ -8,7 +8,7 @@ jobs: if: ${{ !endsWith(github.repository, '/styles') }} runs-on: ubuntu-latest env: - RSPM: "https://packagemanager.rstudio.com/cran/__linux__/xenial/latest" + RSPM: "https://packagemanager.rstudio.com/cran/__linux__/bionic/latest" GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} defaults: run: @@ -48,7 +48,6 @@ jobs: uses: r-lib/actions/setup-r@master with: r-version: 'release' - http-user-agent: "R/4.0.0 (ubuntu-16.04) R (4.0.0 x86_64-pc-linux-gnu x86_64 linux-gnu) on GitHub Actions" - name: Install needed packages if: steps.check-rmd.outputs.count != 0 From 7fd7d18f4664e408d36359284902ce6018e9bdea Mon Sep 17 00:00:00 2001 From: "Zhian N. Kamvar" Date: Fri, 18 Dec 2020 08:16:56 -0800 Subject: [PATCH 012/113] permissive checks for pre-alpha lessons This will fix #533 --- bin/lesson_check.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bin/lesson_check.py b/bin/lesson_check.py index 1fd71182..2f7e773e 100644 --- a/bin/lesson_check.py +++ b/bin/lesson_check.py @@ -117,7 +117,10 @@ def main(): args = parse_args() args.reporter = Reporter() - check_config(args.reporter, args.source_dir) + life_cycle = check_config(args.reporter, args.source_dir) + # pre-alpha lessons should report without error + if life_cycle == "pre-alpha": + args.permissive = True check_source_rmd(args.reporter, args.source_dir, args.parser) args.references = read_references(args.reporter, args.reference_path) @@ -194,6 +197,7 @@ def check_config(reporter, source_dir): reporter.check(defaults in config.get('defaults', []), 'configuration', '"root" not set to "." in configuration') + return config['life_cycle'] def check_source_rmd(reporter, source_dir, parser): """Check that Rmd episode files include `source: Rmd`""" From 9e641fd78742e24688ded4b9d474ef83f96145ce Mon Sep 17 00:00:00 2001 From: Toby Hodges Date: Mon, 21 Dec 2020 20:21:47 +0100 Subject: [PATCH 013/113] bin/lesson_check.py: allow 'language-*' code blocks (#532) --- bin/lesson_check.py | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/bin/lesson_check.py b/bin/lesson_check.py index 2f7e773e..0c153575 100644 --- a/bin/lesson_check.py +++ b/bin/lesson_check.py @@ -76,17 +76,6 @@ 'error', 'output', 'source', - 'language-bash', - 'html', - 'language-c', - 'language-cmake', - 'language-cpp', - 'language-make', - 'language-matlab', - 'language-python', - 'language-r', - 'language-shell', - 'language-sql', 'warning' } @@ -399,7 +388,7 @@ def check_codeblock_classes(self): for node in self.find_all(self.doc, {'type': 'codeblock'}): cls = self.get_val(node, 'attr', 'class') - self.reporter.check(cls in KNOWN_CODEBLOCKS, + self.reporter.check(cls in KNOWN_CODEBLOCKS or cls.startswith('language-'), (self.filename, self.get_loc(node)), 'Unknown or missing code block type {0}', cls) From acdbd1cfae4cca1def0b3ac41422caf720731ffe Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Tue, 22 Dec 2020 11:25:06 -0600 Subject: [PATCH 014/113] bin/lesson_check.py: allow 'caution' blockquote --- bin/lesson_check.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bin/lesson_check.py b/bin/lesson_check.py index 0c153575..b046b34c 100644 --- a/bin/lesson_check.py +++ b/bin/lesson_check.py @@ -59,6 +59,7 @@ # What kinds of blockquotes are allowed? KNOWN_BLOCKQUOTES = { 'callout', + 'caution', 'challenge', 'checklist', 'discussion', @@ -72,6 +73,7 @@ } # What kinds of code fragments are allowed? +# Below we allow all 'language-*' code blocks KNOWN_CODEBLOCKS = { 'error', 'output', From 3d5f6b527932d943ec0958b8324b2915f8c05d87 Mon Sep 17 00:00:00 2001 From: "Zhian N. Kamvar" Date: Tue, 5 Jan 2021 18:08:35 -0800 Subject: [PATCH 015/113] avoid ansi color characters from being printed --- bin/generate_md_episodes.R | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bin/generate_md_episodes.R b/bin/generate_md_episodes.R index ce9e8aa6..7fb4c5a5 100644 --- a/bin/generate_md_episodes.R +++ b/bin/generate_md_episodes.R @@ -1,5 +1,9 @@ generate_md_episodes <- function() { + # avoid ansi color characters from being printed in the output + op <- options() + on.exit(options(op), add = TRUE) + options(crayon.enabled = FALSE) ## get the Rmd file to process from the command line, and generate the path ## for their respective outputs args <- commandArgs(trailingOnly = TRUE) From 627d1a1706a7b8645b8627239045144b975a366d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Michonneau?= Date: Fri, 18 Dec 2020 15:26:14 +0100 Subject: [PATCH 016/113] deploy from "website" action --- .github/workflows/website.yml | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index f58e9c80..719b39db 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/website.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest env: RSPM: "https://packagemanager.rstudio.com/cran/__linux__/bionic/latest" - GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} defaults: run: shell: bash @@ -82,6 +82,24 @@ jobs: done < <(Rscript -e 'cat(remotes::system_requirements("ubuntu", "18.04"), sep = "\n")') - run: make site + + - name: Setup Git + if: ${{ steps.check-rmd.outputs.count != 0 }} + run: | + git config --local user.email "actions@github.com" + git config --local user.name "GitHub Actions" + git status + + - name: Push site + if: ${{ github.event.push == 'true' && steps.check-rmd.outputs.count != 0 && github.ref == 'refs/head/main' }} + run: | + git checkout --orphan gh-pages + git add . + git commit -m "[GitHub Actions] render website" + git remote -v + git status + git push origin gh-pages + - run: make lesson-check if: always() - run: make lesson-check-all From afb88e2b690c5b3c8eac5f788518d7a16950204f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Michonneau?= Date: Fri, 18 Dec 2020 17:02:33 +0100 Subject: [PATCH 017/113] deploy R-based lessons without using another action --- .github/workflows/website.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index 719b39db..7b090b12 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/website.yml @@ -1,7 +1,9 @@ name: Website on: push: - branches: gh-pages + branches: + - gh-pages + - main pull_request: [] jobs: build-website: @@ -88,17 +90,15 @@ jobs: run: | git config --local user.email "actions@github.com" git config --local user.name "GitHub Actions" - git status + git checkout --orphan gha-rendering - name: Push site - if: ${{ github.event.push == 'true' && steps.check-rmd.outputs.count != 0 && github.ref == 'refs/head/main' }} + if: ${{ github.event.push == 'true' && steps.check-rmd.outputs.count != 0 && github.ref == 'refs/heads/main' }} run: | - git checkout --orphan gh-pages - git add . + rm -rf .bundle + git add --force . git commit -m "[GitHub Actions] render website" - git remote -v - git status - git push origin gh-pages + git push --force origin +gha-rendering:gh-pages - run: make lesson-check if: always() From 08e26e6440e891a269466ac8976cb242181acfd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Michonneau?= Date: Fri, 18 Dec 2020 17:42:55 +0100 Subject: [PATCH 018/113] also delete _site --- .github/workflows/website.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index 7b090b12..d5507d94 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/website.yml @@ -95,7 +95,7 @@ jobs: - name: Push site if: ${{ github.event.push == 'true' && steps.check-rmd.outputs.count != 0 && github.ref == 'refs/heads/main' }} run: | - rm -rf .bundle + rm -rf .bundle/ _site/ git add --force . git commit -m "[GitHub Actions] render website" git push --force origin +gha-rendering:gh-pages From 70e34841c7ab336deef49129303901e0b5496d41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Michonneau?= Date: Wed, 6 Jan 2021 15:21:13 +0100 Subject: [PATCH 019/113] include @zkamvar suggestions Co-authored-by: Zhian N. Kamvar --- .github/workflows/website.yml | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index d5507d94..70deeb26 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/website.yml @@ -83,24 +83,31 @@ jobs: eval sudo $cmd done < <(Rscript -e 'cat(remotes::system_requirements("ubuntu", "18.04"), sep = "\n")') - - run: make site + - name: Render the markdown and confirm that the site can be built + run: make site - - name: Setup Git - if: ${{ steps.check-rmd.outputs.count != 0 }} + - name: Checkout github pages + if: ${{ github.event_name == 'push' && steps.check-rmd.outputs.count != 0 && github.ref != 'refs/heads/gh-pages'}} + uses: actions/checkout@master + with: + ref: gh-pages + path: gh-pages + + - name: Commit and Push + if: ${{ github.event_name == 'push' && steps.check-rmd.outputs.count != 0 && github.ref != 'refs/heads/gh-pages'}} run: | + # copy everything into gh-pages site + cp -r `ls -A | grep -v 'gh-pages' | grep -v '.git' | grep -v '.bundle/' | grep -v '_site'` gh-pages + # move into gh-pages, add, commit, and push + cd gh-pages + # setup git git config --local user.email "actions@github.com" git config --local user.name "GitHub Actions" - git checkout --orphan gha-rendering + git add -A . + git commit --allow-empty -m "[Github Actions] render website (via ${{ github.sha }}" + git push origin gh-pages + # return + cd .. - - name: Push site - if: ${{ github.event.push == 'true' && steps.check-rmd.outputs.count != 0 && github.ref == 'refs/heads/main' }} - run: | - rm -rf .bundle/ _site/ - git add --force . - git commit -m "[GitHub Actions] render website" - git push --force origin +gha-rendering:gh-pages - - - run: make lesson-check - if: always() - run: make lesson-check-all if: always() From 951140e21659bf1676d78e3a0e59a340e448a49d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Michonneau?= Date: Fri, 8 Jan 2021 17:15:59 +0100 Subject: [PATCH 020/113] pin ubuntu version to 20.04 (#540) Co-authored-by: Zhian N. Kamvar --- .github/workflows/template.yml | 13 +++++++++---- .github/workflows/website.yml | 6 +++--- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/.github/workflows/template.yml b/.github/workflows/template.yml index 0fe9fd53..7e86e02e 100644 --- a/.github/workflows/template.yml +++ b/.github/workflows/template.yml @@ -12,9 +12,9 @@ jobs: fail-fast: false matrix: lesson: [swcarpentry/shell-novice, datacarpentry/r-intro-geospatial, librarycarpentry/lc-git] - os: [ubuntu-latest, macos-latest, windows-latest] + os: [ubuntu-20.04, macos-latest, windows-latest] include: - - os: ubuntu-latest + - os: ubuntu-20.04 os-name: Ubuntu - os: macos-latest os-name: macOS @@ -30,7 +30,7 @@ jobs: run: shell: bash # forces 'Git for Windows' on Windows env: - RSPM: 'https://packagemanager.rstudio.com/cran/__linux__/bionic/latest' + RSPM: 'https://packagemanager.rstudio.com/cran/__linux__/focal/latest' steps: - name: Set up Ruby uses: actions/setup-ruby@v1 @@ -118,6 +118,11 @@ jobs: key: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-${{ hashFiles('.github/depends.Rds') }} restore-keys: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1- + - name: Install stringi from source + if: runner.os == 'Linux' && steps.check-rmd.outputs.count != 0 + run: install.packages('stringi', repos='https://cloud.r-project.org') + shell: Rscript {0} + - name: Install system dependencies for R packages if: runner.os == 'Linux' && steps.check-rmd.outputs.count != 0 working-directory: lesson @@ -125,7 +130,7 @@ jobs: while read -r cmd do eval sudo $cmd - done < <(Rscript -e 'cat(remotes::system_requirements("ubuntu", "18.04"), sep = "\n")') + done < <(Rscript -e 'cat(remotes::system_requirements("ubuntu", "20.04"), sep = "\n")') - run: make site working-directory: lesson diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index 70deeb26..b67e07ec 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/website.yml @@ -8,9 +8,9 @@ on: jobs: build-website: if: ${{ !endsWith(github.repository, '/styles') }} - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 env: - RSPM: "https://packagemanager.rstudio.com/cran/__linux__/bionic/latest" + RSPM: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest" GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} defaults: run: @@ -81,7 +81,7 @@ jobs: while read -r cmd do eval sudo $cmd - done < <(Rscript -e 'cat(remotes::system_requirements("ubuntu", "18.04"), sep = "\n")') + done < <(Rscript -e 'cat(remotes::system_requirements("ubuntu", "20.04"), sep = "\n")') - name: Render the markdown and confirm that the site can be built run: make site From 2cd3c9c1a2499ac7b7c3b9a80995eb643b917960 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Michonneau?= Date: Fri, 8 Jan 2021 17:18:15 +0100 Subject: [PATCH 021/113] GitHub Actions: cache required R packages (#534) --- .github/workflows/template.yml | 2 +- .github/workflows/website.yml | 17 +++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/.github/workflows/template.yml b/.github/workflows/template.yml index 7e86e02e..84015e4d 100644 --- a/.github/workflows/template.yml +++ b/.github/workflows/template.yml @@ -96,7 +96,7 @@ jobs: - name: Install needed packages if: steps.check-rmd.outputs.count != 0 run: | - install.packages(c('remotes', 'rprojroot', 'renv', 'desc', 'rmarkdown', 'knitr')) + install.packages(setdiff(c('remotes', 'rprojroot', 'renv', 'desc', 'rmarkdown', 'knitr'), rownames(installed.packages()))) shell: Rscript {0} - name: Query dependencies diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index b67e07ec..59e32352 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/website.yml @@ -51,10 +51,18 @@ jobs: with: r-version: 'release' + - name: Cache R packages + if: steps.check-rmd.outputs.count != 0 + uses: actions/cache@v1 + with: + path: ${{ env.R_LIBS_USER }} + key: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-${{ hashFiles('.github/depends.Rds') }} + restore-keys: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1- + - name: Install needed packages if: steps.check-rmd.outputs.count != 0 run: | - install.packages(c('remotes', 'rprojroot', 'renv', 'desc', 'rmarkdown', 'knitr')) + install.packages(setdiff(c('remotes', 'rprojroot', 'renv', 'desc', 'rmarkdown', 'knitr'), rownames(installed.packages())) shell: Rscript {0} - name: Query dependencies @@ -67,13 +75,6 @@ jobs: writeLines(sprintf("R-%i.%i", getRversion()$major, getRversion()$minor), ".github/R-version") shell: Rscript {0} - - name: Cache R packages - if: steps.check-rmd.outputs.count != 0 - uses: actions/cache@v1 - with: - path: ${{ env.R_LIBS_USER }} - key: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-${{ hashFiles('.github/depends.Rds') }} - restore-keys: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1- - name: Install system dependencies for R packages if: steps.check-rmd.outputs.count != 0 From c92e47cf32e2372018e3273fc0a5408c045f9cd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Michonneau?= Date: Fri, 8 Jan 2021 16:34:07 -0500 Subject: [PATCH 022/113] add missing parenthesis --- .github/workflows/website.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index 59e32352..fc08b084 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/website.yml @@ -62,7 +62,7 @@ jobs: - name: Install needed packages if: steps.check-rmd.outputs.count != 0 run: | - install.packages(setdiff(c('remotes', 'rprojroot', 'renv', 'desc', 'rmarkdown', 'knitr'), rownames(installed.packages())) + install.packages(setdiff(c('remotes', 'rprojroot', 'renv', 'desc', 'rmarkdown', 'knitr'), rownames(installed.packages()))) shell: Rscript {0} - name: Query dependencies From bfd8c0069644ffbd256ed3b5801f5e808ed58226 Mon Sep 17 00:00:00 2001 From: Trevor Keller Date: Mon, 11 Jan 2021 11:32:06 -0500 Subject: [PATCH 023/113] Add incubator option for carpentry field. (#542) Closes #541 --- bin/lesson_check.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/lesson_check.py b/bin/lesson_check.py index b046b34c..25388d39 100644 --- a/bin/lesson_check.py +++ b/bin/lesson_check.py @@ -176,7 +176,7 @@ def check_config(reporter, source_dir): reporter.check_field(config_file, 'configuration', config, 'kind', 'lesson') reporter.check_field(config_file, 'configuration', - config, 'carpentry', ('swc', 'dc', 'lc', 'cp')) + config, 'carpentry', ('swc', 'dc', 'lc', 'cp', 'incubator')) reporter.check_field(config_file, 'configuration', config, 'title') reporter.check_field(config_file, 'configuration', config, 'email') From 740773af3bc0a53d16daf1a2e859330ccdb4a226 Mon Sep 17 00:00:00 2001 From: Renato Alves Date: Wed, 27 Jan 2021 20:49:53 +0100 Subject: [PATCH 024/113] .editorconfig: don't trim trailing spaces in markdown --- .editorconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/.editorconfig b/.editorconfig index 1d7d564d..5bf4860b 100644 --- a/.editorconfig +++ b/.editorconfig @@ -9,6 +9,7 @@ trim_trailing_whitespace = true indent_size = 2 indent_style = space max_line_length = 100 # Please keep this in sync with bin/lesson_check.py! +trim_trailing_whitespace = false # keep trailing spaces in markdown - 2+ spaces are translated to a hard break (
) [*.r] max_line_length = 80 From 5bc7724207e1a25999dfe90096715b34771eabcb Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Wed, 27 Jan 2021 14:49:00 -0600 Subject: [PATCH 025/113] lesson.scss: HTML block carpentries/styles#519 --- assets/css/lesson.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/assets/css/lesson.scss b/assets/css/lesson.scss index 9334e372..9ecd5452 100644 --- a/assets/css/lesson.scss +++ b/assets/css/lesson.scss @@ -68,6 +68,7 @@ div.language-bash::before { content: "Bash"; } div.language-c::before { content: "C"; } div.language-cmake::before { content: "CMake"; } div.language-cpp::before { content: "C++"; } +div.language-html::before { content: "HTML"; } div.language-make::before { content: "Make"; } div.language-matlab::before { content: "MATLAB"; } div.language-python::before { content: "Python"; } From d021e1fc38e38ee9d2b6ad298831aa8d519454a0 Mon Sep 17 00:00:00 2001 From: "Zhian N. Kamvar" Date: Wed, 10 Feb 2021 01:14:24 -0800 Subject: [PATCH 026/113] add patch to clean gh-pages before committing (#545) This will address #544 --- .github/workflows/website.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index fc08b084..cb67828c 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/website.yml @@ -97,6 +97,11 @@ jobs: - name: Commit and Push if: ${{ github.event_name == 'push' && steps.check-rmd.outputs.count != 0 && github.ref != 'refs/heads/gh-pages'}} run: | + # clean up gh-pages + cd gh-pages + git rm -rf . # remove all previous files + git restore --staged . # remove things from the stage + cd .. # copy everything into gh-pages site cp -r `ls -A | grep -v 'gh-pages' | grep -v '.git' | grep -v '.bundle/' | grep -v '_site'` gh-pages # move into gh-pages, add, commit, and push @@ -105,7 +110,7 @@ jobs: git config --local user.email "actions@github.com" git config --local user.name "GitHub Actions" git add -A . - git commit --allow-empty -m "[Github Actions] render website (via ${{ github.sha }}" + git commit --allow-empty -m "[Github Actions] render website (via ${{ github.sha }})" git push origin gh-pages # return cd .. From f419f9cdc6945caef5c8881301ea73c8cc6c7ac9 Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Mon, 15 Feb 2021 14:36:29 -0600 Subject: [PATCH 027/113] Fix Kramdown parser crash ... by using GFM (GitHub-flavored Markdown) parser (`kramdown-parser-gfm`) instead of the default one (`kramdown`). The default one fails to produce an AST (Abstract Syntax Tree) when there is no blank line before the line with the opening code fence. Related: - gettalong/kramdown#530 - Python-Markdown/markdown#807 Fixes: carpentries/styles#543 --- .github/workflows/template.yml | 2 +- .github/workflows/website.yml | 2 +- bin/markdown_ast.rb | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/template.yml b/.github/workflows/template.yml index 84015e4d..c1e52b1b 100644 --- a/.github/workflows/template.yml +++ b/.github/workflows/template.yml @@ -44,7 +44,7 @@ jobs: - name: Install GitHub Pages, Bundler, and kramdown gems run: | - gem install github-pages bundler kramdown + gem install github-pages bundler kramdown kramdown-parser-gfm - name: Install Python modules run: | diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index cb67828c..df79f6c5 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/website.yml @@ -28,7 +28,7 @@ jobs: - name: Install GitHub Pages, Bundler, and kramdown gems run: | - gem install github-pages bundler kramdown + gem install github-pages bundler kramdown kramdown-parser-gfm - name: Install Python modules run: | diff --git a/bin/markdown_ast.rb b/bin/markdown_ast.rb index 4fdb6843..2ef3f772 100755 --- a/bin/markdown_ast.rb +++ b/bin/markdown_ast.rb @@ -4,9 +4,10 @@ # Use Kramdown parser to produce AST for Markdown document. require 'kramdown' +require 'kramdown-parser-gfm' require 'json' markdown = $stdin.read -doc = Kramdown::Document.new(markdown) +doc = Kramdown::Document.new(markdown, input: 'GFM', hard_wrap: false) tree = doc.to_hash_a_s_t puts JSON.pretty_generate(tree) From 2a550c74082ccb5e49d1e344c29706c834a44bde Mon Sep 17 00:00:00 2001 From: Andrew Reid Date: Mon, 22 Feb 2021 02:31:24 -0500 Subject: [PATCH 028/113] bin/util.py: Change ruby executable to "bundle exec ruby" Closes: carpentries/styles#547 --- bin/util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/util.py b/bin/util.py index 0e16d869..f3378f6b 100644 --- a/bin/util.py +++ b/bin/util.py @@ -115,7 +115,7 @@ def read_markdown(parser, path): for (i, line) in enumerate(body.split('\n'))] # Parse Markdown. - cmd = 'ruby {0}'.format(parser) + cmd = 'bundle exec ruby {0}'.format(parser) p = Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, close_fds=True, universal_newlines=True, encoding='utf-8') stdout_data, stderr_data = p.communicate(body) From a4e53f948f2572934c64d8b70a654ca6bea814bb Mon Sep 17 00:00:00 2001 From: Bailey Harrington Date: Mon, 22 Feb 2021 13:51:58 +0000 Subject: [PATCH 029/113] Change link colours (#549) ...to make them distinguishable from regular text. And for accessibility! --- assets/css/lesson.scss | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/assets/css/lesson.scss b/assets/css/lesson.scss index 9ecd5452..806315de 100644 --- a/assets/css/lesson.scss +++ b/assets/css/lesson.scss @@ -210,6 +210,20 @@ a code { color: #006cad; } +a:link { + color: #196EBD; +} + +a:active, +a:hover { + outline: 0; + text-decoration: underline; +} + +a:visited { + color: #1AA4DA; +} + code { white-space: nowrap; padding: 2px 5px; From 03fb1a0ffeb998d6921e4c0b00aa887f52b853e6 Mon Sep 17 00:00:00 2001 From: Toby Hodges Date: Thu, 4 Mar 2021 17:54:53 +0100 Subject: [PATCH 030/113] bin/workshop_check.py: update default contact email address --- bin/workshop_check.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/workshop_check.py b/bin/workshop_check.py index 15d954a6..2c8dddf3 100644 --- a/bin/workshop_check.py +++ b/bin/workshop_check.py @@ -17,7 +17,7 @@ # Defaults. CARPENTRIES = ("dc", "swc", "lc", "cp") -DEFAULT_CONTACT_EMAIL = 'admin@software-carpentry.org' +DEFAULT_CONTACT_EMAIL = 'team@carpentries.org' USAGE = 'Usage: "workshop_check.py path/to/root/directory"' From a841a56c896554249ac2d8566d630080defe72b1 Mon Sep 17 00:00:00 2001 From: Michael Joseph Date: Fri, 5 Mar 2021 11:28:26 -0500 Subject: [PATCH 031/113] Gemfile: add 'webrick' dependency for Ruby 3.0.0 and above Fixes carpentries/styles#552 --- Gemfile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Gemfile b/Gemfile index 41c97a9a..8d69492b 100644 --- a/Gemfile +++ b/Gemfile @@ -8,3 +8,7 @@ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" } ruby '>=2.7.1' gem 'github-pages', group: :jekyll_plugins + +if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.0.0') + gem 'webrick', '>= 1.6.1' +end \ No newline at end of file From 32f7bd1e80eda16ba33bdebb1fe0ad5896a606e8 Mon Sep 17 00:00:00 2001 From: "Zhian N. Kamvar" Date: Wed, 10 Mar 2021 10:21:57 -0800 Subject: [PATCH 032/113] lesson_check.py allow for missing life_cycle This will fix https://github.com/carpentries/styles/issues/556 --- bin/lesson_check.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/bin/lesson_check.py b/bin/lesson_check.py index 25388d39..889596c2 100644 --- a/bin/lesson_check.py +++ b/bin/lesson_check.py @@ -188,7 +188,10 @@ def check_config(reporter, source_dir): reporter.check(defaults in config.get('defaults', []), 'configuration', '"root" not set to "." in configuration') - return config['life_cycle'] + if 'life_cycle' in config: + return config['life_cycle'] + else + return None def check_source_rmd(reporter, source_dir, parser): """Check that Rmd episode files include `source: Rmd`""" From b2f42c2ed2b9aafcb312bab9ca21fd1701984c5a Mon Sep 17 00:00:00 2001 From: "Zhian N. Kamvar" Date: Wed, 10 Mar 2021 11:12:58 -0800 Subject: [PATCH 033/113] update with Maxim's suggestion --- bin/lesson_check.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/bin/lesson_check.py b/bin/lesson_check.py index 889596c2..193f994f 100644 --- a/bin/lesson_check.py +++ b/bin/lesson_check.py @@ -188,10 +188,9 @@ def check_config(reporter, source_dir): reporter.check(defaults in config.get('defaults', []), 'configuration', '"root" not set to "." in configuration') - if 'life_cycle' in config: - return config['life_cycle'] - else - return None + if 'life_cycle' not in config: + config['life_cycle'] = None + return config['life_cycle'] def check_source_rmd(reporter, source_dir, parser): """Check that Rmd episode files include `source: Rmd`""" From 0554a8d099cbc999121e36d59f402ea90fa20269 Mon Sep 17 00:00:00 2001 From: "Zhian N. Kamvar" Date: Thu, 11 Mar 2021 09:08:08 -0800 Subject: [PATCH 034/113] Add catch for None type code block in lesson_check There are times when the AST is malformed and does not emit a class for the code element. We do not want the parser to crash when this happens, but we also want to notify ourselves that the AST is malformed. This should not result in an error because as we saw in https://github.com/carpentries/styles/issues/543, the parser itself can cause these malformations when the lesson itself renders well. Even though we fixed the previous issue with an updated parser, problems still persist: https://github.com/swcarpentry/r-novice-gapminder/pull/696#issuecomment-796265728 I fully admit that this is a kludge. --- bin/lesson_check.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bin/lesson_check.py b/bin/lesson_check.py index 193f994f..4aa1eec9 100644 --- a/bin/lesson_check.py +++ b/bin/lesson_check.py @@ -392,10 +392,14 @@ def check_codeblock_classes(self): for node in self.find_all(self.doc, {'type': 'codeblock'}): cls = self.get_val(node, 'attr', 'class') - self.reporter.check(cls in KNOWN_CODEBLOCKS or cls.startswith('language-'), + self.reporter.check(cls is not none and (cls in KNOWN_CODEBLOCKS or + cls.startswith('language-')), (self.filename, self.get_loc(node)), 'Unknown or missing code block type {0}', cls) + if not cls is None: + print("NOTE: The AST was malformed and needs to be investigated") + print(self.filename, self.get_loc(node)) def check_defined_link_references(self): """Check that defined links resolve in the file. From cce6a66f4b0273f703730e9729592a2dcc45f645 Mon Sep 17 00:00:00 2001 From: "Zhian N. Kamvar" Date: Thu, 11 Mar 2021 09:32:54 -0800 Subject: [PATCH 035/113] fix syntax I've removed the print condition, because it will just result in an error no matter what (sigh) --- bin/lesson_check.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/bin/lesson_check.py b/bin/lesson_check.py index 4aa1eec9..74d50549 100644 --- a/bin/lesson_check.py +++ b/bin/lesson_check.py @@ -392,14 +392,11 @@ def check_codeblock_classes(self): for node in self.find_all(self.doc, {'type': 'codeblock'}): cls = self.get_val(node, 'attr', 'class') - self.reporter.check(cls is not none and (cls in KNOWN_CODEBLOCKS or + self.reporter.check(cls is not None and (cls in KNOWN_CODEBLOCKS or cls.startswith('language-')), (self.filename, self.get_loc(node)), 'Unknown or missing code block type {0}', cls) - if not cls is None: - print("NOTE: The AST was malformed and needs to be investigated") - print(self.filename, self.get_loc(node)) def check_defined_link_references(self): """Check that defined links resolve in the file. From 905d24a8644df9c626a02f639423146e472a96a3 Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Tue, 16 Mar 2021 13:58:05 -0500 Subject: [PATCH 036/113] Makefile: fix 'bundle config' command flags --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 60bd888b..934041b6 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ # Settings MAKEFILES=Makefile $(wildcard *.mk) -JEKYLL=bundle config --local set path .vendor/bundle && bundle install && bundle update && bundle exec jekyll +JEKYLL=bundle config set --local path .vendor/bundle && bundle install && bundle update && bundle exec jekyll PARSER=bin/markdown_ast.rb DST=_site From b43257a1439e31a26d1a2ec63fffdd489c194f77 Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Thu, 18 Mar 2021 17:13:38 -0500 Subject: [PATCH 037/113] Makefile: clean target: remove .vendor, .bundle, Gemfile.lock Clean up: 1. `.vendor` directory where Bundler installs all the gems. 2. `.bundle` directory where Bundler stores its settings. 3. `Gemfile.lock` file generated by the Bundler. --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index 934041b6..30c2b202 100644 --- a/Makefile +++ b/Makefile @@ -68,6 +68,9 @@ clean : @rm -rf ${DST} @rm -rf .sass-cache @rm -rf bin/__pycache__ + @rm -rf .vendor + @rm -rf .bundle + @rm -f Gemfile.lock @find . -name .DS_Store -exec rm {} \; @find . -name '*~' -exec rm {} \; @find . -name '*.pyc' -exec rm {} \; From 39a32f6289cce93f1711a1a454b11b5eb66b1861 Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Thu, 18 Mar 2021 17:17:56 -0500 Subject: [PATCH 038/113] Makefile: silence Docker commands --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 30c2b202..d0be0d18 100644 --- a/Makefile +++ b/Makefile @@ -50,8 +50,8 @@ site : lesson-md ## * docker-serve : use Docker to serve the site docker-serve : - docker pull carpentries/lesson-docker:latest - docker run --rm -it \ + @docker pull carpentries/lesson-docker:latest + @docker run --rm -it \ -v $${PWD}:/home/rstudio \ -p 4000:4000 \ -p 8787:8787 \ From ed77edaea17ac700970da9388d489256d5e3494e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Michonneau?= Date: Fri, 19 Mar 2021 15:26:24 +0100 Subject: [PATCH 039/113] use Ruby's official GH Actions --- .github/workflows/template.yml | 3 ++- .github/workflows/website.yml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/template.yml b/.github/workflows/template.yml index c1e52b1b..810bf2d2 100644 --- a/.github/workflows/template.yml +++ b/.github/workflows/template.yml @@ -33,9 +33,10 @@ jobs: RSPM: 'https://packagemanager.rstudio.com/cran/__linux__/focal/latest' steps: - name: Set up Ruby - uses: actions/setup-ruby@v1 + uses: ruby/setup-ruby@v1 with: ruby-version: '2.7' + bundler-cache: true - name: Set up Python uses: actions/setup-python@v2 diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index df79f6c5..af3519fe 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/website.yml @@ -17,9 +17,10 @@ jobs: shell: bash steps: - name: Set up Ruby - uses: actions/setup-ruby@v1 + uses: ruby/setup-ruby@v1 with: ruby-version: '2.7' + bundler-cache: true - name: Set up Python uses: actions/setup-python@v2 From b46187f7ec0b7cf2cd26ba12509c10e0b2e4bcf6 Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Fri, 19 Mar 2021 10:20:04 -0500 Subject: [PATCH 040/113] Makefile: use SHELL to call bin/knit_lesson.sh --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index d0be0d18..befd7b28 100644 --- a/Makefile +++ b/Makefile @@ -131,7 +131,7 @@ lesson-md : ${RMD_DST} _episodes/%.md: _episodes_rmd/%.Rmd install-rmd-deps @mkdir -p _episodes - @bin/knit_lessons.sh $< $@ + @$(SHELL) bin/knit_lessons.sh $< $@ ## * lesson-check : validate lesson Markdown lesson-check : lesson-fixme From b1ca20a2b2cb65adf101e0a6912c39c10fda17c9 Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Fri, 19 Mar 2021 10:29:26 -0500 Subject: [PATCH 041/113] Makefile: fix up PHONY targets --- Makefile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index befd7b28..9d952810 100644 --- a/Makefile +++ b/Makefile @@ -31,15 +31,14 @@ ifeq (,$(PYTHON)) endif -# Controls -.PHONY : commands clean files - # Default target .DEFAULT_GOAL := commands ## I. Commands for both workshop and lesson websites ## ================================================= +.PHONY: site docker-serve repo-check clean clean-rmd + ## * serve : render website and run a local server serve : lesson-md ${JEKYLL} serve @@ -160,6 +159,8 @@ lesson-fixme : ## IV. Auxililary (plumbing) commands ## ================================================= +.PHONY : commands + ## * commands : show all commands. commands : @sed -n -e '/^##/s|^##[[:space:]]*||p' $(MAKEFILE_LIST) From 943c8d9968f7a9170924513e4e7d4f0a6bf9d0d5 Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Fri, 19 Mar 2021 14:28:40 -0500 Subject: [PATCH 042/113] Fix GitHub actions for lessons in Rmarkdown Specifically, set CRAN repository to https://cran.rstudio.com --- .github/workflows/template.yml | 3 ++- .github/workflows/website.yml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/template.yml b/.github/workflows/template.yml index 810bf2d2..9d7f3b48 100644 --- a/.github/workflows/template.yml +++ b/.github/workflows/template.yml @@ -97,7 +97,8 @@ jobs: - name: Install needed packages if: steps.check-rmd.outputs.count != 0 run: | - install.packages(setdiff(c('remotes', 'rprojroot', 'renv', 'desc', 'rmarkdown', 'knitr'), rownames(installed.packages()))) + packages = setdiff(c('remotes', 'rprojroot', 'renv', 'desc', 'rmarkdown', 'knitr'), rownames(installed.packages())) + install.packages(packages, repo="https://cran.rstudio.com/") shell: Rscript {0} - name: Query dependencies diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index af3519fe..246d4c70 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/website.yml @@ -63,7 +63,8 @@ jobs: - name: Install needed packages if: steps.check-rmd.outputs.count != 0 run: | - install.packages(setdiff(c('remotes', 'rprojroot', 'renv', 'desc', 'rmarkdown', 'knitr'), rownames(installed.packages()))) + packages = setdiff(c('remotes', 'rprojroot', 'renv', 'desc', 'rmarkdown', 'knitr'), rownames(installed.packages())) + install.packages(packages, repo="https://cran.rstudio.com/") shell: Rscript {0} - name: Query dependencies From 4df32a87f2d4ca683b3624e1672c53f1cef10e26 Mon Sep 17 00:00:00 2001 From: Toby Hodges Date: Mon, 22 Mar 2021 11:37:48 +0100 Subject: [PATCH 043/113] apply single shadow to image class --- assets/css/lesson.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/css/lesson.scss b/assets/css/lesson.scss index e5908712..973a67ab 100644 --- a/assets/css/lesson.scss +++ b/assets/css/lesson.scss @@ -302,7 +302,7 @@ span.fold-unfold { img.image-with-shadow { - box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.2), 0 6px 24px 0 rgba(0, 0, 0, 0.19); + box-shadow: 0 6px 24px 0 rgba(0, 0, 0, 0.25); } //---------------------------------------- From 93dfc15b561af3da2c43f378fde19d7720cf4027 Mon Sep 17 00:00:00 2001 From: Toby Hodges Date: Mon, 22 Mar 2021 11:40:54 +0100 Subject: [PATCH 044/113] use grey shadow instead of transparent black --- assets/css/lesson.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/css/lesson.scss b/assets/css/lesson.scss index 973a67ab..bd31caa0 100644 --- a/assets/css/lesson.scss +++ b/assets/css/lesson.scss @@ -302,7 +302,7 @@ span.fold-unfold { img.image-with-shadow { - box-shadow: 0 6px 24px 0 rgba(0, 0, 0, 0.25); + box-shadow: 0 6px 24px 0 #888; } //---------------------------------------- From 4b2036879c88f68e420f101c1cc1c29d2d300ffc Mon Sep 17 00:00:00 2001 From: Toby Hodges Date: Tue, 23 Mar 2021 14:44:23 +0100 Subject: [PATCH 045/113] expand image-with-shadow selection --- assets/css/lesson.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/assets/css/lesson.scss b/assets/css/lesson.scss index bd31caa0..fe174ab8 100644 --- a/assets/css/lesson.scss +++ b/assets/css/lesson.scss @@ -301,6 +301,7 @@ span.fold-unfold { } +p.image-with-shadow img, img.image-with-shadow { box-shadow: 0 6px 24px 0 #888; } From 5a010aba8c26166e8d556945d35901ff391b3763 Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Tue, 23 Mar 2021 09:15:33 -0500 Subject: [PATCH 046/113] Makefile: don't fail when Python isn't found --- Makefile | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index 9d952810..8b02ab11 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ DST=_site PYTHON3_EXE := $(shell which python3 2>/dev/null) ifneq (, $(PYTHON3_EXE)) ifeq (,$(findstring Microsoft/WindowsApps/python3,$(subst \,/,$(PYTHON3_EXE)))) - PYTHON := python3 + PYTHON := $(PYTHON3_EXE) endif endif @@ -21,12 +21,13 @@ ifeq (,$(PYTHON)) ifneq (, $(PYTHON_EXE)) PYTHON_VERSION_FULL := $(wordlist 2,4,$(subst ., ,$(shell python --version 2>&1))) PYTHON_VERSION_MAJOR := $(word 1,${PYTHON_VERSION_FULL}) - ifneq (3, ${PYTHON_VERSION_MAJOR}) - $(error "Your system does not appear to have Python 3 installed.") + ifeq (3, ${PYTHON_VERSION_MAJOR}) + PYTHON := $(PYTHON_EXE) + else + PYTHON_NOTE = "Your system does not appear to have Python 3 installed." endif - PYTHON := python else - $(error "Your system does not appear to have any Python installed.") + PYTHON_NOTE = "Your system does not appear to have any Python installed." endif endif @@ -59,7 +60,7 @@ docker-serve : carpentries/lesson-docker:latest ## * repo-check : check repository settings -repo-check : +repo-check : python @${PYTHON} bin/repo_check.py -s . ## * clean : clean up junk files @@ -87,7 +88,7 @@ clean-rmd : .PHONY : workshop-check ## * workshop-check : check workshop homepage -workshop-check : +workshop-check : python @${PYTHON} bin/workshop_check.py . @@ -133,15 +134,15 @@ _episodes/%.md: _episodes_rmd/%.Rmd install-rmd-deps @$(SHELL) bin/knit_lessons.sh $< $@ ## * lesson-check : validate lesson Markdown -lesson-check : lesson-fixme +lesson-check : python lesson-fixme @${PYTHON} bin/lesson_check.py -s . -p ${PARSER} -r _includes/links.md ## * lesson-check-all : validate lesson Markdown, checking line lengths and trailing whitespace -lesson-check-all : +lesson-check-all : python @${PYTHON} bin/lesson_check.py -s . -p ${PARSER} -r _includes/links.md -l -w --permissive ## * unittest : run unit tests on checking tools -unittest : +unittest : python @${PYTHON} bin/test_lesson_check.py ## * lesson-files : show expected names of generated files for debugging @@ -159,8 +160,15 @@ lesson-fixme : ## IV. Auxililary (plumbing) commands ## ================================================= -.PHONY : commands +.PHONY : commands python ## * commands : show all commands. commands : @sed -n -e '/^##/s|^##[[:space:]]*||p' $(MAKEFILE_LIST) + +python : +ifeq (, $(PYTHON)) + $(error $(PYTHON_NOTE)) +else + @: +endif From 1bad008530933b2b15afefd0631f258c2c3e1b8a Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Sat, 27 Mar 2021 13:20:29 -0500 Subject: [PATCH 047/113] bin/dependencies.R: handle 'no packages were specified' error Fixes the following issue: ``` $ make site lib paths: /Library/Frameworks/R.framework/Versions/3.5/Resources/library Error in install.packages(missing_pkgs, lib = lib, repos = repos) : no packages were specified Calls: install_required_packages -> install.packages Execution halted make: *** [install-rmd-deps] Error 1 ``` --- bin/dependencies.R | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/bin/dependencies.R b/bin/dependencies.R index 640b3e24..ee9d38a8 100644 --- a/bin/dependencies.R +++ b/bin/dependencies.R @@ -5,10 +5,10 @@ install_required_packages <- function(lib = NULL, repos = getOption("repos", def } message("lib paths: ", paste(lib, collapse = ", ")) - missing_pkgs <- setdiff( - c("rprojroot", "desc", "remotes", "renv"), - rownames(installed.packages(lib.loc = lib)) - ) + required_pkgs <- c("rprojroot", "desc", "remotes", "renv") + installed_pkgs <- rownames(installed.packages(lib.loc = lib)) + missing_pkgs <- setdiff(required_pkgs, installed_pkgs) + # The default installation of R will have "@CRAN@" as the default repository, which directs contrib.url() to either # force the user to choose a mirror if interactive or fail if not. Since we are not interactve, we need to force the # mirror here. @@ -16,8 +16,9 @@ install_required_packages <- function(lib = NULL, repos = getOption("repos", def repos <- c(CRAN = "https://cran.rstudio.com/") } - install.packages(missing_pkgs, lib = lib, repos = repos) - + if (length(missing_pkgs) != 0) { + install.packages(missing_pkgs, lib = lib, repos = repos) + } } find_root <- function() { From 4df505249a27191c3475102cde4c150b0a131102 Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Wed, 14 Apr 2021 00:42:49 -0500 Subject: [PATCH 048/113] Don't check links.md in lessons that use remote theme Fixes carpentries/styles#570 --- bin/lesson_check.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/bin/lesson_check.py b/bin/lesson_check.py index 74d50549..249464fd 100644 --- a/bin/lesson_check.py +++ b/bin/lesson_check.py @@ -113,7 +113,10 @@ def main(): if life_cycle == "pre-alpha": args.permissive = True check_source_rmd(args.reporter, args.source_dir, args.parser) - args.references = read_references(args.reporter, args.reference_path) + + args.references = {} + if not using_remote_theme(): + args.references = read_references(args.reporter, args.reference_path) docs = read_all_markdown(args.source_dir, args.parser) check_fileset(args.source_dir, args.reporter, list(docs.keys())) @@ -167,6 +170,10 @@ def parse_args(): return args +def using_remote_theme(): + config_file = os.path.join(source_dir, '_config.yml') + config = load_yaml(config_file) + return 'remote_theme' in config def check_config(reporter, source_dir): """Check configuration file.""" @@ -493,7 +500,8 @@ def check(self): """Run extra tests.""" super().check() - self.check_reference_inclusion() + if not using_remote_theme(): + self.check_reference_inclusion() def check_metadata(self): super().check_metadata() From 9a73007fcaa85d62dbcfe399acb9de29da4d33f4 Mon Sep 17 00:00:00 2001 From: Toby Hodges Date: Wed, 14 Apr 2021 21:25:35 +0200 Subject: [PATCH 049/113] add link references to code_of_conduct.md (#572) --- CODE_OF_CONDUCT.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index c3b96690..2cf1133b 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -8,4 +8,5 @@ we pledge to follow the [Carpentry Code of Conduct][coc]. Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by following our [reporting guidelines][coc-reporting]. -{% include links.md %} +[coc]: https://docs.carpentries.org/topic_folders/policies/code-of-conduct.html +[coc-reporting]: https://docs.carpentries.org/topic_folders/policies/incident-reporting.html From ced22447d6a8f97bc26d7eb5af166392d1e4e902 Mon Sep 17 00:00:00 2001 From: Alan O'Callaghan Date: Thu, 15 Apr 2021 01:08:10 +0100 Subject: [PATCH 050/113] Update links.md --- _includes/links.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_includes/links.md b/_includes/links.md index abe60930..7f8e0026 100644 --- a/_includes/links.md +++ b/_includes/links.md @@ -12,7 +12,7 @@ [cran-stringr]: https://cran.r-project.org/package=stringr [dc-lessons]: http://www.datacarpentry.org/lessons/ [email]: mailto:team@carpentries.org -[github-importer]: https://import.github.com/ +[github-importer]: https://import2.github.com/ [importer]: https://github.com/new/import [jekyll-collection]: https://jekyllrb.com/docs/collections/ [jekyll-install]: https://jekyllrb.com/docs/installation/ From 494e2d60064578d1e5a45df0734ef9b8865c3e29 Mon Sep 17 00:00:00 2001 From: "Zhian N. Kamvar" Date: Wed, 14 Apr 2021 17:38:35 -0700 Subject: [PATCH 051/113] add source_dir argument This will fix https://github.com/carpentries/styles/issues/576 --- bin/lesson_check.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/lesson_check.py b/bin/lesson_check.py index 249464fd..cb38e5b2 100644 --- a/bin/lesson_check.py +++ b/bin/lesson_check.py @@ -115,7 +115,7 @@ def main(): check_source_rmd(args.reporter, args.source_dir, args.parser) args.references = {} - if not using_remote_theme(): + if not using_remote_theme(args.source_dir): args.references = read_references(args.reporter, args.reference_path) docs = read_all_markdown(args.source_dir, args.parser) @@ -170,7 +170,7 @@ def parse_args(): return args -def using_remote_theme(): +def using_remote_theme(source_dir): config_file = os.path.join(source_dir, '_config.yml') config = load_yaml(config_file) return 'remote_theme' in config From 01fa7e60d9672aacc405121bdacf835e10ae723c Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Fri, 16 Apr 2021 13:22:09 -0500 Subject: [PATCH 052/113] Improved relative_root_path --- _includes/base_path.html | 54 +++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/_includes/base_path.html b/_includes/base_path.html index 7efb3570..41139587 100644 --- a/_includes/base_path.html +++ b/_includes/base_path.html @@ -1,27 +1,41 @@ -{% comment %} -This is adapted from: https://ricostacruz.com/til/relative-paths-in-jekyll +{%- comment -%} +When the website is built by GitHub Pages, +'site.url' is set to 'https://username.github.io' +'site.baseurl' is set to '/lesson-name' -`page.url` gives the URL of the current page with a leading /: +When we start a local server using `jekyll serve`, +'site.url' is set to 'http://localhost:4000' and +'site.baseurl' is empty. -- when the URL ends with the extension (e.g., /foo/bar.html) then we can get - the depth by counting the number of / and remove - 1 -- when the URL ends with a / (e.g. /foo/bar/) then the number / gives the depth - directly -{% endcomment %} +In both of the above cases we set 'relative_root_path' to 'site.url + site.baseurl'. -{% assign relative_root_path = '' %} +When we build a website locally with `jekyll build`, +both 'site.url' and 'site.baseurl' are empty. +This case is handled by the last 'else' in the code below. +The logic there follows the (adapted) instructions found at: + https://ricostacruz.com/til/relative-paths-in-jekyll -{% assign last_char = page.url | slice: -1 %} + `page.url` gives the URL of the current page with a leading /: -{% if last_char == "/"} -{% assign offset = 0 %} -{% else %} -{% assign offset = 1 %} -{% endif %} + - when the URL ends with an extension (e.g., /foo/bar.html), + we can get the 'depth' of the page by counting the number of + forward slashes ('/') and subtracting 1 + - when the URL ends with a forward slash (e.g. /foo/bar/), + we can get the depth of the page by counting the number of / +{%- endcomment -%} -{% assign depth = page.url | split: '/' | size | minus: offset %} -{% if depth <= 1 %}{% assign relative_root_path = '.' %} -{% elsif depth == 2 %}{% assign relative_root_path = '..' %} -{% elsif depth == 3 %}{% assign relative_root_path = '../..' %} -{% elsif depth == 4 %}{% assign relative_root_path = '../../..' %} +{% if site.url %} + {% assign relative_root_path = site.url | append: site.baseurl %} +{% else %} + {% assign last_char = page.url | slice: -1 %} + {% if last_char == "/" %} + {% assign offset = 0 %} + {% else %} + {% assign offset = 1 %} + {% endif %} + {% assign depth = page.url | split: '/' | size | minus: offset %} + {% if depth <= 1 %}{% assign relative_root_path = '.' %} + {% elsif depth == 2 %}{% assign relative_root_path = '..' %} + {% else %}{% capture relative_root_path %}..{% for i in (3..depth) %}/..{% endfor %}{% endcapture %} + {% endif %} {% endif %} From 8541f28df500c8cf546bbf8455bc26bf829ddd2d Mon Sep 17 00:00:00 2001 From: Toby Hodges Date: Sat, 17 Apr 2021 02:13:35 +0200 Subject: [PATCH 053/113] update contributing guide --- bin/boilerplate/CONTRIBUTING.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/bin/boilerplate/CONTRIBUTING.md b/bin/boilerplate/CONTRIBUTING.md index f5158b02..a997b350 100644 --- a/bin/boilerplate/CONTRIBUTING.md +++ b/bin/boilerplate/CONTRIBUTING.md @@ -70,7 +70,7 @@ There are many ways to contribute, from writing new exercises and improving existing ones to updating or filling in the documentation and submitting [bug reports][issues] -about things that do not work, aren not clear, or are missing. +about things that do not work, are not clear, or are missing. If you are looking for ideas, please see the 'Issues' tab for a list of issues associated with this repository, or you may also look at the issues for [Data Carpentry][dc-issues], @@ -94,7 +94,7 @@ and (b) explain what you would take out to make room for it. The first encourages contributors to be honest about requirements; the second, to think hard about priorities. -We are also not looking for exercises or other material that only run on one platform. +We are also not looking for exercises or other material that will only run on one platform. Our workshops typically contain a mixture of Windows, macOS, and Linux users; in order to be usable, our lessons must run equally well on all three. @@ -104,7 +104,7 @@ our lessons must run equally well on all three. If you choose to contribute via GitHub, you may want to look at [How to Contribute to an Open Source Project on GitHub][how-contribute]. To manage changes, we follow [GitHub flow][github-flow]. -Each lesson has two maintainers who review issues and pull requests or encourage others to do so. +Each lesson has at least two maintainers who review issues and pull requests or encourage others to do so. The maintainers are community volunteers and have final say over what gets merged into the lesson. To use the web interface for contributing to a lesson: @@ -128,12 +128,12 @@ repository for reference while revising. ## Other Resources -General discussion of [Software Carpentry][swc-site] and [Data Carpentry][dc-site] +General discussion of [Software Carpentry][swc-site], [Data Carpentry][dc-site], and [Library Carpentry][lc-site] happens on the [discussion mailing list][discuss-list], which everyone is welcome to join. You can also [reach us by email][email]. -[email]: mailto:admin@software-carpentry.org +[email]: mailto:team@carpentries.org [dc-issues]: https://github.com/issues?q=user%3Adatacarpentry [dc-lessons]: http://datacarpentry.org/lessons/ [dc-site]: http://datacarpentry.org/ From a56a34e029802273f715990da258e3cc750b6588 Mon Sep 17 00:00:00 2001 From: Benson Muite Date: Tue, 20 Apr 2021 18:44:22 +0300 Subject: [PATCH 054/113] add further languages for box titles (#580) Will be useful for HPC-Carpentry lessons, GPU programming lesson as well as Julia lessons which are currently in the incubator. --- assets/css/lesson.scss | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/assets/css/lesson.scss b/assets/css/lesson.scss index fe174ab8..68a35508 100644 --- a/assets/css/lesson.scss +++ b/assets/css/lesson.scss @@ -64,16 +64,32 @@ div.error::before { background-color: #ffebe6; content: "Error"; } div.warning:before { background-color: #f8f4e8; content:" Warning"; } div.output::before { background-color: #efefef; content: "Output"; } -div.language-bash::before { content: "Bash"; } -div.language-c::before { content: "C"; } -div.language-cmake::before { content: "CMake"; } -div.language-cpp::before { content: "C++"; } -div.language-html::before { content: "HTML"; } -div.language-make::before { content: "Make"; } -div.language-matlab::before { content: "MATLAB"; } -div.language-python::before { content: "Python"; } -div.language-r::before { content: "R"; } -div.language-sql::before { content: "SQL"; } +div.language-basic::before { content: "Basic"; } +div.language-bash::before { content: "Bash"; } +div.language-c::before { content: "C"; } +div.language-chapel::before { content: "Chapel"; } +div.language-cmake::before { content: "CMake"; } +div.language-cpp::before { content: "C++"; } +div.language-cuda::before { content: "Cuda"; } +div.language-d::before { content: "D"; } +div.language-fortran::before { content: "Fortran"; } +div.language-go::before { content: "Go"; } +div.language-html::before { content: "HTML"; } +div.language-java::before { content: "Java"; } +div.language-julia::before { content: "Julia"; } +div.language-kotlin::before { content: "Kotlin"; } +div.language-lua::before { content: "Lua"; } +div.language-make::before { content: "Make"; } +div.language-matlab::before { content: "MATLAB"; } +div.language-opencl::before { content: "OpenCL"; } +div.language-perl::before { content: "Perl"; } +div.language-python::before { content: "Python"; } +div.language-r::before { content: "R"; } +div.language-ruby::before { content: "Ruby"; } +div.language-rust::before { content: "Rust"; } +div.language-scala::before { content: "Scala"; } +div.language-sql::before { content: "SQL"; } +div.language-vulkan::before { content: "Vulkan"; } // Tab panels are used on Setup pages to show instructions for different Operating Systems .tab-pane { From 0c927577002fba1f89c7db24e736d3fca14a34fa Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Wed, 21 Apr 2021 10:13:02 -0500 Subject: [PATCH 055/113] bin/lesson_check.py: allow comments and empty lines in links.md --- bin/lesson_check.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/bin/lesson_check.py b/bin/lesson_check.py index cb38e5b2..4245d218 100644 --- a/bin/lesson_check.py +++ b/bin/lesson_check.py @@ -227,7 +227,17 @@ def read_references(reporter, ref_path): with open(ref_path, 'r', encoding='utf-8') as reader: for (num, line) in enumerate(reader, 1): - if P_INTERNAL_INCLUDE_LINK.search(line): continue + # Skip empty lines + if length(line.strip()) == 0: + continue + + # Skip HTML comments + if line.strip().startswith(""): + continue + + # Skip Liquid's {% include ... %} lines + if P_INTERNAL_INCLUDE_LINK.search(line): + continue m = P_INTERNAL_LINK_DEF.search(line) From 7e9492870bb5f2ca34ca4a2a078744187d2f5add Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Thu, 22 Apr 2021 15:09:31 -0500 Subject: [PATCH 056/113] bin/lesson_check.py: one more fix for using_remote_theme() --- bin/lesson_check.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/lesson_check.py b/bin/lesson_check.py index cb38e5b2..bb97c5b9 100644 --- a/bin/lesson_check.py +++ b/bin/lesson_check.py @@ -500,7 +500,7 @@ def check(self): """Run extra tests.""" super().check() - if not using_remote_theme(): + if not using_remote_theme(args.source_dir): self.check_reference_inclusion() def check_metadata(self): From ac0a2bf5e0761f58a1844ce40c5b3335b4f24606 Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Wed, 21 Apr 2021 17:27:02 -0500 Subject: [PATCH 057/113] Template workflow: add two more lessons --- .github/workflows/template.yml | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/.github/workflows/template.yml b/.github/workflows/template.yml index 9d7f3b48..5cdb8362 100644 --- a/.github/workflows/template.yml +++ b/.github/workflows/template.yml @@ -8,14 +8,17 @@ jobs: name: ${{ matrix.lesson-name }} (${{ matrix.os-name }}) if: github.repository == 'carpentries/styles' runs-on: ${{ matrix.os }} + continue-on-error: ${{ matrix.experimental }} strategy: fail-fast: false matrix: lesson: [swcarpentry/shell-novice, datacarpentry/r-intro-geospatial, librarycarpentry/lc-git] os: [ubuntu-20.04, macos-latest, windows-latest] + experimental: [false] + remote-theme: [false] include: - os: ubuntu-20.04 - os-name: Ubuntu + os-name: Linux - os: macos-latest os-name: macOS - os: windows-latest @@ -26,6 +29,17 @@ jobs: lesson-name: (DC) R Intro Geospatial - lesson: librarycarpentry/lc-git lesson-name: (LC) Intro to Git + - lesson: datacarpentry/astronomy-python + lesson-name: (DC) Foundations of Astronomical Data Science + experimental: true + os: ubuntu-20.04 + os-name: Linux + remote-theme: true + - lesson: carpentries/lesson-example + lesson-name: (CP) Lesson Example + experimental: false + os: ubuntu-20.04 + os-name: Linux defaults: run: shell: bash # forces 'Git for Windows' on Windows @@ -72,6 +86,7 @@ jobs: fi - name: Sync lesson with carpentries/styles + if: ${{ ! matrix.remote-theme }} working-directory: lesson run: | git config --global user.email "team@carpentries.org" From 091ecf784ce28f987095d201a3b2730a2b6b2dd3 Mon Sep 17 00:00:00 2001 From: "Zhian N. Kamvar" Date: Thu, 22 Apr 2021 12:03:52 -0700 Subject: [PATCH 058/113] add make lesson-check-all step --- .github/workflows/template.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/template.yml b/.github/workflows/template.yml index 5cdb8362..5598268d 100644 --- a/.github/workflows/template.yml +++ b/.github/workflows/template.yml @@ -150,4 +150,5 @@ jobs: done < <(Rscript -e 'cat(remotes::system_requirements("ubuntu", "20.04"), sep = "\n")') - run: make site + - run: make lesson-check-all working-directory: lesson From 902705d117779316df1947093731446fa94049f2 Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Thu, 22 Apr 2021 16:29:25 -0500 Subject: [PATCH 059/113] Set working directory for the 'make site' step --- .github/workflows/template.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/template.yml b/.github/workflows/template.yml index 5598268d..62bd938b 100644 --- a/.github/workflows/template.yml +++ b/.github/workflows/template.yml @@ -150,5 +150,7 @@ jobs: done < <(Rscript -e 'cat(remotes::system_requirements("ubuntu", "20.04"), sep = "\n")') - run: make site + working-directory: lesson + - run: make lesson-check-all working-directory: lesson From d3f553d205fd7dfb71998f2ac6f4072e072ebeda Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Wed, 21 Apr 2021 17:25:44 -0500 Subject: [PATCH 060/113] Template workflow: smarter syncing with the styles repo Current syncing procedure that used in the Template workflow fails for: 1. Lessons that are, in fact, nsync with the styles repo. 2. For lessons that use The Carpentries' remote theme and have deleted some of the files. This PR makes this step a little bit more intelligent and takes into account the above two scenarios. --- .github/workflows/template.yml | 48 +++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/.github/workflows/template.yml b/.github/workflows/template.yml index 62bd938b..a4e800a1 100644 --- a/.github/workflows/template.yml +++ b/.github/workflows/template.yml @@ -15,7 +15,6 @@ jobs: lesson: [swcarpentry/shell-novice, datacarpentry/r-intro-geospatial, librarycarpentry/lc-git] os: [ubuntu-20.04, macos-latest, windows-latest] experimental: [false] - remote-theme: [false] include: - os: ubuntu-20.04 os-name: Linux @@ -34,7 +33,6 @@ jobs: experimental: true os: ubuntu-20.04 os-name: Linux - remote-theme: true - lesson: carpentries/lesson-example lesson-name: (CP) Lesson Example experimental: false @@ -76,26 +74,46 @@ jobs: path: lesson fetch-depth: 0 - - name: Determine the proper reference to use - id: styles-ref + - name: Sync lesson with carpentries/styles + working-directory: lesson run: | - if [[ -n "${{ github.event.pull_request.number }}" ]]; then - echo "::set-output name=ref::refs/pull/${{ github.event.pull_request.number }}/head" + if [[ -n "${{ github.event.pull_request.number }}" ]] + then + ref="refs/pull/${{ github.event.pull_request.number }}/head" else - echo "::set-output name=ref::gh-pages" + ref="gh-pages" fi - - name: Sync lesson with carpentries/styles - if: ${{ ! matrix.remote-theme }} - working-directory: lesson - run: | git config --global user.email "team@carpentries.org" git config --global user.name "The Carpentries Bot" + git remote add styles https://github.com/carpentries/styles.git - git config --local remote.styles.tagOpt --no-tags - git fetch styles ${{ steps.styles-ref.outputs.ref }}:styles-ref - git merge -s recursive -Xtheirs --no-commit styles-ref - git commit -m "Sync lesson with carpentries/styles" + git fetch styles $ref:styles-ref + + # Sync up only if necessary + if [[ $(git rev-list --count HEAD..styles-ref) != 0 ]] + then + + # The merge command below might fail for lessons that use remote theme + # https://github.com/carpentries/carpentries-theme + if ! git merge -s recursive -Xtheirs --no-commit styles-ref + then + + # Remove "deleted by us, unmerged" files from the staging area. + # these are the files that were removed from the lesson + # but are still present in the carpentries/styles repo + git rm $(git diff --name-only --diff-filter=DU) + + # If there are still "unmerged" files, + # let's raise an error and look into this more closely + if [[ -n $(git diff --name-only --diff-filter=U) ]] + then + exit 1 + fi + fi + + git commit -m "Sync lesson with carpentries/styles" + fi - name: Look for R-markdown files id: check-rmd From db953ba6cbdced4137c78bf184f47f1f67a78a64 Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Fri, 23 Apr 2021 17:01:29 -0500 Subject: [PATCH 061/113] Apply Zhian's suggestions Co-authored-by: Zhian N. Kamvar --- .github/workflows/template.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/template.yml b/.github/workflows/template.yml index a4e800a1..3e91db6b 100644 --- a/.github/workflows/template.yml +++ b/.github/workflows/template.yml @@ -77,6 +77,7 @@ jobs: - name: Sync lesson with carpentries/styles working-directory: lesson run: | + echo "::group::Fetch Styles" if [[ -n "${{ github.event.pull_request.number }}" ]] then ref="refs/pull/${{ github.event.pull_request.number }}/head" @@ -89,31 +90,38 @@ jobs: git remote add styles https://github.com/carpentries/styles.git git fetch styles $ref:styles-ref - + echo "::endgroup::" + echo "::group::Synchronize Styles" # Sync up only if necessary if [[ $(git rev-list --count HEAD..styles-ref) != 0 ]] then # The merge command below might fail for lessons that use remote theme # https://github.com/carpentries/carpentries-theme + echo "Testing merge using recursive strategy, accepting upstream changes without committing" if ! git merge -s recursive -Xtheirs --no-commit styles-ref then # Remove "deleted by us, unmerged" files from the staging area. # these are the files that were removed from the lesson # but are still present in the carpentries/styles repo + echo "Removing previously deleted files" git rm $(git diff --name-only --diff-filter=DU) # If there are still "unmerged" files, # let's raise an error and look into this more closely if [[ -n $(git diff --name-only --diff-filter=U) ]] then + echo "There were unmerged files in ${{ matrix.lesson-name }}:" + echo "$(git diff --compact-summary --diff-filter=U)" exit 1 fi fi + echo "Committing changes" git commit -m "Sync lesson with carpentries/styles" fi + echo "::endgroup::" - name: Look for R-markdown files id: check-rmd From 973177ebc0a64ed53ba78a36e70be8929ba067de Mon Sep 17 00:00:00 2001 From: Alan O'Callaghan Date: Tue, 27 Apr 2021 21:56:58 +0100 Subject: [PATCH 062/113] add math support with katex (#573) --- _includes/javascript.html | 16 ++++++++++++++++ _layouts/base.html | 3 +++ assets/css/katex.min.css | 1 + assets/js/katex-auto-render.min.js | 1 + assets/js/katex.min.js | 1 + 5 files changed, 22 insertions(+) create mode 100644 assets/css/katex.min.css create mode 100644 assets/js/katex-auto-render.min.js create mode 100644 assets/js/katex.min.js diff --git a/_includes/javascript.html b/_includes/javascript.html index fcc74e6e..77080ae5 100644 --- a/_includes/javascript.html +++ b/_includes/javascript.html @@ -12,3 +12,19 @@ ga('create', 'UA-37305346-2', 'auto'); ga('send', 'pageview'); +{% if page.math %} + + + +{% endif %} + diff --git a/_layouts/base.html b/_layouts/base.html index cc4132d6..27b116eb 100644 --- a/_layouts/base.html +++ b/_layouts/base.html @@ -16,6 +16,9 @@ + {% if page.math %} + + {% endif %} {% include favicons.html %} diff --git a/assets/css/katex.min.css b/assets/css/katex.min.css new file mode 100644 index 00000000..e1dfc046 --- /dev/null +++ b/assets/css/katex.min.css @@ -0,0 +1 @@ +@font-face{font-family:KaTeX_AMS;font-style:normal;font-weight:400;src:url(fonts/KaTeX_AMS-Regular.woff2) format("woff2"),url(fonts/KaTeX_AMS-Regular.woff) format("woff"),url(fonts/KaTeX_AMS-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Caligraphic;font-style:normal;font-weight:700;src:url(fonts/KaTeX_Caligraphic-Bold.woff2) format("woff2"),url(fonts/KaTeX_Caligraphic-Bold.woff) format("woff"),url(fonts/KaTeX_Caligraphic-Bold.ttf) format("truetype")}@font-face{font-family:KaTeX_Caligraphic;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Caligraphic-Regular.woff2) format("woff2"),url(fonts/KaTeX_Caligraphic-Regular.woff) format("woff"),url(fonts/KaTeX_Caligraphic-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Fraktur;font-style:normal;font-weight:700;src:url(fonts/KaTeX_Fraktur-Bold.woff2) format("woff2"),url(fonts/KaTeX_Fraktur-Bold.woff) format("woff"),url(fonts/KaTeX_Fraktur-Bold.ttf) format("truetype")}@font-face{font-family:KaTeX_Fraktur;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Fraktur-Regular.woff2) format("woff2"),url(fonts/KaTeX_Fraktur-Regular.woff) format("woff"),url(fonts/KaTeX_Fraktur-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Main;font-style:normal;font-weight:700;src:url(fonts/KaTeX_Main-Bold.woff2) format("woff2"),url(fonts/KaTeX_Main-Bold.woff) format("woff"),url(fonts/KaTeX_Main-Bold.ttf) format("truetype")}@font-face{font-family:KaTeX_Main;font-style:italic;font-weight:700;src:url(fonts/KaTeX_Main-BoldItalic.woff2) format("woff2"),url(fonts/KaTeX_Main-BoldItalic.woff) format("woff"),url(fonts/KaTeX_Main-BoldItalic.ttf) format("truetype")}@font-face{font-family:KaTeX_Main;font-style:italic;font-weight:400;src:url(fonts/KaTeX_Main-Italic.woff2) format("woff2"),url(fonts/KaTeX_Main-Italic.woff) format("woff"),url(fonts/KaTeX_Main-Italic.ttf) format("truetype")}@font-face{font-family:KaTeX_Main;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Main-Regular.woff2) format("woff2"),url(fonts/KaTeX_Main-Regular.woff) format("woff"),url(fonts/KaTeX_Main-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Math;font-style:italic;font-weight:700;src:url(fonts/KaTeX_Math-BoldItalic.woff2) format("woff2"),url(fonts/KaTeX_Math-BoldItalic.woff) format("woff"),url(fonts/KaTeX_Math-BoldItalic.ttf) format("truetype")}@font-face{font-family:KaTeX_Math;font-style:italic;font-weight:400;src:url(fonts/KaTeX_Math-Italic.woff2) format("woff2"),url(fonts/KaTeX_Math-Italic.woff) format("woff"),url(fonts/KaTeX_Math-Italic.ttf) format("truetype")}@font-face{font-family:"KaTeX_SansSerif";font-style:normal;font-weight:700;src:url(fonts/KaTeX_SansSerif-Bold.woff2) format("woff2"),url(fonts/KaTeX_SansSerif-Bold.woff) format("woff"),url(fonts/KaTeX_SansSerif-Bold.ttf) format("truetype")}@font-face{font-family:"KaTeX_SansSerif";font-style:italic;font-weight:400;src:url(fonts/KaTeX_SansSerif-Italic.woff2) format("woff2"),url(fonts/KaTeX_SansSerif-Italic.woff) format("woff"),url(fonts/KaTeX_SansSerif-Italic.ttf) format("truetype")}@font-face{font-family:"KaTeX_SansSerif";font-style:normal;font-weight:400;src:url(fonts/KaTeX_SansSerif-Regular.woff2) format("woff2"),url(fonts/KaTeX_SansSerif-Regular.woff) format("woff"),url(fonts/KaTeX_SansSerif-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Script;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Script-Regular.woff2) format("woff2"),url(fonts/KaTeX_Script-Regular.woff) format("woff"),url(fonts/KaTeX_Script-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Size1;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Size1-Regular.woff2) format("woff2"),url(fonts/KaTeX_Size1-Regular.woff) format("woff"),url(fonts/KaTeX_Size1-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Size2;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Size2-Regular.woff2) format("woff2"),url(fonts/KaTeX_Size2-Regular.woff) format("woff"),url(fonts/KaTeX_Size2-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Size3;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Size3-Regular.woff2) format("woff2"),url(fonts/KaTeX_Size3-Regular.woff) format("woff"),url(fonts/KaTeX_Size3-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Size4;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Size4-Regular.woff2) format("woff2"),url(fonts/KaTeX_Size4-Regular.woff) format("woff"),url(fonts/KaTeX_Size4-Regular.ttf) format("truetype")}@font-face{font-family:KaTeX_Typewriter;font-style:normal;font-weight:400;src:url(fonts/KaTeX_Typewriter-Regular.woff2) format("woff2"),url(fonts/KaTeX_Typewriter-Regular.woff) format("woff"),url(fonts/KaTeX_Typewriter-Regular.ttf) format("truetype")}.katex{font:normal 1.21em KaTeX_Main,Times New Roman,serif;line-height:1.2;text-indent:0;text-rendering:auto}.katex *{-ms-high-contrast-adjust:none!important;border-color:currentColor}.katex .katex-version:after{content:"0.13.2"}.katex .katex-mathml{clip:rect(1px,1px,1px,1px);border:0;height:1px;overflow:hidden;padding:0;position:absolute;width:1px}.katex .katex-html>.newline{display:block}.katex .base{position:relative;white-space:nowrap;width:-webkit-min-content;width:-moz-min-content;width:min-content}.katex .base,.katex .strut{display:inline-block}.katex .textbf{font-weight:700}.katex .textit{font-style:italic}.katex .textrm{font-family:KaTeX_Main}.katex .textsf{font-family:KaTeX_SansSerif}.katex .texttt{font-family:KaTeX_Typewriter}.katex .mathnormal{font-family:KaTeX_Math;font-style:italic}.katex .mathit{font-family:KaTeX_Main;font-style:italic}.katex .mathrm{font-style:normal}.katex .mathbf{font-family:KaTeX_Main;font-weight:700}.katex .boldsymbol{font-family:KaTeX_Math;font-style:italic;font-weight:700}.katex .amsrm,.katex .mathbb,.katex .textbb{font-family:KaTeX_AMS}.katex .mathcal{font-family:KaTeX_Caligraphic}.katex .mathfrak,.katex .textfrak{font-family:KaTeX_Fraktur}.katex .mathtt{font-family:KaTeX_Typewriter}.katex .mathscr,.katex .textscr{font-family:KaTeX_Script}.katex .mathsf,.katex .textsf{font-family:KaTeX_SansSerif}.katex .mathboldsf,.katex .textboldsf{font-family:KaTeX_SansSerif;font-weight:700}.katex .mathitsf,.katex .textitsf{font-family:KaTeX_SansSerif;font-style:italic}.katex .mainrm{font-family:KaTeX_Main;font-style:normal}.katex .vlist-t{border-collapse:collapse;display:inline-table;table-layout:fixed}.katex .vlist-r{display:table-row}.katex .vlist{display:table-cell;position:relative;vertical-align:bottom}.katex .vlist>span{display:block;height:0;position:relative}.katex .vlist>span>span{display:inline-block}.katex .vlist>span>.pstrut{overflow:hidden;width:0}.katex .vlist-t2{margin-right:-2px}.katex .vlist-s{display:table-cell;font-size:1px;min-width:2px;vertical-align:bottom;width:2px}.katex .vbox{-webkit-box-orient:vertical;-webkit-box-direction:normal;-webkit-box-align:baseline;align-items:baseline;display:-webkit-inline-box;display:inline-flex;flex-direction:column}.katex .hbox{width:100%}.katex .hbox,.katex .thinbox{-webkit-box-orient:horizontal;-webkit-box-direction:normal;display:-webkit-inline-box;display:inline-flex;flex-direction:row}.katex .thinbox{max-width:0;width:0}.katex .msupsub{text-align:left}.katex .mfrac>span>span{text-align:center}.katex .mfrac .frac-line{border-bottom-style:solid;display:inline-block;width:100%}.katex .hdashline,.katex .hline,.katex .mfrac .frac-line,.katex .overline .overline-line,.katex .rule,.katex .underline .underline-line{min-height:1px}.katex .mspace{display:inline-block}.katex .clap,.katex .llap,.katex .rlap{position:relative;width:0}.katex .clap>.inner,.katex .llap>.inner,.katex .rlap>.inner{position:absolute}.katex .clap>.fix,.katex .llap>.fix,.katex .rlap>.fix{display:inline-block}.katex .llap>.inner{right:0}.katex .clap>.inner,.katex .rlap>.inner{left:0}.katex .clap>.inner>span{margin-left:-50%;margin-right:50%}.katex .rule{border:0 solid;display:inline-block;position:relative}.katex .hline,.katex .overline .overline-line,.katex .underline .underline-line{border-bottom-style:solid;display:inline-block;width:100%}.katex .hdashline{border-bottom-style:dashed;display:inline-block;width:100%}.katex .sqrt>.root{margin-left:.27777778em;margin-right:-.55555556em}.katex .fontsize-ensurer.reset-size1.size1,.katex .sizing.reset-size1.size1{font-size:1em}.katex .fontsize-ensurer.reset-size1.size2,.katex .sizing.reset-size1.size2{font-size:1.2em}.katex .fontsize-ensurer.reset-size1.size3,.katex .sizing.reset-size1.size3{font-size:1.4em}.katex .fontsize-ensurer.reset-size1.size4,.katex .sizing.reset-size1.size4{font-size:1.6em}.katex .fontsize-ensurer.reset-size1.size5,.katex .sizing.reset-size1.size5{font-size:1.8em}.katex .fontsize-ensurer.reset-size1.size6,.katex .sizing.reset-size1.size6{font-size:2em}.katex .fontsize-ensurer.reset-size1.size7,.katex .sizing.reset-size1.size7{font-size:2.4em}.katex .fontsize-ensurer.reset-size1.size8,.katex .sizing.reset-size1.size8{font-size:2.88em}.katex .fontsize-ensurer.reset-size1.size9,.katex .sizing.reset-size1.size9{font-size:3.456em}.katex .fontsize-ensurer.reset-size1.size10,.katex .sizing.reset-size1.size10{font-size:4.148em}.katex .fontsize-ensurer.reset-size1.size11,.katex .sizing.reset-size1.size11{font-size:4.976em}.katex .fontsize-ensurer.reset-size2.size1,.katex .sizing.reset-size2.size1{font-size:.83333333em}.katex .fontsize-ensurer.reset-size2.size2,.katex .sizing.reset-size2.size2{font-size:1em}.katex .fontsize-ensurer.reset-size2.size3,.katex .sizing.reset-size2.size3{font-size:1.16666667em}.katex .fontsize-ensurer.reset-size2.size4,.katex .sizing.reset-size2.size4{font-size:1.33333333em}.katex .fontsize-ensurer.reset-size2.size5,.katex .sizing.reset-size2.size5{font-size:1.5em}.katex .fontsize-ensurer.reset-size2.size6,.katex .sizing.reset-size2.size6{font-size:1.66666667em}.katex .fontsize-ensurer.reset-size2.size7,.katex .sizing.reset-size2.size7{font-size:2em}.katex .fontsize-ensurer.reset-size2.size8,.katex .sizing.reset-size2.size8{font-size:2.4em}.katex .fontsize-ensurer.reset-size2.size9,.katex .sizing.reset-size2.size9{font-size:2.88em}.katex .fontsize-ensurer.reset-size2.size10,.katex .sizing.reset-size2.size10{font-size:3.45666667em}.katex .fontsize-ensurer.reset-size2.size11,.katex .sizing.reset-size2.size11{font-size:4.14666667em}.katex .fontsize-ensurer.reset-size3.size1,.katex .sizing.reset-size3.size1{font-size:.71428571em}.katex .fontsize-ensurer.reset-size3.size2,.katex .sizing.reset-size3.size2{font-size:.85714286em}.katex .fontsize-ensurer.reset-size3.size3,.katex .sizing.reset-size3.size3{font-size:1em}.katex .fontsize-ensurer.reset-size3.size4,.katex .sizing.reset-size3.size4{font-size:1.14285714em}.katex .fontsize-ensurer.reset-size3.size5,.katex .sizing.reset-size3.size5{font-size:1.28571429em}.katex .fontsize-ensurer.reset-size3.size6,.katex .sizing.reset-size3.size6{font-size:1.42857143em}.katex .fontsize-ensurer.reset-size3.size7,.katex .sizing.reset-size3.size7{font-size:1.71428571em}.katex .fontsize-ensurer.reset-size3.size8,.katex .sizing.reset-size3.size8{font-size:2.05714286em}.katex .fontsize-ensurer.reset-size3.size9,.katex .sizing.reset-size3.size9{font-size:2.46857143em}.katex .fontsize-ensurer.reset-size3.size10,.katex .sizing.reset-size3.size10{font-size:2.96285714em}.katex .fontsize-ensurer.reset-size3.size11,.katex .sizing.reset-size3.size11{font-size:3.55428571em}.katex .fontsize-ensurer.reset-size4.size1,.katex .sizing.reset-size4.size1{font-size:.625em}.katex .fontsize-ensurer.reset-size4.size2,.katex .sizing.reset-size4.size2{font-size:.75em}.katex .fontsize-ensurer.reset-size4.size3,.katex .sizing.reset-size4.size3{font-size:.875em}.katex .fontsize-ensurer.reset-size4.size4,.katex .sizing.reset-size4.size4{font-size:1em}.katex .fontsize-ensurer.reset-size4.size5,.katex .sizing.reset-size4.size5{font-size:1.125em}.katex .fontsize-ensurer.reset-size4.size6,.katex .sizing.reset-size4.size6{font-size:1.25em}.katex .fontsize-ensurer.reset-size4.size7,.katex .sizing.reset-size4.size7{font-size:1.5em}.katex .fontsize-ensurer.reset-size4.size8,.katex .sizing.reset-size4.size8{font-size:1.8em}.katex .fontsize-ensurer.reset-size4.size9,.katex .sizing.reset-size4.size9{font-size:2.16em}.katex .fontsize-ensurer.reset-size4.size10,.katex .sizing.reset-size4.size10{font-size:2.5925em}.katex .fontsize-ensurer.reset-size4.size11,.katex .sizing.reset-size4.size11{font-size:3.11em}.katex .fontsize-ensurer.reset-size5.size1,.katex .sizing.reset-size5.size1{font-size:.55555556em}.katex .fontsize-ensurer.reset-size5.size2,.katex .sizing.reset-size5.size2{font-size:.66666667em}.katex .fontsize-ensurer.reset-size5.size3,.katex .sizing.reset-size5.size3{font-size:.77777778em}.katex .fontsize-ensurer.reset-size5.size4,.katex .sizing.reset-size5.size4{font-size:.88888889em}.katex .fontsize-ensurer.reset-size5.size5,.katex .sizing.reset-size5.size5{font-size:1em}.katex .fontsize-ensurer.reset-size5.size6,.katex .sizing.reset-size5.size6{font-size:1.11111111em}.katex .fontsize-ensurer.reset-size5.size7,.katex .sizing.reset-size5.size7{font-size:1.33333333em}.katex .fontsize-ensurer.reset-size5.size8,.katex .sizing.reset-size5.size8{font-size:1.6em}.katex .fontsize-ensurer.reset-size5.size9,.katex .sizing.reset-size5.size9{font-size:1.92em}.katex .fontsize-ensurer.reset-size5.size10,.katex .sizing.reset-size5.size10{font-size:2.30444444em}.katex .fontsize-ensurer.reset-size5.size11,.katex .sizing.reset-size5.size11{font-size:2.76444444em}.katex .fontsize-ensurer.reset-size6.size1,.katex .sizing.reset-size6.size1{font-size:.5em}.katex .fontsize-ensurer.reset-size6.size2,.katex .sizing.reset-size6.size2{font-size:.6em}.katex .fontsize-ensurer.reset-size6.size3,.katex .sizing.reset-size6.size3{font-size:.7em}.katex .fontsize-ensurer.reset-size6.size4,.katex .sizing.reset-size6.size4{font-size:.8em}.katex .fontsize-ensurer.reset-size6.size5,.katex .sizing.reset-size6.size5{font-size:.9em}.katex .fontsize-ensurer.reset-size6.size6,.katex .sizing.reset-size6.size6{font-size:1em}.katex .fontsize-ensurer.reset-size6.size7,.katex .sizing.reset-size6.size7{font-size:1.2em}.katex .fontsize-ensurer.reset-size6.size8,.katex .sizing.reset-size6.size8{font-size:1.44em}.katex .fontsize-ensurer.reset-size6.size9,.katex .sizing.reset-size6.size9{font-size:1.728em}.katex .fontsize-ensurer.reset-size6.size10,.katex .sizing.reset-size6.size10{font-size:2.074em}.katex .fontsize-ensurer.reset-size6.size11,.katex .sizing.reset-size6.size11{font-size:2.488em}.katex .fontsize-ensurer.reset-size7.size1,.katex .sizing.reset-size7.size1{font-size:.41666667em}.katex .fontsize-ensurer.reset-size7.size2,.katex .sizing.reset-size7.size2{font-size:.5em}.katex .fontsize-ensurer.reset-size7.size3,.katex .sizing.reset-size7.size3{font-size:.58333333em}.katex .fontsize-ensurer.reset-size7.size4,.katex .sizing.reset-size7.size4{font-size:.66666667em}.katex .fontsize-ensurer.reset-size7.size5,.katex .sizing.reset-size7.size5{font-size:.75em}.katex .fontsize-ensurer.reset-size7.size6,.katex .sizing.reset-size7.size6{font-size:.83333333em}.katex .fontsize-ensurer.reset-size7.size7,.katex .sizing.reset-size7.size7{font-size:1em}.katex .fontsize-ensurer.reset-size7.size8,.katex .sizing.reset-size7.size8{font-size:1.2em}.katex .fontsize-ensurer.reset-size7.size9,.katex .sizing.reset-size7.size9{font-size:1.44em}.katex .fontsize-ensurer.reset-size7.size10,.katex .sizing.reset-size7.size10{font-size:1.72833333em}.katex .fontsize-ensurer.reset-size7.size11,.katex .sizing.reset-size7.size11{font-size:2.07333333em}.katex .fontsize-ensurer.reset-size8.size1,.katex .sizing.reset-size8.size1{font-size:.34722222em}.katex .fontsize-ensurer.reset-size8.size2,.katex .sizing.reset-size8.size2{font-size:.41666667em}.katex .fontsize-ensurer.reset-size8.size3,.katex .sizing.reset-size8.size3{font-size:.48611111em}.katex .fontsize-ensurer.reset-size8.size4,.katex .sizing.reset-size8.size4{font-size:.55555556em}.katex .fontsize-ensurer.reset-size8.size5,.katex .sizing.reset-size8.size5{font-size:.625em}.katex .fontsize-ensurer.reset-size8.size6,.katex .sizing.reset-size8.size6{font-size:.69444444em}.katex .fontsize-ensurer.reset-size8.size7,.katex .sizing.reset-size8.size7{font-size:.83333333em}.katex .fontsize-ensurer.reset-size8.size8,.katex .sizing.reset-size8.size8{font-size:1em}.katex .fontsize-ensurer.reset-size8.size9,.katex .sizing.reset-size8.size9{font-size:1.2em}.katex .fontsize-ensurer.reset-size8.size10,.katex .sizing.reset-size8.size10{font-size:1.44027778em}.katex .fontsize-ensurer.reset-size8.size11,.katex .sizing.reset-size8.size11{font-size:1.72777778em}.katex .fontsize-ensurer.reset-size9.size1,.katex .sizing.reset-size9.size1{font-size:.28935185em}.katex .fontsize-ensurer.reset-size9.size2,.katex .sizing.reset-size9.size2{font-size:.34722222em}.katex .fontsize-ensurer.reset-size9.size3,.katex .sizing.reset-size9.size3{font-size:.40509259em}.katex .fontsize-ensurer.reset-size9.size4,.katex .sizing.reset-size9.size4{font-size:.46296296em}.katex .fontsize-ensurer.reset-size9.size5,.katex .sizing.reset-size9.size5{font-size:.52083333em}.katex .fontsize-ensurer.reset-size9.size6,.katex .sizing.reset-size9.size6{font-size:.5787037em}.katex .fontsize-ensurer.reset-size9.size7,.katex .sizing.reset-size9.size7{font-size:.69444444em}.katex .fontsize-ensurer.reset-size9.size8,.katex .sizing.reset-size9.size8{font-size:.83333333em}.katex .fontsize-ensurer.reset-size9.size9,.katex .sizing.reset-size9.size9{font-size:1em}.katex .fontsize-ensurer.reset-size9.size10,.katex .sizing.reset-size9.size10{font-size:1.20023148em}.katex .fontsize-ensurer.reset-size9.size11,.katex .sizing.reset-size9.size11{font-size:1.43981481em}.katex .fontsize-ensurer.reset-size10.size1,.katex .sizing.reset-size10.size1{font-size:.24108004em}.katex .fontsize-ensurer.reset-size10.size2,.katex .sizing.reset-size10.size2{font-size:.28929605em}.katex .fontsize-ensurer.reset-size10.size3,.katex .sizing.reset-size10.size3{font-size:.33751205em}.katex .fontsize-ensurer.reset-size10.size4,.katex .sizing.reset-size10.size4{font-size:.38572806em}.katex .fontsize-ensurer.reset-size10.size5,.katex .sizing.reset-size10.size5{font-size:.43394407em}.katex .fontsize-ensurer.reset-size10.size6,.katex .sizing.reset-size10.size6{font-size:.48216008em}.katex .fontsize-ensurer.reset-size10.size7,.katex .sizing.reset-size10.size7{font-size:.57859209em}.katex .fontsize-ensurer.reset-size10.size8,.katex .sizing.reset-size10.size8{font-size:.69431051em}.katex .fontsize-ensurer.reset-size10.size9,.katex .sizing.reset-size10.size9{font-size:.83317261em}.katex .fontsize-ensurer.reset-size10.size10,.katex .sizing.reset-size10.size10{font-size:1em}.katex .fontsize-ensurer.reset-size10.size11,.katex .sizing.reset-size10.size11{font-size:1.19961427em}.katex .fontsize-ensurer.reset-size11.size1,.katex .sizing.reset-size11.size1{font-size:.20096463em}.katex .fontsize-ensurer.reset-size11.size2,.katex .sizing.reset-size11.size2{font-size:.24115756em}.katex .fontsize-ensurer.reset-size11.size3,.katex .sizing.reset-size11.size3{font-size:.28135048em}.katex .fontsize-ensurer.reset-size11.size4,.katex .sizing.reset-size11.size4{font-size:.32154341em}.katex .fontsize-ensurer.reset-size11.size5,.katex .sizing.reset-size11.size5{font-size:.36173633em}.katex .fontsize-ensurer.reset-size11.size6,.katex .sizing.reset-size11.size6{font-size:.40192926em}.katex .fontsize-ensurer.reset-size11.size7,.katex .sizing.reset-size11.size7{font-size:.48231511em}.katex .fontsize-ensurer.reset-size11.size8,.katex .sizing.reset-size11.size8{font-size:.57877814em}.katex .fontsize-ensurer.reset-size11.size9,.katex .sizing.reset-size11.size9{font-size:.69453376em}.katex .fontsize-ensurer.reset-size11.size10,.katex .sizing.reset-size11.size10{font-size:.83360129em}.katex .fontsize-ensurer.reset-size11.size11,.katex .sizing.reset-size11.size11{font-size:1em}.katex .delimsizing.size1{font-family:KaTeX_Size1}.katex .delimsizing.size2{font-family:KaTeX_Size2}.katex .delimsizing.size3{font-family:KaTeX_Size3}.katex .delimsizing.size4{font-family:KaTeX_Size4}.katex .delimsizing.mult .delim-size1>span{font-family:KaTeX_Size1}.katex .delimsizing.mult .delim-size4>span{font-family:KaTeX_Size4}.katex .nulldelimiter{display:inline-block;width:.12em}.katex .delimcenter,.katex .op-symbol{position:relative}.katex .op-symbol.small-op{font-family:KaTeX_Size1}.katex .op-symbol.large-op{font-family:KaTeX_Size2}.katex .accent>.vlist-t,.katex .op-limits>.vlist-t{text-align:center}.katex .accent .accent-body{position:relative}.katex .accent .accent-body:not(.accent-full){width:0}.katex .overlay{display:block}.katex .mtable .vertical-separator{display:inline-block;min-width:1px}.katex .mtable .arraycolsep{display:inline-block}.katex .mtable .col-align-c>.vlist-t{text-align:center}.katex .mtable .col-align-l>.vlist-t{text-align:left}.katex .mtable .col-align-r>.vlist-t{text-align:right}.katex .svg-align{text-align:left}.katex svg{fill:currentColor;stroke:currentColor;fill-rule:nonzero;fill-opacity:1;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:block;height:inherit;position:absolute;width:100%}.katex svg path{stroke:none}.katex img{border-style:none;max-height:none;max-width:none;min-height:0;min-width:0}.katex .stretchy{display:block;overflow:hidden;position:relative;width:100%}.katex .stretchy:after,.katex .stretchy:before{content:""}.katex .hide-tail{overflow:hidden;position:relative;width:100%}.katex .halfarrow-left{left:0;overflow:hidden;position:absolute;width:50.2%}.katex .halfarrow-right{overflow:hidden;position:absolute;right:0;width:50.2%}.katex .brace-left{left:0;overflow:hidden;position:absolute;width:25.1%}.katex .brace-center{left:25%;overflow:hidden;position:absolute;width:50%}.katex .brace-right{overflow:hidden;position:absolute;right:0;width:25.1%}.katex .x-arrow-pad{padding:0 .5em}.katex .cd-arrow-pad{padding:0 .55556em 0 .27778em}.katex .mover,.katex .munder,.katex .x-arrow{text-align:center}.katex .boxpad{padding:0 .3em}.katex .fbox,.katex .fcolorbox{border:.04em solid;box-sizing:border-box}.katex .cancel-pad{padding:0 .2em}.katex .cancel-lap{margin-left:-.2em;margin-right:-.2em}.katex .sout{border-bottom-style:solid;border-bottom-width:.08em}.katex .angl{border-right:.049em solid;border-top:.049em solid;box-sizing:border-content;margin-right:.03889em}.katex .anglpad{padding:0 .03889em}.katex .eqn-num:before{content:"(" counter(katexEqnNo) ")";counter-increment:katexEqnNo}.katex .mml-eqn-num:before{content:"(" counter(mmlEqnNo) ")";counter-increment:mmlEqnNo}.katex .mtr-glue{width:50%}.katex .cd-vert-arrow{display:inline-block;position:relative}.katex .cd-label-left{display:inline-block;position:absolute;right:-webkit-calc(50% + .3em);right:calc(50% + .3em);text-align:left}.katex .cd-label-right{display:inline-block;left:-webkit-calc(50% + .3em);left:calc(50% + .3em);position:absolute;text-align:right}.katex-display{display:block;margin:1em 0;text-align:center}.katex-display>.katex{display:block;text-align:center;white-space:nowrap}.katex-display>.katex>.katex-html{display:block;position:relative}.katex-display>.katex>.katex-html>.tag{position:absolute;right:0}.katex-display.leqno>.katex>.katex-html>.tag{left:0;right:auto}.katex-display.fleqn>.katex{padding-left:2em;text-align:left}body{counter-reset:katexEqnNo mmlEqnNo} diff --git a/assets/js/katex-auto-render.min.js b/assets/js/katex-auto-render.min.js new file mode 100644 index 00000000..92bf352b --- /dev/null +++ b/assets/js/katex-auto-render.min.js @@ -0,0 +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;i15?"\u2026"+o.slice(n-15,n):o.slice(0,n))+l+(s+15":">","<":"<",'"':""","'":"'"},o=/[&><"']/g;var s=function e(t){return"ordgroup"===t.type||"color"===t.type?1===t.body.length?e(t.body[0]):t:"font"===t.type?e(t.body):t},l={contains:function(e,t){return-1!==e.indexOf(t)},deflt:function(e,t){return void 0===e?t:e},escape:function(e){return String(e).replace(o,(function(e){return i[e]}))},hyphenate:function(e){return e.replace(a,"-$1").toLowerCase()},getBaseElem:s,isCharacterBox:function(e){var t=s(e);return"mathord"===t.type||"textord"===t.type||"atom"===t.type},protocolFromUrl:function(e){var t=/^\s*([^\\/#]*?)(?::|�*58|�*3a)/i.exec(e);return null!=t?t[1]:"_relative"}},h=function(){function e(e){this.displayMode=void 0,this.output=void 0,this.leqno=void 0,this.fleqn=void 0,this.throwOnError=void 0,this.errorColor=void 0,this.macros=void 0,this.minRuleThickness=void 0,this.colorIsTextColor=void 0,this.strict=void 0,this.trust=void 0,this.maxSize=void 0,this.maxExpand=void 0,this.globalGroup=void 0,e=e||{},this.displayMode=l.deflt(e.displayMode,!1),this.output=l.deflt(e.output,"htmlAndMathml"),this.leqno=l.deflt(e.leqno,!1),this.fleqn=l.deflt(e.fleqn,!1),this.throwOnError=l.deflt(e.throwOnError,!0),this.errorColor=l.deflt(e.errorColor,"#cc0000"),this.macros=e.macros||{},this.minRuleThickness=Math.max(0,l.deflt(e.minRuleThickness,0)),this.colorIsTextColor=l.deflt(e.colorIsTextColor,!1),this.strict=l.deflt(e.strict,"warn"),this.trust=l.deflt(e.trust,!1),this.maxSize=Math.max(0,l.deflt(e.maxSize,1/0)),this.maxExpand=Math.max(0,l.deflt(e.maxExpand,1e3)),this.globalGroup=l.deflt(e.globalGroup,!1)}var t=e.prototype;return t.reportNonstrict=function(e,t,r){var a=this.strict;if("function"==typeof a&&(a=a(e,t,r)),a&&"ignore"!==a){if(!0===a||"error"===a)throw new n("LaTeX-incompatible input and strict mode is set to 'error': "+t+" ["+e+"]",r);"warn"===a?"undefined"!=typeof console&&console.warn("LaTeX-incompatible input and strict mode is set to 'warn': "+t+" ["+e+"]"):"undefined"!=typeof console&&console.warn("LaTeX-incompatible input and strict mode is set to unrecognized '"+a+"': "+t+" ["+e+"]")}},t.useStrictBehavior=function(e,t,r){var n=this.strict;if("function"==typeof n)try{n=n(e,t,r)}catch(e){n="error"}return!(!n||"ignore"===n)&&(!0===n||"error"===n||("warn"===n?("undefined"!=typeof console&&console.warn("LaTeX-incompatible input and strict mode is set to 'warn': "+t+" ["+e+"]"),!1):("undefined"!=typeof console&&console.warn("LaTeX-incompatible input and strict mode is set to unrecognized '"+n+"': "+t+" ["+e+"]"),!1)))},t.isTrusted=function(e){e.url&&!e.protocol&&(e.protocol=l.protocolFromUrl(e.url));var t="function"==typeof this.trust?this.trust(e):this.trust;return Boolean(t)},e}(),m=function(){function e(e,t,r){this.id=void 0,this.size=void 0,this.cramped=void 0,this.id=e,this.size=t,this.cramped=r}var t=e.prototype;return t.sup=function(){return c[u[this.id]]},t.sub=function(){return c[p[this.id]]},t.fracNum=function(){return c[d[this.id]]},t.fracDen=function(){return c[f[this.id]]},t.cramp=function(){return c[g[this.id]]},t.text=function(){return c[v[this.id]]},t.isTight=function(){return this.size>=2},e}(),c=[new m(0,0,!1),new m(1,0,!0),new m(2,1,!1),new m(3,1,!0),new m(4,2,!1),new m(5,2,!0),new m(6,3,!1),new m(7,3,!0)],u=[4,5,4,5,6,7,6,7],p=[5,5,5,5,7,7,7,7],d=[2,3,4,5,6,7,6,7],f=[3,3,5,5,7,7,7,7],g=[1,1,3,3,5,5,7,7],v=[0,1,2,3,2,3,2,3],b={DISPLAY:c[0],TEXT:c[2],SCRIPT:c[4],SCRIPTSCRIPT:c[6]},y=[{name:"latin",blocks:[[256,591],[768,879]]},{name:"cyrillic",blocks:[[1024,1279]]},{name:"armenian",blocks:[[1328,1423]]},{name:"brahmic",blocks:[[2304,4255]]},{name:"georgian",blocks:[[4256,4351]]},{name:"cjk",blocks:[[12288,12543],[19968,40879],[65280,65376]]},{name:"hangul",blocks:[[44032,55215]]}];var x=[];function w(e){for(var t=0;t=x[t]&&e<=x[t+1])return!0;return!1}y.forEach((function(e){return e.blocks.forEach((function(e){return x.push.apply(x,e)}))}));var k=80,S={doubleleftarrow:"M262 157\nl10-10c34-36 62.7-77 86-123 3.3-8 5-13.3 5-16 0-5.3-6.7-8-20-8-7.3\n 0-12.2.5-14.5 1.5-2.3 1-4.8 4.5-7.5 10.5-49.3 97.3-121.7 169.3-217 216-28\n 14-57.3 25-88 33-6.7 2-11 3.8-13 5.5-2 1.7-3 4.2-3 7.5s1 5.8 3 7.5\nc2 1.7 6.3 3.5 13 5.5 68 17.3 128.2 47.8 180.5 91.5 52.3 43.7 93.8 96.2 124.5\n 157.5 9.3 8 15.3 12.3 18 13h6c12-.7 18-4 18-10 0-2-1.7-7-5-15-23.3-46-52-87\n-86-123l-10-10h399738v-40H218c328 0 0 0 0 0l-10-8c-26.7-20-65.7-43-117-69 2.7\n-2 6-3.7 10-5 36.7-16 72.3-37.3 107-64l10-8h399782v-40z\nm8 0v40h399730v-40zm0 194v40h399730v-40z",doublerightarrow:"M399738 392l\n-10 10c-34 36-62.7 77-86 123-3.3 8-5 13.3-5 16 0 5.3 6.7 8 20 8 7.3 0 12.2-.5\n 14.5-1.5 2.3-1 4.8-4.5 7.5-10.5 49.3-97.3 121.7-169.3 217-216 28-14 57.3-25 88\n-33 6.7-2 11-3.8 13-5.5 2-1.7 3-4.2 3-7.5s-1-5.8-3-7.5c-2-1.7-6.3-3.5-13-5.5-68\n-17.3-128.2-47.8-180.5-91.5-52.3-43.7-93.8-96.2-124.5-157.5-9.3-8-15.3-12.3-18\n-13h-6c-12 .7-18 4-18 10 0 2 1.7 7 5 15 23.3 46 52 87 86 123l10 10H0v40h399782\nc-328 0 0 0 0 0l10 8c26.7 20 65.7 43 117 69-2.7 2-6 3.7-10 5-36.7 16-72.3 37.3\n-107 64l-10 8H0v40zM0 157v40h399730v-40zm0 194v40h399730v-40z",leftarrow:"M400000 241H110l3-3c68.7-52.7 113.7-120\n 135-202 4-14.7 6-23 6-25 0-7.3-7-11-21-11-8 0-13.2.8-15.5 2.5-2.3 1.7-4.2 5.8\n-5.5 12.5-1.3 4.7-2.7 10.3-4 17-12 48.7-34.8 92-68.5 130S65.3 228.3 18 247\nc-10 4-16 7.7-18 11 0 8.7 6 14.3 18 17 47.3 18.7 87.8 47 121.5 85S196 441.3 208\n 490c.7 2 1.3 5 2 9s1.2 6.7 1.5 8c.3 1.3 1 3.3 2 6s2.2 4.5 3.5 5.5c1.3 1 3.3\n 1.8 6 2.5s6 1 10 1c14 0 21-3.7 21-11 0-2-2-10.3-6-25-20-79.3-65-146.7-135-202\n l-3-3h399890zM100 241v40h399900v-40z",leftbrace:"M6 548l-6-6v-35l6-11c56-104 135.3-181.3 238-232 57.3-28.7 117\n-45 179-50h399577v120H403c-43.3 7-81 15-113 26-100.7 33-179.7 91-237 174-2.7\n 5-6 9-10 13-.7 1-7.3 1-20 1H6z",leftbraceunder:"M0 6l6-6h17c12.688 0 19.313.3 20 1 4 4 7.313 8.3 10 13\n 35.313 51.3 80.813 93.8 136.5 127.5 55.688 33.7 117.188 55.8 184.5 66.5.688\n 0 2 .3 4 1 18.688 2.7 76 4.3 172 5h399450v120H429l-6-1c-124.688-8-235-61.7\n-331-161C60.687 138.7 32.312 99.3 7 54L0 41V6z",leftgroup:"M400000 80\nH435C64 80 168.3 229.4 21 260c-5.9 1.2-18 0-18 0-2 0-3-1-3-3v-38C76 61 257 0\n 435 0h399565z",leftgroupunder:"M400000 262\nH435C64 262 168.3 112.6 21 82c-5.9-1.2-18 0-18 0-2 0-3 1-3 3v38c76 158 257 219\n 435 219h399565z",leftharpoon:"M0 267c.7 5.3 3 10 7 14h399993v-40H93c3.3\n-3.3 10.2-9.5 20.5-18.5s17.8-15.8 22.5-20.5c50.7-52 88-110.3 112-175 4-11.3 5\n-18.3 3-21-1.3-4-7.3-6-18-6-8 0-13 .7-15 2s-4.7 6.7-8 16c-42 98.7-107.3 174.7\n-196 228-6.7 4.7-10.7 8-12 10-1.3 2-2 5.7-2 11zm100-26v40h399900v-40z",leftharpoonplus:"M0 267c.7 5.3 3 10 7 14h399993v-40H93c3.3-3.3 10.2-9.5\n 20.5-18.5s17.8-15.8 22.5-20.5c50.7-52 88-110.3 112-175 4-11.3 5-18.3 3-21-1.3\n-4-7.3-6-18-6-8 0-13 .7-15 2s-4.7 6.7-8 16c-42 98.7-107.3 174.7-196 228-6.7 4.7\n-10.7 8-12 10-1.3 2-2 5.7-2 11zm100-26v40h399900v-40zM0 435v40h400000v-40z\nm0 0v40h400000v-40z",leftharpoondown:"M7 241c-4 4-6.333 8.667-7 14 0 5.333.667 9 2 11s5.333\n 5.333 12 10c90.667 54 156 130 196 228 3.333 10.667 6.333 16.333 9 17 2 .667 5\n 1 9 1h5c10.667 0 16.667-2 18-6 2-2.667 1-9.667-3-21-32-87.333-82.667-157.667\n-152-211l-3-3h399907v-40zM93 281 H400000 v-40L7 241z",leftharpoondownplus:"M7 435c-4 4-6.3 8.7-7 14 0 5.3.7 9 2 11s5.3 5.3 12\n 10c90.7 54 156 130 196 228 3.3 10.7 6.3 16.3 9 17 2 .7 5 1 9 1h5c10.7 0 16.7\n-2 18-6 2-2.7 1-9.7-3-21-32-87.3-82.7-157.7-152-211l-3-3h399907v-40H7zm93 0\nv40h399900v-40zM0 241v40h399900v-40zm0 0v40h399900v-40z",lefthook:"M400000 281 H103s-33-11.2-61-33.5S0 197.3 0 164s14.2-61.2 42.5\n-83.5C70.8 58.2 104 47 142 47 c16.7 0 25 6.7 25 20 0 12-8.7 18.7-26 20-40 3.3\n-68.7 15.7-86 37-10 12-15 25.3-15 40 0 22.7 9.8 40.7 29.5 54 19.7 13.3 43.5 21\n 71.5 23h399859zM103 281v-40h399897v40z",leftlinesegment:"M40 281 V428 H0 V94 H40 V241 H400000 v40z\nM40 281 V428 H0 V94 H40 V241 H400000 v40z",leftmapsto:"M40 281 V448H0V74H40V241H400000v40z\nM40 281 V448H0V74H40V241H400000v40z",leftToFrom:"M0 147h400000v40H0zm0 214c68 40 115.7 95.7 143 167h22c15.3 0 23\n-.3 23-1 0-1.3-5.3-13.7-16-37-18-35.3-41.3-69-70-101l-7-8h399905v-40H95l7-8\nc28.7-32 52-65.7 70-101 10.7-23.3 16-35.7 16-37 0-.7-7.7-1-23-1h-22C115.7 265.3\n 68 321 0 361zm0-174v-40h399900v40zm100 154v40h399900v-40z",longequal:"M0 50 h400000 v40H0z m0 194h40000v40H0z\nM0 50 h400000 v40H0z m0 194h40000v40H0z",midbrace:"M200428 334\nc-100.7-8.3-195.3-44-280-108-55.3-42-101.7-93-139-153l-9-14c-2.7 4-5.7 8.7-9 14\n-53.3 86.7-123.7 153-211 199-66.7 36-137.3 56.3-212 62H0V214h199568c178.3-11.7\n 311.7-78.3 403-201 6-8 9.7-12 11-12 .7-.7 6.7-1 18-1s17.3.3 18 1c1.3 0 5 4 11\n 12 44.7 59.3 101.3 106.3 170 141s145.3 54.3 229 60h199572v120z",midbraceunder:"M199572 214\nc100.7 8.3 195.3 44 280 108 55.3 42 101.7 93 139 153l9 14c2.7-4 5.7-8.7 9-14\n 53.3-86.7 123.7-153 211-199 66.7-36 137.3-56.3 212-62h199568v120H200432c-178.3\n 11.7-311.7 78.3-403 201-6 8-9.7 12-11 12-.7.7-6.7 1-18 1s-17.3-.3-18-1c-1.3 0\n-5-4-11-12-44.7-59.3-101.3-106.3-170-141s-145.3-54.3-229-60H0V214z",oiintSize1:"M512.6 71.6c272.6 0 320.3 106.8 320.3 178.2 0 70.8-47.7 177.6\n-320.3 177.6S193.1 320.6 193.1 249.8c0-71.4 46.9-178.2 319.5-178.2z\nm368.1 178.2c0-86.4-60.9-215.4-368.1-215.4-306.4 0-367.3 129-367.3 215.4 0 85.8\n60.9 214.8 367.3 214.8 307.2 0 368.1-129 368.1-214.8z",oiintSize2:"M757.8 100.1c384.7 0 451.1 137.6 451.1 230 0 91.3-66.4 228.8\n-451.1 228.8-386.3 0-452.7-137.5-452.7-228.8 0-92.4 66.4-230 452.7-230z\nm502.4 230c0-111.2-82.4-277.2-502.4-277.2s-504 166-504 277.2\nc0 110 84 276 504 276s502.4-166 502.4-276z",oiiintSize1:"M681.4 71.6c408.9 0 480.5 106.8 480.5 178.2 0 70.8-71.6 177.6\n-480.5 177.6S202.1 320.6 202.1 249.8c0-71.4 70.5-178.2 479.3-178.2z\nm525.8 178.2c0-86.4-86.8-215.4-525.7-215.4-437.9 0-524.7 129-524.7 215.4 0\n85.8 86.8 214.8 524.7 214.8 438.9 0 525.7-129 525.7-214.8z",oiiintSize2:"M1021.2 53c603.6 0 707.8 165.8 707.8 277.2 0 110-104.2 275.8\n-707.8 275.8-606 0-710.2-165.8-710.2-275.8C311 218.8 415.2 53 1021.2 53z\nm770.4 277.1c0-131.2-126.4-327.6-770.5-327.6S248.4 198.9 248.4 330.1\nc0 130 128.8 326.4 772.7 326.4s770.5-196.4 770.5-326.4z",rightarrow:"M0 241v40h399891c-47.3 35.3-84 78-110 128\n-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20\n 11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7\n 39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85\n-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5\n-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67\n 151.7 139 205zm0 0v40h399900v-40z",rightbrace:"M400000 542l\n-6 6h-17c-12.7 0-19.3-.3-20-1-4-4-7.3-8.3-10-13-35.3-51.3-80.8-93.8-136.5-127.5\ns-117.2-55.8-184.5-66.5c-.7 0-2-.3-4-1-18.7-2.7-76-4.3-172-5H0V214h399571l6 1\nc124.7 8 235 61.7 331 161 31.3 33.3 59.7 72.7 85 118l7 13v35z",rightbraceunder:"M399994 0l6 6v35l-6 11c-56 104-135.3 181.3-238 232-57.3\n 28.7-117 45-179 50H-300V214h399897c43.3-7 81-15 113-26 100.7-33 179.7-91 237\n-174 2.7-5 6-9 10-13 .7-1 7.3-1 20-1h17z",rightgroup:"M0 80h399565c371 0 266.7 149.4 414 180 5.9 1.2 18 0 18 0 2 0\n 3-1 3-3v-38c-76-158-257-219-435-219H0z",rightgroupunder:"M0 262h399565c371 0 266.7-149.4 414-180 5.9-1.2 18 0 18\n 0 2 0 3 1 3 3v38c-76 158-257 219-435 219H0z",rightharpoon:"M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3\n-3.7-15.3-11-18-92.7-56.7-159-133.7-199-231-3.3-9.3-6-14.7-8-16-2-1.3-7-2-15-2\n-10.7 0-16.7 2-18 6-2 2.7-1 9.7 3 21 15.3 42 36.7 81.8 64 119.5 27.3 37.7 58\n 69.2 92 94.5zm0 0v40h399900v-40z",rightharpoonplus:"M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3-3.7-15.3-11\n-18-92.7-56.7-159-133.7-199-231-3.3-9.3-6-14.7-8-16-2-1.3-7-2-15-2-10.7 0-16.7\n 2-18 6-2 2.7-1 9.7 3 21 15.3 42 36.7 81.8 64 119.5 27.3 37.7 58 69.2 92 94.5z\nm0 0v40h399900v-40z m100 194v40h399900v-40zm0 0v40h399900v-40z",rightharpoondown:"M399747 511c0 7.3 6.7 11 20 11 8 0 13-.8 15-2.5s4.7-6.8\n 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3 8.5-5.8 9.5\n-7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3-64.7 57-92 95\n-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 241v40h399900v-40z",rightharpoondownplus:"M399747 705c0 7.3 6.7 11 20 11 8 0 13-.8\n 15-2.5s4.7-6.8 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3\n 8.5-5.8 9.5-7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3\n-64.7 57-92 95-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 435v40h399900v-40z\nm0-194v40h400000v-40zm0 0v40h400000v-40z",righthook:"M399859 241c-764 0 0 0 0 0 40-3.3 68.7-15.7 86-37 10-12 15-25.3\n 15-40 0-22.7-9.8-40.7-29.5-54-19.7-13.3-43.5-21-71.5-23-17.3-1.3-26-8-26-20 0\n-13.3 8.7-20 26-20 38 0 71 11.2 99 33.5 0 0 7 5.6 21 16.7 14 11.2 21 33.5 21\n 66.8s-14 61.2-42 83.5c-28 22.3-61 33.5-99 33.5L0 241z M0 281v-40h399859v40z",rightlinesegment:"M399960 241 V94 h40 V428 h-40 V281 H0 v-40z\nM399960 241 V94 h40 V428 h-40 V281 H0 v-40z",rightToFrom:"M400000 167c-70.7-42-118-97.7-142-167h-23c-15.3 0-23 .3-23\n 1 0 1.3 5.3 13.7 16 37 18 35.3 41.3 69 70 101l7 8H0v40h399905l-7 8c-28.7 32\n-52 65.7-70 101-10.7 23.3-16 35.7-16 37 0 .7 7.7 1 23 1h23c24-69.3 71.3-125 142\n-167z M100 147v40h399900v-40zM0 341v40h399900v-40z",twoheadleftarrow:"M0 167c68 40\n 115.7 95.7 143 167h22c15.3 0 23-.3 23-1 0-1.3-5.3-13.7-16-37-18-35.3-41.3-69\n-70-101l-7-8h125l9 7c50.7 39.3 85 86 103 140h46c0-4.7-6.3-18.7-19-42-18-35.3\n-40-67.3-66-96l-9-9h399716v-40H284l9-9c26-28.7 48-60.7 66-96 12.7-23.333 19\n-37.333 19-42h-46c-18 54-52.3 100.7-103 140l-9 7H95l7-8c28.7-32 52-65.7 70-101\n 10.7-23.333 16-35.7 16-37 0-.7-7.7-1-23-1h-22C115.7 71.3 68 127 0 167z",twoheadrightarrow:"M400000 167\nc-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3\n 41.3 69 70 101l7 8h-125l-9-7c-50.7-39.3-85-86-103-140h-46c0 4.7 6.3 18.7 19 42\n 18 35.3 40 67.3 66 96l9 9H0v40h399716l-9 9c-26 28.7-48 60.7-66 96-12.7 23.333\n-19 37.333-19 42h46c18-54 52.3-100.7 103-140l9-7h125l-7 8c-28.7 32-52 65.7-70\n 101-10.7 23.333-16 35.7-16 37 0 .7 7.7 1 23 1h22c27.3-71.3 75-127 143-167z",tilde1:"M200 55.538c-77 0-168 73.953-177 73.953-3 0-7\n-2.175-9-5.437L2 97c-1-2-2-4-2-6 0-4 2-7 5-9l20-12C116 12 171 0 207 0c86 0\n 114 68 191 68 78 0 168-68 177-68 4 0 7 2 9 5l12 19c1 2.175 2 4.35 2 6.525 0\n 4.35-2 7.613-5 9.788l-19 13.05c-92 63.077-116.937 75.308-183 76.128\n-68.267.847-113-73.952-191-73.952z",tilde2:"M344 55.266c-142 0-300.638 81.316-311.5 86.418\n-8.01 3.762-22.5 10.91-23.5 5.562L1 120c-1-2-1-3-1-4 0-5 3-9 8-10l18.4-9C160.9\n 31.9 283 0 358 0c148 0 188 122 331 122s314-97 326-97c4 0 8 2 10 7l7 21.114\nc1 2.14 1 3.21 1 4.28 0 5.347-3 9.626-7 10.696l-22.3 12.622C852.6 158.372 751\n 181.476 676 181.476c-149 0-189-126.21-332-126.21z",tilde3:"M786 59C457 59 32 175.242 13 175.242c-6 0-10-3.457\n-11-10.37L.15 138c-1-7 3-12 10-13l19.2-6.4C378.4 40.7 634.3 0 804.3 0c337 0\n 411.8 157 746.8 157 328 0 754-112 773-112 5 0 10 3 11 9l1 14.075c1 8.066-.697\n 16.595-6.697 17.492l-21.052 7.31c-367.9 98.146-609.15 122.696-778.15 122.696\n -338 0-409-156.573-744-156.573z",tilde4:"M786 58C457 58 32 177.487 13 177.487c-6 0-10-3.345\n-11-10.035L.15 143c-1-7 3-12 10-13l22-6.7C381.2 35 637.15 0 807.15 0c337 0 409\n 177 744 177 328 0 754-127 773-127 5 0 10 3 11 9l1 14.794c1 7.805-3 13.38-9\n 14.495l-20.7 5.574c-366.85 99.79-607.3 139.372-776.3 139.372-338 0-409\n -175.236-744-175.236z",vec:"M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 5\n3.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 11\n10.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63\n-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1\n-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59\nH213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359\nc-16-25.333-24-45-24-59z",widehat1:"M529 0h5l519 115c5 1 9 5 9 10 0 1-1 2-1 3l-4 22\nc-1 5-5 9-11 9h-2L532 67 19 159h-2c-5 0-9-4-11-9l-5-22c-1-6 2-12 8-13z",widehat2:"M1181 0h2l1171 176c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 220h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z",widehat3:"M1181 0h2l1171 236c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 280h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z",widehat4:"M1181 0h2l1171 296c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 340h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z",widecheck1:"M529,159h5l519,-115c5,-1,9,-5,9,-10c0,-1,-1,-2,-1,-3l-4,-22c-1,\n-5,-5,-9,-11,-9h-2l-512,92l-513,-92h-2c-5,0,-9,4,-11,9l-5,22c-1,6,2,12,8,13z",widecheck2:"M1181,220h2l1171,-176c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,153l-1167,-153h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z",widecheck3:"M1181,280h2l1171,-236c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,213l-1167,-213h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z",widecheck4:"M1181,340h2l1171,-296c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,273l-1167,-273h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z",baraboveleftarrow:"M400000 620h-399890l3 -3c68.7 -52.7 113.7 -120 135 -202\nc4 -14.7 6 -23 6 -25c0 -7.3 -7 -11 -21 -11c-8 0 -13.2 0.8 -15.5 2.5\nc-2.3 1.7 -4.2 5.8 -5.5 12.5c-1.3 4.7 -2.7 10.3 -4 17c-12 48.7 -34.8 92 -68.5 130\ns-74.2 66.3 -121.5 85c-10 4 -16 7.7 -18 11c0 8.7 6 14.3 18 17c47.3 18.7 87.8 47\n121.5 85s56.5 81.3 68.5 130c0.7 2 1.3 5 2 9s1.2 6.7 1.5 8c0.3 1.3 1 3.3 2 6\ns2.2 4.5 3.5 5.5c1.3 1 3.3 1.8 6 2.5s6 1 10 1c14 0 21 -3.7 21 -11\nc0 -2 -2 -10.3 -6 -25c-20 -79.3 -65 -146.7 -135 -202l-3 -3h399890z\nM100 620v40h399900v-40z M0 241v40h399900v-40zM0 241v40h399900v-40z",rightarrowabovebar:"M0 241v40h399891c-47.3 35.3-84 78-110 128-16.7 32\n-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20 11 8 0\n13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7 39\n-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85-40.5\n-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5\n-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67\n151.7 139 205zm96 379h399894v40H0zm0 0h399904v40H0z",baraboveshortleftharpoon:"M507,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11\nc1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17\nc2,0.7,5,1,9,1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21\nc-32,-87.3,-82.7,-157.7,-152,-211c0,0,-3,-3,-3,-3l399351,0l0,-40\nc-398570,0,-399437,0,-399437,0z M593 435 v40 H399500 v-40z\nM0 281 v-40 H399908 v40z M0 281 v-40 H399908 v40z",rightharpoonaboveshortbar:"M0,241 l0,40c399126,0,399993,0,399993,0\nc4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199,\n-231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6\nc-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z\nM0 241 v40 H399908 v-40z M0 475 v-40 H399500 v40z M0 475 v-40 H399500 v40z",shortbaraboveleftharpoon:"M7,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11\nc1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17c2,0.7,5,1,9,\n1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21c-32,-87.3,-82.7,-157.7,\n-152,-211c0,0,-3,-3,-3,-3l399907,0l0,-40c-399126,0,-399993,0,-399993,0z\nM93 435 v40 H400000 v-40z M500 241 v40 H400000 v-40z M500 241 v40 H400000 v-40z",shortrightharpoonabovebar:"M53,241l0,40c398570,0,399437,0,399437,0\nc4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199,\n-231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6\nc-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z\nM500 241 v40 H399408 v-40z M500 435 v40 H400000 v-40z"},M=function(){function e(e){this.children=void 0,this.classes=void 0,this.height=void 0,this.depth=void 0,this.maxFontSize=void 0,this.style=void 0,this.children=e,this.classes=[],this.height=0,this.depth=0,this.maxFontSize=0,this.style={}}var t=e.prototype;return t.hasClass=function(e){return l.contains(this.classes,e)},t.toNode=function(){for(var e=document.createDocumentFragment(),t=0;t"},q=function(){function e(e,t,r,n){this.children=void 0,this.attributes=void 0,this.classes=void 0,this.height=void 0,this.depth=void 0,this.width=void 0,this.maxFontSize=void 0,this.style=void 0,A.call(this,e,r,n),this.children=t||[]}var t=e.prototype;return t.setAttribute=function(e,t){this.attributes[e]=t},t.hasClass=function(e){return l.contains(this.classes,e)},t.toNode=function(){return T.call(this,"span")},t.toMarkup=function(){return B.call(this,"span")},e}(),N=function(){function e(e,t,r,n){this.children=void 0,this.attributes=void 0,this.classes=void 0,this.height=void 0,this.depth=void 0,this.maxFontSize=void 0,this.style=void 0,A.call(this,t,n),this.children=r||[],this.setAttribute("href",e)}var t=e.prototype;return t.setAttribute=function(e,t){this.attributes[e]=t},t.hasClass=function(e){return l.contains(this.classes,e)},t.toNode=function(){return T.call(this,"a")},t.toMarkup=function(){return B.call(this,"a")},e}(),C=function(){function e(e,t,r){this.src=void 0,this.alt=void 0,this.classes=void 0,this.height=void 0,this.depth=void 0,this.maxFontSize=void 0,this.style=void 0,this.alt=t,this.src=e,this.classes=["mord"],this.style=r}var t=e.prototype;return t.hasClass=function(e){return l.contains(this.classes,e)},t.toNode=function(){var e=document.createElement("img");for(var t in e.src=this.src,e.alt=this.alt,e.className="mord",this.style)this.style.hasOwnProperty(t)&&(e.style[t]=this.style[t]);return e},t.toMarkup=function(){var e=""+this.alt+"=a[0]&&e<=a[1])return r.name}return null}(this.text.charCodeAt(0));l&&this.classes.push(l+"_fallback"),/[\xee\xef\xed\xec]/.test(this.text)&&(this.text=I[this.text])}var t=e.prototype;return t.hasClass=function(e){return l.contains(this.classes,e)},t.toNode=function(){var e=document.createTextNode(this.text),t=null;for(var r in this.italic>0&&((t=document.createElement("span")).style.marginRight=this.italic+"em"),this.classes.length>0&&((t=t||document.createElement("span")).className=z(this.classes)),this.style)this.style.hasOwnProperty(r)&&((t=t||document.createElement("span")).style[r]=this.style[r]);return t?(t.appendChild(e),t):e},t.toMarkup=function(){var e=!1,t="0&&(r+="margin-right:"+this.italic+"em;"),this.style)this.style.hasOwnProperty(n)&&(r+=l.hyphenate(n)+":"+this.style[n]+";");r&&(e=!0,t+=' style="'+l.escape(r)+'"');var a=l.escape(this.text);return e?(t+=">",t+=a,t+=""):a},e}(),R=function(){function e(e,t){this.children=void 0,this.attributes=void 0,this.children=e||[],this.attributes=t||{}}var t=e.prototype;return t.toNode=function(){var e=document.createElementNS("http://www.w3.org/2000/svg","svg");for(var t in this.attributes)Object.prototype.hasOwnProperty.call(this.attributes,t)&&e.setAttribute(t,this.attributes[t]);for(var r=0;r":""},e}(),H=function(){function e(e){this.attributes=void 0,this.attributes=e||{}}var t=e.prototype;return t.toNode=function(){var e=document.createElementNS("http://www.w3.org/2000/svg","line");for(var t in this.attributes)Object.prototype.hasOwnProperty.call(this.attributes,t)&&e.setAttribute(t,this.attributes[t]);return e},t.toMarkup=function(){var e="","\\gt",!0),_(j,Z,oe,"\u2208","\\in",!0),_(j,Z,oe,"\ue020","\\@not"),_(j,Z,oe,"\u2282","\\subset",!0),_(j,Z,oe,"\u2283","\\supset",!0),_(j,Z,oe,"\u2286","\\subseteq",!0),_(j,Z,oe,"\u2287","\\supseteq",!0),_(j,K,oe,"\u2288","\\nsubseteq",!0),_(j,K,oe,"\u2289","\\nsupseteq",!0),_(j,Z,oe,"\u22a8","\\models"),_(j,Z,oe,"\u2190","\\leftarrow",!0),_(j,Z,oe,"\u2264","\\le"),_(j,Z,oe,"\u2264","\\leq",!0),_(j,Z,oe,"<","\\lt",!0),_(j,Z,oe,"\u2192","\\rightarrow",!0),_(j,Z,oe,"\u2192","\\to"),_(j,K,oe,"\u2271","\\ngeq",!0),_(j,K,oe,"\u2270","\\nleq",!0),_(j,Z,se,"\xa0","\\ "),_(j,Z,se,"\xa0","~"),_(j,Z,se,"\xa0","\\space"),_(j,Z,se,"\xa0","\\nobreakspace"),_($,Z,se,"\xa0","\\ "),_($,Z,se,"\xa0"," "),_($,Z,se,"\xa0","~"),_($,Z,se,"\xa0","\\space"),_($,Z,se,"\xa0","\\nobreakspace"),_(j,Z,se,null,"\\nobreak"),_(j,Z,se,null,"\\allowbreak"),_(j,Z,ie,",",","),_(j,Z,ie,";",";"),_(j,K,Q,"\u22bc","\\barwedge",!0),_(j,K,Q,"\u22bb","\\veebar",!0),_(j,Z,Q,"\u2299","\\odot",!0),_(j,Z,Q,"\u2295","\\oplus",!0),_(j,Z,Q,"\u2297","\\otimes",!0),_(j,Z,le,"\u2202","\\partial",!0),_(j,Z,Q,"\u2298","\\oslash",!0),_(j,K,Q,"\u229a","\\circledcirc",!0),_(j,K,Q,"\u22a1","\\boxdot",!0),_(j,Z,Q,"\u25b3","\\bigtriangleup"),_(j,Z,Q,"\u25bd","\\bigtriangledown"),_(j,Z,Q,"\u2020","\\dagger"),_(j,Z,Q,"\u22c4","\\diamond"),_(j,Z,Q,"\u22c6","\\star"),_(j,Z,Q,"\u25c3","\\triangleleft"),_(j,Z,Q,"\u25b9","\\triangleright"),_(j,Z,ae,"{","\\{"),_($,Z,le,"{","\\{"),_($,Z,le,"{","\\textbraceleft"),_(j,Z,ee,"}","\\}"),_($,Z,le,"}","\\}"),_($,Z,le,"}","\\textbraceright"),_(j,Z,ae,"{","\\lbrace"),_(j,Z,ee,"}","\\rbrace"),_(j,Z,ae,"[","\\lbrack",!0),_($,Z,le,"[","\\lbrack",!0),_(j,Z,ee,"]","\\rbrack",!0),_($,Z,le,"]","\\rbrack",!0),_(j,Z,ae,"(","\\lparen",!0),_(j,Z,ee,")","\\rparen",!0),_($,Z,le,"<","\\textless",!0),_($,Z,le,">","\\textgreater",!0),_(j,Z,ae,"\u230a","\\lfloor",!0),_(j,Z,ee,"\u230b","\\rfloor",!0),_(j,Z,ae,"\u2308","\\lceil",!0),_(j,Z,ee,"\u2309","\\rceil",!0),_(j,Z,le,"\\","\\backslash"),_(j,Z,le,"\u2223","|"),_(j,Z,le,"\u2223","\\vert"),_($,Z,le,"|","\\textbar",!0),_(j,Z,le,"\u2225","\\|"),_(j,Z,le,"\u2225","\\Vert"),_($,Z,le,"\u2225","\\textbardbl"),_($,Z,le,"~","\\textasciitilde"),_($,Z,le,"\\","\\textbackslash"),_($,Z,le,"^","\\textasciicircum"),_(j,Z,oe,"\u2191","\\uparrow",!0),_(j,Z,oe,"\u21d1","\\Uparrow",!0),_(j,Z,oe,"\u2193","\\downarrow",!0),_(j,Z,oe,"\u21d3","\\Downarrow",!0),_(j,Z,oe,"\u2195","\\updownarrow",!0),_(j,Z,oe,"\u21d5","\\Updownarrow",!0),_(j,Z,ne,"\u2210","\\coprod"),_(j,Z,ne,"\u22c1","\\bigvee"),_(j,Z,ne,"\u22c0","\\bigwedge"),_(j,Z,ne,"\u2a04","\\biguplus"),_(j,Z,ne,"\u22c2","\\bigcap"),_(j,Z,ne,"\u22c3","\\bigcup"),_(j,Z,ne,"\u222b","\\int"),_(j,Z,ne,"\u222b","\\intop"),_(j,Z,ne,"\u222c","\\iint"),_(j,Z,ne,"\u222d","\\iiint"),_(j,Z,ne,"\u220f","\\prod"),_(j,Z,ne,"\u2211","\\sum"),_(j,Z,ne,"\u2a02","\\bigotimes"),_(j,Z,ne,"\u2a01","\\bigoplus"),_(j,Z,ne,"\u2a00","\\bigodot"),_(j,Z,ne,"\u222e","\\oint"),_(j,Z,ne,"\u222f","\\oiint"),_(j,Z,ne,"\u2230","\\oiiint"),_(j,Z,ne,"\u2a06","\\bigsqcup"),_(j,Z,ne,"\u222b","\\smallint"),_($,Z,te,"\u2026","\\textellipsis"),_(j,Z,te,"\u2026","\\mathellipsis"),_($,Z,te,"\u2026","\\ldots",!0),_(j,Z,te,"\u2026","\\ldots",!0),_(j,Z,te,"\u22ef","\\@cdots",!0),_(j,Z,te,"\u22f1","\\ddots",!0),_(j,Z,le,"\u22ee","\\varvdots"),_(j,Z,J,"\u02ca","\\acute"),_(j,Z,J,"\u02cb","\\grave"),_(j,Z,J,"\xa8","\\ddot"),_(j,Z,J,"~","\\tilde"),_(j,Z,J,"\u02c9","\\bar"),_(j,Z,J,"\u02d8","\\breve"),_(j,Z,J,"\u02c7","\\check"),_(j,Z,J,"^","\\hat"),_(j,Z,J,"\u20d7","\\vec"),_(j,Z,J,"\u02d9","\\dot"),_(j,Z,J,"\u02da","\\mathring"),_(j,Z,re,"\ue131","\\@imath"),_(j,Z,re,"\ue237","\\@jmath"),_(j,Z,le,"\u0131","\u0131"),_(j,Z,le,"\u0237","\u0237"),_($,Z,le,"\u0131","\\i",!0),_($,Z,le,"\u0237","\\j",!0),_($,Z,le,"\xdf","\\ss",!0),_($,Z,le,"\xe6","\\ae",!0),_($,Z,le,"\u0153","\\oe",!0),_($,Z,le,"\xf8","\\o",!0),_($,Z,le,"\xc6","\\AE",!0),_($,Z,le,"\u0152","\\OE",!0),_($,Z,le,"\xd8","\\O",!0),_($,Z,J,"\u02ca","\\'"),_($,Z,J,"\u02cb","\\`"),_($,Z,J,"\u02c6","\\^"),_($,Z,J,"\u02dc","\\~"),_($,Z,J,"\u02c9","\\="),_($,Z,J,"\u02d8","\\u"),_($,Z,J,"\u02d9","\\."),_($,Z,J,"\u02da","\\r"),_($,Z,J,"\u02c7","\\v"),_($,Z,J,"\xa8",'\\"'),_($,Z,J,"\u02dd","\\H"),_($,Z,J,"\u25ef","\\textcircled");var he={"--":!0,"---":!0,"``":!0,"''":!0};_($,Z,le,"\u2013","--",!0),_($,Z,le,"\u2013","\\textendash"),_($,Z,le,"\u2014","---",!0),_($,Z,le,"\u2014","\\textemdash"),_($,Z,le,"\u2018","`",!0),_($,Z,le,"\u2018","\\textquoteleft"),_($,Z,le,"\u2019","'",!0),_($,Z,le,"\u2019","\\textquoteright"),_($,Z,le,"\u201c","``",!0),_($,Z,le,"\u201c","\\textquotedblleft"),_($,Z,le,"\u201d","''",!0),_($,Z,le,"\u201d","\\textquotedblright"),_(j,Z,le,"\xb0","\\degree",!0),_($,Z,le,"\xb0","\\degree"),_($,Z,le,"\xb0","\\textdegree",!0),_(j,Z,le,"\xa3","\\pounds"),_(j,Z,le,"\xa3","\\mathsterling",!0),_($,Z,le,"\xa3","\\pounds"),_($,Z,le,"\xa3","\\textsterling",!0),_(j,K,le,"\u2720","\\maltese"),_($,K,le,"\u2720","\\maltese");for(var me='0123456789/@."',ce=0;ce=5?0:e>=3?1:2]){var r=G[t]={cssEmPerMu:P.quad[t]/18};for(var n in P)P.hasOwnProperty(n)&&(r[n]=P[n][t])}return G[t]}(this.size)),this._fontMetrics},t.getColor=function(){return this.phantom?"transparent":this.color},e}();Ie.BASESIZE=6;var Oe=Ie,Re={pt:1,mm:7227/2540,cm:7227/254,in:72.27,bp:1.00375,pc:12,dd:1238/1157,cc:14856/1157,nd:685/642,nc:1370/107,sp:1/65536,px:1.00375},Ee={ex:!0,em:!0,mu:!0},He=function(e){return"string"!=typeof e&&(e=e.unit),e in Re||e in Ee||"ex"===e},Le=function(e,t){var r;if(e.unit in Re)r=Re[e.unit]/t.fontMetrics().ptPerEm/t.sizeMultiplier;else if("mu"===e.unit)r=t.fontMetrics().cssEmPerMu;else{var a;if(a=t.style.isTight()?t.havingStyle(t.style.text()):t,"ex"===e.unit)r=a.fontMetrics().xHeight;else{if("em"!==e.unit)throw new n("Invalid unit: '"+e.unit+"'");r=a.fontMetrics().quad}a!==t&&(r*=a.sizeMultiplier/t.sizeMultiplier)}return Math.min(e.number*r,t.maxSize)},De=function(e,t,r){return X[r][e]&&X[r][e].replace&&(e=X[r][e].replace),{value:e,metrics:V(e,t,r)}},Pe=function(e,t,r,n,a){var i,o=De(e,t,r),s=o.metrics;if(e=o.value,s){var l=s.italic;("text"===r||n&&"mathit"===n.font)&&(l=0),i=new O(e,s.height,s.depth,l,s.skew,s.width,a)}else"undefined"!=typeof console&&console.warn("No character metrics for '"+e+"' in style '"+t+"' and mode '"+r+"'"),i=new O(e,0,0,0,0,0,a);if(n){i.maxFontSize=n.sizeMultiplier,n.style.isTight()&&i.classes.push("mtight");var h=n.getColor();h&&(i.style.color=h)}return i},Fe=function(e,t){if(z(e.classes)!==z(t.classes)||e.skew!==t.skew||e.maxFontSize!==t.maxFontSize)return!1;if(1===e.classes.length){var r=e.classes[0];if("mbin"===r||"mord"===r)return!1}for(var n in e.style)if(e.style.hasOwnProperty(n)&&e.style[n]!==t.style[n])return!1;for(var a in t.style)if(t.style.hasOwnProperty(a)&&e.style[a]!==t.style[a])return!1;return!0},Ve=function(e){for(var t=0,r=0,n=0,a=0;at&&(t=i.height),i.depth>r&&(r=i.depth),i.maxFontSize>n&&(n=i.maxFontSize)}e.height=t,e.depth=r,e.maxFontSize=n},Ge=function(e,t,r,n){var a=new q(e,t,r,n);return Ve(a),a},Ue=function(e,t,r,n){return new q(e,t,r,n)},Ye=function(e){var t=new M(e);return Ve(t),t},We=function(e,t,r){var n="";switch(e){case"amsrm":n="AMS";break;case"textrm":n="Main";break;case"textsf":n="SansSerif";break;case"texttt":n="Typewriter";break;default:n=e}return n+"-"+("textbf"===t&&"textit"===r?"BoldItalic":"textbf"===t?"Bold":"textit"===t?"Italic":"Regular")},Xe={mathbf:{variant:"bold",fontName:"Main-Bold"},mathrm:{variant:"normal",fontName:"Main-Regular"},textit:{variant:"italic",fontName:"Main-Italic"},mathit:{variant:"italic",fontName:"Main-Italic"},mathnormal:{variant:"italic",fontName:"Math-Italic"},mathbb:{variant:"double-struck",fontName:"AMS-Regular"},mathcal:{variant:"script",fontName:"Caligraphic-Regular"},mathfrak:{variant:"fraktur",fontName:"Fraktur-Regular"},mathscr:{variant:"script",fontName:"Script-Regular"},mathsf:{variant:"sans-serif",fontName:"SansSerif-Regular"},mathtt:{variant:"monospace",fontName:"Typewriter-Regular"}},_e={vec:["vec",.471,.714],oiintSize1:["oiintSize1",.957,.499],oiintSize2:["oiintSize2",1.472,.659],oiiintSize1:["oiiintSize1",1.304,.499],oiiintSize2:["oiiintSize2",1.98,.659]},je={fontMap:Xe,makeSymbol:Pe,mathsym:function(e,t,r,n){return void 0===n&&(n=[]),"boldsymbol"===r.font&&De(e,"Main-Bold",t).metrics?Pe(e,"Main-Bold",t,r,n.concat(["mathbf"])):"\\"===e||"main"===X[t][e].font?Pe(e,"Main-Regular",t,r,n):Pe(e,"AMS-Regular",t,r,n.concat(["amsrm"]))},makeSpan:Ge,makeSvgSpan:Ue,makeLineSpan:function(e,t,r){var n=Ge([e],[],t);return n.height=Math.max(r||t.fontMetrics().defaultRuleThickness,t.minRuleThickness),n.style.borderBottomWidth=n.height+"em",n.maxFontSize=1,n},makeAnchor:function(e,t,r,n){var a=new N(e,t,r,n);return Ve(a),a},makeFragment:Ye,wrapFragment:function(e,t){return e instanceof M?Ge([],[e],t):e},makeVList:function(e,t){for(var r=function(e){if("individualShift"===e.positionType){for(var t=e.children,r=[t[0]],n=-t[0].shift-t[0].elem.depth,a=n,i=1;i0&&(o.push(yt(s,t)),s=[]),o.push(a[l]));s.length>0&&o.push(yt(s,t)),r?((i=yt(ut(r,t,!0))).classes=["tag"],o.push(i)):n&&o.push(n);var m=st(["katex-html"],o);if(m.setAttribute("aria-hidden","true"),i){var c=i.children[0];c.style.height=m.height+m.depth+"em",c.style.verticalAlign=-m.depth+"em"}return m}function wt(e){return new M(e)}var kt=function(){function e(e,t,r){this.type=void 0,this.attributes=void 0,this.children=void 0,this.classes=void 0,this.type=e,this.attributes={},this.children=t||[],this.classes=r||[]}var t=e.prototype;return t.setAttribute=function(e,t){this.attributes[e]=t},t.getAttribute=function(e){return this.attributes[e]},t.toNode=function(){var e=document.createElementNS("http://www.w3.org/1998/Math/MathML",this.type);for(var t in this.attributes)Object.prototype.hasOwnProperty.call(this.attributes,t)&&e.setAttribute(t,this.attributes[t]);this.classes.length>0&&(e.className=z(this.classes));for(var r=0;r0&&(e+=' class ="'+l.escape(z(this.classes))+'"'),e+=">";for(var r=0;r"},t.toText=function(){return this.children.map((function(e){return e.toText()})).join("")},e}(),St=function(){function e(e){this.text=void 0,this.text=e}var t=e.prototype;return t.toNode=function(){return document.createTextNode(this.text)},t.toMarkup=function(){return l.escape(this.toText())},t.toText=function(){return this.text},e}(),Mt={MathNode:kt,TextNode:St,SpaceNode:function(){function e(e){this.width=void 0,this.character=void 0,this.width=e,this.character=e>=.05555&&e<=.05556?"\u200a":e>=.1666&&e<=.1667?"\u2009":e>=.2222&&e<=.2223?"\u2005":e>=.2777&&e<=.2778?"\u2005\u200a":e>=-.05556&&e<=-.05555?"\u200a\u2063":e>=-.1667&&e<=-.1666?"\u2009\u2063":e>=-.2223&&e<=-.2222?"\u205f\u2063":e>=-.2778&&e<=-.2777?"\u2005\u2063":null}var t=e.prototype;return t.toNode=function(){if(this.character)return document.createTextNode(this.character);var e=document.createElementNS("http://www.w3.org/1998/Math/MathML","mspace");return e.setAttribute("width",this.width+"em"),e},t.toMarkup=function(){return this.character?""+this.character+"":''},t.toText=function(){return this.character?this.character:" "},e}(),newDocumentFragment:wt},zt=function(e,t,r){return!X[t][e]||!X[t][e].replace||55349===e.charCodeAt(0)||he.hasOwnProperty(e)&&r&&(r.fontFamily&&"tt"===r.fontFamily.substr(4,2)||r.font&&"tt"===r.font.substr(4,2))||(e=X[t][e].replace),new Mt.TextNode(e)},At=function(e){return 1===e.length?e[0]:new Mt.MathNode("mrow",e)},Tt=function(e,t){if("texttt"===t.fontFamily)return"monospace";if("textsf"===t.fontFamily)return"textit"===t.fontShape&&"textbf"===t.fontWeight?"sans-serif-bold-italic":"textit"===t.fontShape?"sans-serif-italic":"textbf"===t.fontWeight?"bold-sans-serif":"sans-serif";if("textit"===t.fontShape&&"textbf"===t.fontWeight)return"bold-italic";if("textit"===t.fontShape)return"italic";if("textbf"===t.fontWeight)return"bold";var r=t.font;if(!r||"mathnormal"===r)return null;var n=e.mode;if("mathit"===r)return"italic";if("boldsymbol"===r)return"textord"===e.type?"bold":"bold-italic";if("mathbf"===r)return"bold";if("mathbb"===r)return"double-struck";if("mathfrak"===r)return"fraktur";if("mathscr"===r||"mathcal"===r)return"script";if("mathsf"===r)return"sans-serif";if("mathtt"===r)return"monospace";var a=e.text;return l.contains(["\\imath","\\jmath"],a)?null:(X[n][a]&&X[n][a].replace&&(a=X[n][a].replace),V(a,je.fontMap[r].fontName,n)?je.fontMap[r].variant:null)},Bt=function(e,t,r){if(1===e.length){var n=Nt(e[0],t);return r&&n instanceof kt&&"mo"===n.type&&(n.setAttribute("lspace","0em"),n.setAttribute("rspace","0em")),[n]}for(var a,i=[],o=0;o0&&(p.text=p.text.slice(0,1)+"\u0338"+p.text.slice(1),i.pop())}}}i.push(s),a=s}return i},qt=function(e,t,r){return At(Bt(e,t,r))},Nt=function(e,t){if(!e)return new Mt.MathNode("mrow");if(rt[e.type])return rt[e.type](e,t);throw new n("Got group of unknown type: '"+e.type+"'")};function Ct(e,t,r,n,a){var i,o=Bt(e,r);i=1===o.length&&o[0]instanceof kt&&l.contains(["mrow","mtable"],o[0].type)?o[0]:new Mt.MathNode("mrow",o);var s=new Mt.MathNode("annotation",[new Mt.TextNode(t)]);s.setAttribute("encoding","application/x-tex");var h=new Mt.MathNode("semantics",[i,s]),m=new Mt.MathNode("math",[h]);m.setAttribute("xmlns","http://www.w3.org/1998/Math/MathML"),n&&m.setAttribute("display","block");var c=a?"katex":"katex-mathml";return je.makeSpan([c],[m])}var It=function(e){return new Oe({style:e.displayMode?b.DISPLAY:b.TEXT,maxSize:e.maxSize,minRuleThickness:e.minRuleThickness})},Ot=function(e,t){if(t.displayMode){var r=["katex-display"];t.leqno&&r.push("leqno"),t.fleqn&&r.push("fleqn"),e=je.makeSpan(r,[e])}return e},Rt=function(e,t,r){var n,a=It(r);if("mathml"===r.output)return Ct(e,t,a,r.displayMode,!0);if("html"===r.output){var i=xt(e,a);n=je.makeSpan(["katex"],[i])}else{var o=Ct(e,t,a,r.displayMode,!1),s=xt(e,a);n=je.makeSpan(["katex"],[o,s])}return Ot(n,r)},Et={widehat:"^",widecheck:"\u02c7",widetilde:"~",utilde:"~",overleftarrow:"\u2190",underleftarrow:"\u2190",xleftarrow:"\u2190",overrightarrow:"\u2192",underrightarrow:"\u2192",xrightarrow:"\u2192",underbrace:"\u23df",overbrace:"\u23de",overgroup:"\u23e0",undergroup:"\u23e1",overleftrightarrow:"\u2194",underleftrightarrow:"\u2194",xleftrightarrow:"\u2194",Overrightarrow:"\u21d2",xRightarrow:"\u21d2",overleftharpoon:"\u21bc",xleftharpoonup:"\u21bc",overrightharpoon:"\u21c0",xrightharpoonup:"\u21c0",xLeftarrow:"\u21d0",xLeftrightarrow:"\u21d4",xhookleftarrow:"\u21a9",xhookrightarrow:"\u21aa",xmapsto:"\u21a6",xrightharpoondown:"\u21c1",xleftharpoondown:"\u21bd",xrightleftharpoons:"\u21cc",xleftrightharpoons:"\u21cb",xtwoheadleftarrow:"\u219e",xtwoheadrightarrow:"\u21a0",xlongequal:"=",xtofrom:"\u21c4",xrightleftarrows:"\u21c4",xrightequilibrium:"\u21cc",xleftequilibrium:"\u21cb","\\\\cdrightarrow":"\u2192","\\\\cdleftarrow":"\u2190","\\\\cdlongequal":"="},Ht={overrightarrow:[["rightarrow"],.888,522,"xMaxYMin"],overleftarrow:[["leftarrow"],.888,522,"xMinYMin"],underrightarrow:[["rightarrow"],.888,522,"xMaxYMin"],underleftarrow:[["leftarrow"],.888,522,"xMinYMin"],xrightarrow:[["rightarrow"],1.469,522,"xMaxYMin"],"\\cdrightarrow":[["rightarrow"],3,522,"xMaxYMin"],xleftarrow:[["leftarrow"],1.469,522,"xMinYMin"],"\\cdleftarrow":[["leftarrow"],3,522,"xMinYMin"],Overrightarrow:[["doublerightarrow"],.888,560,"xMaxYMin"],xRightarrow:[["doublerightarrow"],1.526,560,"xMaxYMin"],xLeftarrow:[["doubleleftarrow"],1.526,560,"xMinYMin"],overleftharpoon:[["leftharpoon"],.888,522,"xMinYMin"],xleftharpoonup:[["leftharpoon"],.888,522,"xMinYMin"],xleftharpoondown:[["leftharpoondown"],.888,522,"xMinYMin"],overrightharpoon:[["rightharpoon"],.888,522,"xMaxYMin"],xrightharpoonup:[["rightharpoon"],.888,522,"xMaxYMin"],xrightharpoondown:[["rightharpoondown"],.888,522,"xMaxYMin"],xlongequal:[["longequal"],.888,334,"xMinYMin"],"\\cdlongequal":[["longequal"],3,334,"xMinYMin"],xtwoheadleftarrow:[["twoheadleftarrow"],.888,334,"xMinYMin"],xtwoheadrightarrow:[["twoheadrightarrow"],.888,334,"xMaxYMin"],overleftrightarrow:[["leftarrow","rightarrow"],.888,522],overbrace:[["leftbrace","midbrace","rightbrace"],1.6,548],underbrace:[["leftbraceunder","midbraceunder","rightbraceunder"],1.6,548],underleftrightarrow:[["leftarrow","rightarrow"],.888,522],xleftrightarrow:[["leftarrow","rightarrow"],1.75,522],xLeftrightarrow:[["doubleleftarrow","doublerightarrow"],1.75,560],xrightleftharpoons:[["leftharpoondownplus","rightharpoonplus"],1.75,716],xleftrightharpoons:[["leftharpoonplus","rightharpoondownplus"],1.75,716],xhookleftarrow:[["leftarrow","righthook"],1.08,522],xhookrightarrow:[["lefthook","rightarrow"],1.08,522],overlinesegment:[["leftlinesegment","rightlinesegment"],.888,522],underlinesegment:[["leftlinesegment","rightlinesegment"],.888,522],overgroup:[["leftgroup","rightgroup"],.888,342],undergroup:[["leftgroupunder","rightgroupunder"],.888,342],xmapsto:[["leftmapsto","rightarrow"],1.5,522],xtofrom:[["leftToFrom","rightToFrom"],1.75,528],xrightleftarrows:[["baraboveleftarrow","rightarrowabovebar"],1.75,901],xrightequilibrium:[["baraboveshortleftharpoon","rightharpoonaboveshortbar"],1.75,716],xleftequilibrium:[["shortbaraboveleftharpoon","shortrightharpoonabovebar"],1.75,716]},Lt=function(e,t,r,n,a){var i,o=e.height+e.depth+r+n;if(/fbox|color|angl/.test(t)){if(i=je.makeSpan(["stretchy",t],[],a),"fbox"===t){var s=a.color&&a.getColor();s&&(i.style.borderColor=s)}}else{var l=[];/^[bx]cancel$/.test(t)&&l.push(new H({x1:"0",y1:"0",x2:"100%",y2:"100%","stroke-width":"0.046em"})),/^x?cancel$/.test(t)&&l.push(new H({x1:"0",y1:"100%",x2:"100%",y2:"0","stroke-width":"0.046em"}));var h=new R(l,{width:"100%",height:o+"em"});i=je.makeSvgSpan([],[h],a)}return i.height=o,i.style.height=o+"em",i},Dt=function(e){var t=new Mt.MathNode("mo",[new Mt.TextNode(Et[e])]);return t.setAttribute("stretchy","true"),t},Pt=function(e,t){var r=function(){var r=4e5,n=e.label.substr(1);if(l.contains(["widehat","widecheck","widetilde","utilde"],n)){var a,i,o,s="ordgroup"===(d=e.base).type?d.body.length:1;if(s>5)"widehat"===n||"widecheck"===n?(a=420,r=2364,o=.42,i=n+"4"):(a=312,r=2340,o=.34,i="tilde4");else{var h=[1,1,2,2,3,3][s];"widehat"===n||"widecheck"===n?(r=[0,1062,2364,2364,2364][h],a=[0,239,300,360,420][h],o=[0,.24,.3,.3,.36,.42][h],i=n+h):(r=[0,600,1033,2339,2340][h],a=[0,260,286,306,312][h],o=[0,.26,.286,.3,.306,.34][h],i="tilde"+h)}var m=new E(i),c=new R([m],{width:"100%",height:o+"em",viewBox:"0 0 "+r+" "+a,preserveAspectRatio:"none"});return{span:je.makeSvgSpan([],[c],t),minWidth:0,height:o}}var u,p,d,f=[],g=Ht[n],v=g[0],b=g[1],y=g[2],x=y/1e3,w=v.length;if(1===w)u=["hide-tail"],p=[g[3]];else if(2===w)u=["halfarrow-left","halfarrow-right"],p=["xMinYMin","xMaxYMin"];else{if(3!==w)throw new Error("Correct katexImagesData or update code here to support\n "+w+" children.");u=["brace-left","brace-center","brace-right"],p=["xMinYMin","xMidYMin","xMaxYMin"]}for(var k=0;k0&&(n.style.minWidth=a+"em"),n};function Ft(e,t){if(!e||e.type!==t)throw new Error("Expected node of type "+t+", but got "+(e?"node of type "+e.type:String(e)));return e}function Vt(e){var t=Gt(e);if(!t)throw new Error("Expected node of symbol group type, but got "+(e?"node of type "+e.type:String(e)));return t}function Gt(e){return e&&("atom"===e.type||Y.hasOwnProperty(e.type))?e:null}var Ut=function(e,t){var r,n,a;e&&"supsub"===e.type?(r=(n=Ft(e.base,"accent")).base,e.base=r,a=function(e){if(e instanceof q)return e;throw new Error("Expected span but got "+String(e)+".")}(bt(e,t)),e.base=n):r=(n=Ft(e,"accent")).base;var i=bt(r,t.havingCrampedStyle()),o=0;if(n.isShifty&&l.isCharacterBox(r)){var s=l.getBaseElem(r);o=L(bt(s,t.havingCrampedStyle())).skew}var h,m=Math.min(i.height,t.fontMetrics().xHeight);if(n.isStretchy)h=Pt(n,t),h=je.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:i},{type:"elem",elem:h,wrapperClasses:["svg-align"],wrapperStyle:o>0?{width:"calc(100% - "+2*o+"em)",marginLeft:2*o+"em"}:void 0}]},t);else{var c,u;"\\vec"===n.label?(c=je.staticSvg("vec",t),u=je.svgData.vec[1]):((c=L(c=je.makeOrd({mode:n.mode,text:n.label},t,"textord"))).italic=0,u=c.width),h=je.makeSpan(["accent-body"],[c]);var p="\\textcircled"===n.label;p&&(h.classes.push("accent-full"),m=i.height);var d=o;p||(d-=u/2),h.style.left=d+"em","\\textcircled"===n.label&&(h.style.top=".2em"),h=je.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:i},{type:"kern",size:-m},{type:"elem",elem:h}]},t)}var f=je.makeSpan(["mord","accent"],[h],t);return a?(a.children[0]=f,a.height=Math.max(f.height,a.height),a.classes[0]="mord",a):f},Yt=function(e,t){var r=e.isStretchy?Dt(e.label):new Mt.MathNode("mo",[zt(e.label,e.mode)]),n=new Mt.MathNode("mover",[Nt(e.base,t),r]);return n.setAttribute("accent","true"),n},Wt=new RegExp(["\\acute","\\grave","\\ddot","\\tilde","\\bar","\\breve","\\check","\\hat","\\vec","\\dot","\\mathring"].map((function(e){return"\\"+e})).join("|"));nt({type:"accent",names:["\\acute","\\grave","\\ddot","\\tilde","\\bar","\\breve","\\check","\\hat","\\vec","\\dot","\\mathring","\\widecheck","\\widehat","\\widetilde","\\overrightarrow","\\overleftarrow","\\Overrightarrow","\\overleftrightarrow","\\overgroup","\\overlinesegment","\\overleftharpoon","\\overrightharpoon"],props:{numArgs:1},handler:function(e,t){var r=it(t[0]),n=!Wt.test(e.funcName),a=!n||"\\widehat"===e.funcName||"\\widetilde"===e.funcName||"\\widecheck"===e.funcName;return{type:"accent",mode:e.parser.mode,label:e.funcName,isStretchy:n,isShifty:a,base:r}},htmlBuilder:Ut,mathmlBuilder:Yt}),nt({type:"accent",names:["\\'","\\`","\\^","\\~","\\=","\\u","\\.",'\\"',"\\r","\\H","\\v","\\textcircled"],props:{numArgs:1,allowedInText:!0,allowedInMath:!1,argTypes:["primitive"]},handler:function(e,t){var r=t[0];return{type:"accent",mode:e.parser.mode,label:e.funcName,isStretchy:!1,isShifty:!0,base:r}},htmlBuilder:Ut,mathmlBuilder:Yt}),nt({type:"accentUnder",names:["\\underleftarrow","\\underrightarrow","\\underleftrightarrow","\\undergroup","\\underlinesegment","\\utilde"],props:{numArgs:1},handler:function(e,t){var r=e.parser,n=e.funcName,a=t[0];return{type:"accentUnder",mode:r.mode,label:n,base:a}},htmlBuilder:function(e,t){var r=bt(e.base,t),n=Pt(e,t),a="\\utilde"===e.label?.12:0,i=je.makeVList({positionType:"top",positionData:r.height,children:[{type:"elem",elem:n,wrapperClasses:["svg-align"]},{type:"kern",size:a},{type:"elem",elem:r}]},t);return je.makeSpan(["mord","accentunder"],[i],t)},mathmlBuilder:function(e,t){var r=Dt(e.label),n=new Mt.MathNode("munder",[Nt(e.base,t),r]);return n.setAttribute("accentunder","true"),n}});var Xt=function(e){var t=new Mt.MathNode("mpadded",e?[e]:[]);return t.setAttribute("width","+0.6em"),t.setAttribute("lspace","0.3em"),t};nt({type:"xArrow",names:["\\xleftarrow","\\xrightarrow","\\xLeftarrow","\\xRightarrow","\\xleftrightarrow","\\xLeftrightarrow","\\xhookleftarrow","\\xhookrightarrow","\\xmapsto","\\xrightharpoondown","\\xrightharpoonup","\\xleftharpoondown","\\xleftharpoonup","\\xrightleftharpoons","\\xleftrightharpoons","\\xlongequal","\\xtwoheadrightarrow","\\xtwoheadleftarrow","\\xtofrom","\\xrightleftarrows","\\xrightequilibrium","\\xleftequilibrium","\\\\cdrightarrow","\\\\cdleftarrow","\\\\cdlongequal"],props:{numArgs:1,numOptionalArgs:1},handler:function(e,t,r){var n=e.parser,a=e.funcName;return{type:"xArrow",mode:n.mode,label:a,body:t[0],below:r[0]}},htmlBuilder:function(e,t){var r,n=t.style,a=t.havingStyle(n.sup()),i=je.wrapFragment(bt(e.body,a,t),t),o="\\x"===e.label.slice(0,2)?"x":"cd";i.classes.push(o+"-arrow-pad"),e.below&&(a=t.havingStyle(n.sub()),(r=je.wrapFragment(bt(e.below,a,t),t)).classes.push(o+"-arrow-pad"));var s,l=Pt(e,t),h=-t.fontMetrics().axisHeight+.5*l.height,m=-t.fontMetrics().axisHeight-.5*l.height-.111;if((i.depth>.25||"\\xleftequilibrium"===e.label)&&(m-=i.depth),r){var c=-t.fontMetrics().axisHeight+r.height+.5*l.height+.111;s=je.makeVList({positionType:"individualShift",children:[{type:"elem",elem:i,shift:m},{type:"elem",elem:l,shift:h},{type:"elem",elem:r,shift:c}]},t)}else s=je.makeVList({positionType:"individualShift",children:[{type:"elem",elem:i,shift:m},{type:"elem",elem:l,shift:h}]},t);return s.children[0].children[0].children[1].classes.push("svg-align"),je.makeSpan(["mrel","x-arrow"],[s],t)},mathmlBuilder:function(e,t){var r,n=Dt(e.label);if(n.setAttribute("minsize","x"===e.label.charAt(0)?"1.75em":"3.0em"),e.body){var a=Xt(Nt(e.body,t));if(e.below){var i=Xt(Nt(e.below,t));r=new Mt.MathNode("munderover",[n,i,a])}else r=new Mt.MathNode("mover",[n,a])}else if(e.below){var o=Xt(Nt(e.below,t));r=new Mt.MathNode("munder",[n,o])}else r=Xt(),r=new Mt.MathNode("mover",[n,r]);return r}});var _t={">":"\\\\cdrightarrow","<":"\\\\cdleftarrow","=":"\\\\cdlongequal",A:"\\uparrow",V:"\\downarrow","|":"\\Vert",".":"no arrow"},jt=function(e){return"textord"===e.type&&"@"===e.text};function $t(e,t,r){var n=_t[e];switch(n){case"\\\\cdrightarrow":case"\\\\cdleftarrow":return r.callFunction(n,[t[0]],[t[1]]);case"\\uparrow":case"\\downarrow":var a={type:"atom",text:n,mode:"math",family:"rel"},i={type:"ordgroup",mode:"math",body:[r.callFunction("\\\\cdleft",[t[0]],[]),r.callFunction("\\Big",[a],[]),r.callFunction("\\\\cdright",[t[1]],[])]};return r.callFunction("\\\\cdparent",[i],[]);case"\\\\cdlongequal":return r.callFunction("\\\\cdlongequal",[],[]);case"\\Vert":return r.callFunction("\\Big",[{type:"textord",text:"\\Vert",mode:"math"}],[]);default:return{type:"textord",text:" ",mode:"math"}}}nt({type:"cdlabel",names:["\\\\cdleft","\\\\cdright"],props:{numArgs:1},handler:function(e,t){var r=e.parser,n=e.funcName;return{type:"cdlabel",mode:r.mode,side:n.slice(4),label:t[0]}},htmlBuilder:function(e,t){var r=t.havingStyle(t.style.sup()),n=je.wrapFragment(bt(e.label,r,t),t);return n.classes.push("cd-label-"+e.side),n.style.bottom=.8-n.depth+"em",n.height=0,n.depth=0,n},mathmlBuilder:function(e,t){var r=new Mt.MathNode("mrow",[Nt(e.label,t)]);return(r=new Mt.MathNode("mpadded",[r])).setAttribute("width","0"),"left"===e.side&&r.setAttribute("lspace","-1width"),r.setAttribute("voffset","0.7em"),(r=new Mt.MathNode("mstyle",[r])).setAttribute("displaystyle","false"),r.setAttribute("scriptlevel","1"),r}}),nt({type:"cdlabelparent",names:["\\\\cdparent"],props:{numArgs:1},handler:function(e,t){return{type:"cdlabelparent",mode:e.parser.mode,fragment:t[0]}},htmlBuilder:function(e,t){var r=je.wrapFragment(bt(e.fragment,t),t);return r.classes.push("cd-vert-arrow"),r},mathmlBuilder:function(e,t){return new Mt.MathNode("mrow",[Nt(e.fragment,t)])}}),nt({type:"textord",names:["\\@char"],props:{numArgs:1,allowedInText:!0},handler:function(e,t){for(var r=e.parser,a=Ft(t[0],"ordgroup").body,i="",o=0;o","\\langle","\\rangle","/","\\backslash","\\lt","\\gt"],gr=[0,1.2,1.8,2.4,3],vr=[{type:"small",style:b.SCRIPTSCRIPT},{type:"small",style:b.SCRIPT},{type:"small",style:b.TEXT},{type:"large",size:1},{type:"large",size:2},{type:"large",size:3},{type:"large",size:4}],br=[{type:"small",style:b.SCRIPTSCRIPT},{type:"small",style:b.SCRIPT},{type:"small",style:b.TEXT},{type:"stack"}],yr=[{type:"small",style:b.SCRIPTSCRIPT},{type:"small",style:b.SCRIPT},{type:"small",style:b.TEXT},{type:"large",size:1},{type:"large",size:2},{type:"large",size:3},{type:"large",size:4},{type:"stack"}],xr=function(e){if("small"===e.type)return"Main-Regular";if("large"===e.type)return"Size"+e.size+"-Regular";if("stack"===e.type)return"Size4-Regular";throw new Error("Add support for delim type '"+e.type+"' here.")},wr=function(e,t,r,n){for(var a=Math.min(2,3-n.style.size);at)return r[a]}return r[r.length-1]},kr=function(e,t,r,n,a,i){var o;"<"===e||"\\lt"===e||"\u27e8"===e?e="\\langle":">"!==e&&"\\gt"!==e&&"\u27e9"!==e||(e="\\rangle"),o=l.contains(fr,e)?vr:l.contains(pr,e)?yr:br;var s=wr(e,t,o,n);return"small"===s.type?function(e,t,r,n,a,i){var o=je.makeSymbol(e,"Main-Regular",a,n),s=rr(o,t,n,i);return r&&nr(s,n,t),s}(e,s.style,r,n,a,i):"large"===s.type?ar(e,s.size,r,n,a,i):mr(e,t,r,n,a,i)},Sr=function(e,t){var r,n,a=t.havingBaseSizing(),i=wr("\\surd",e*a.sizeMultiplier,yr,a),o=a.sizeMultiplier,s=Math.max(0,t.minRuleThickness-t.fontMetrics().sqrtRuleThickness),l=0,h=0,m=0;return"small"===i.type?(e<1?o=1:e<1.4&&(o=.7),h=(1+s)/o,(r=ur("sqrtMain",l=(1+s+cr)/o,m=1e3+1e3*s+80,s,t)).style.minWidth="0.853em",n=.833/o):"large"===i.type?(m=1080*gr[i.size],h=(gr[i.size]+s)/o,l=(gr[i.size]+s+cr)/o,(r=ur("sqrtSize"+i.size,l,m,s,t)).style.minWidth="1.02em",n=1/o):(l=e+s+cr,h=e+s,m=Math.floor(1e3*e+s)+80,(r=ur("sqrtTall",l,m,s,t)).style.minWidth="0.742em",n=1.056),r.height=h,r.style.height=l+"em",{span:r,advanceWidth:n,ruleWidth:(t.fontMetrics().sqrtRuleThickness+s)*o}},Mr=function(e,t,r,a,i){if("<"===e||"\\lt"===e||"\u27e8"===e?e="\\langle":">"!==e&&"\\gt"!==e&&"\u27e9"!==e||(e="\\rangle"),l.contains(pr,e)||l.contains(fr,e))return ar(e,t,!1,r,a,i);if(l.contains(dr,e))return mr(e,gr[t],!1,r,a,i);throw new n("Illegal delimiter: '"+e+"'")},zr=gr,Ar=kr,Tr=function(e,t,r,n,a,i){var o=n.fontMetrics().axisHeight*n.sizeMultiplier,s=5/n.fontMetrics().ptPerEm,l=Math.max(t-o,r+o),h=Math.max(l/500*901,2*l-s);return kr(e,h,!0,n,a,i)},Br={"\\bigl":{mclass:"mopen",size:1},"\\Bigl":{mclass:"mopen",size:2},"\\biggl":{mclass:"mopen",size:3},"\\Biggl":{mclass:"mopen",size:4},"\\bigr":{mclass:"mclose",size:1},"\\Bigr":{mclass:"mclose",size:2},"\\biggr":{mclass:"mclose",size:3},"\\Biggr":{mclass:"mclose",size:4},"\\bigm":{mclass:"mrel",size:1},"\\Bigm":{mclass:"mrel",size:2},"\\biggm":{mclass:"mrel",size:3},"\\Biggm":{mclass:"mrel",size:4},"\\big":{mclass:"mord",size:1},"\\Big":{mclass:"mord",size:2},"\\bigg":{mclass:"mord",size:3},"\\Bigg":{mclass:"mord",size:4}},qr=["(","\\lparen",")","\\rparen","[","\\lbrack","]","\\rbrack","\\{","\\lbrace","\\}","\\rbrace","\\lfloor","\\rfloor","\u230a","\u230b","\\lceil","\\rceil","\u2308","\u2309","<",">","\\langle","\u27e8","\\rangle","\u27e9","\\lt","\\gt","\\lvert","\\rvert","\\lVert","\\rVert","\\lgroup","\\rgroup","\u27ee","\u27ef","\\lmoustache","\\rmoustache","\u23b0","\u23b1","/","\\backslash","|","\\vert","\\|","\\Vert","\\uparrow","\\Uparrow","\\downarrow","\\Downarrow","\\updownarrow","\\Updownarrow","."];function Nr(e,t){var r=Gt(e);if(r&&l.contains(qr,r.text))return r;throw new n(r?"Invalid delimiter '"+r.text+"' after '"+t.funcName+"'":"Invalid delimiter type '"+e.type+"'",e)}function Cr(e){if(!e.body)throw new Error("Bug: The leftright ParseNode wasn't fully parsed.")}nt({type:"delimsizing",names:["\\bigl","\\Bigl","\\biggl","\\Biggl","\\bigr","\\Bigr","\\biggr","\\Biggr","\\bigm","\\Bigm","\\biggm","\\Biggm","\\big","\\Big","\\bigg","\\Bigg"],props:{numArgs:1,argTypes:["primitive"]},handler:function(e,t){var r=Nr(t[0],e);return{type:"delimsizing",mode:e.parser.mode,size:Br[e.funcName].size,mclass:Br[e.funcName].mclass,delim:r.text}},htmlBuilder:function(e,t){return"."===e.delim?je.makeSpan([e.mclass]):Mr(e.delim,e.size,t,e.mode,[e.mclass])},mathmlBuilder:function(e){var t=[];"."!==e.delim&&t.push(zt(e.delim,e.mode));var r=new Mt.MathNode("mo",t);return"mopen"===e.mclass||"mclose"===e.mclass?r.setAttribute("fence","true"):r.setAttribute("fence","false"),r.setAttribute("stretchy","true"),r.setAttribute("minsize",zr[e.size]+"em"),r.setAttribute("maxsize",zr[e.size]+"em"),r}}),nt({type:"leftright-right",names:["\\right"],props:{numArgs:1,primitive:!0},handler:function(e,t){var r=e.parser.gullet.macros.get("\\current@color");if(r&&"string"!=typeof r)throw new n("\\current@color set to non-string in \\right");return{type:"leftright-right",mode:e.parser.mode,delim:Nr(t[0],e).text,color:r}}}),nt({type:"leftright",names:["\\left"],props:{numArgs:1,primitive:!0},handler:function(e,t){var r=Nr(t[0],e),n=e.parser;++n.leftrightDepth;var a=n.parseExpression(!1);--n.leftrightDepth,n.expect("\\right",!1);var i=Ft(n.parseFunction(),"leftright-right");return{type:"leftright",mode:n.mode,body:a,left:r.text,right:i.delim,rightColor:i.color}},htmlBuilder:function(e,t){Cr(e);for(var r,n,a=ut(e.body,t,!0,["mopen","mclose"]),i=0,o=0,s=!1,l=0;l-1?"mpadded":"menclose",[Nt(e.body,t)]);switch(e.label){case"\\cancel":n.setAttribute("notation","updiagonalstrike");break;case"\\bcancel":n.setAttribute("notation","downdiagonalstrike");break;case"\\phase":n.setAttribute("notation","phasorangle");break;case"\\sout":n.setAttribute("notation","horizontalstrike");break;case"\\fbox":n.setAttribute("notation","box");break;case"\\angl":n.setAttribute("notation","actuarial");break;case"\\fcolorbox":case"\\colorbox":if(r=t.fontMetrics().fboxsep*t.fontMetrics().ptPerEm,n.setAttribute("width","+"+2*r+"pt"),n.setAttribute("height","+"+2*r+"pt"),n.setAttribute("lspace",r+"pt"),n.setAttribute("voffset",r+"pt"),"\\fcolorbox"===e.label){var a=Math.max(t.fontMetrics().fboxrule,t.minRuleThickness);n.setAttribute("style","border: "+a+"em solid "+String(e.borderColor))}break;case"\\xcancel":n.setAttribute("notation","updiagonalstrike downdiagonalstrike")}return e.backgroundColor&&n.setAttribute("mathbackground",e.backgroundColor),n};nt({type:"enclose",names:["\\colorbox"],props:{numArgs:2,allowedInText:!0,argTypes:["color","text"]},handler:function(e,t,r){var n=e.parser,a=e.funcName,i=Ft(t[0],"color-token").color,o=t[1];return{type:"enclose",mode:n.mode,label:a,backgroundColor:i,body:o}},htmlBuilder:Ir,mathmlBuilder:Or}),nt({type:"enclose",names:["\\fcolorbox"],props:{numArgs:3,allowedInText:!0,argTypes:["color","color","text"]},handler:function(e,t,r){var n=e.parser,a=e.funcName,i=Ft(t[0],"color-token").color,o=Ft(t[1],"color-token").color,s=t[2];return{type:"enclose",mode:n.mode,label:a,backgroundColor:o,borderColor:i,body:s}},htmlBuilder:Ir,mathmlBuilder:Or}),nt({type:"enclose",names:["\\fbox"],props:{numArgs:1,argTypes:["hbox"],allowedInText:!0},handler:function(e,t){return{type:"enclose",mode:e.parser.mode,label:"\\fbox",body:t[0]}}}),nt({type:"enclose",names:["\\cancel","\\bcancel","\\xcancel","\\sout","\\phase"],props:{numArgs:1},handler:function(e,t){var r=e.parser,n=e.funcName,a=t[0];return{type:"enclose",mode:r.mode,label:n,body:a}},htmlBuilder:Ir,mathmlBuilder:Or}),nt({type:"enclose",names:["\\angl"],props:{numArgs:1,argTypes:["hbox"],allowedInText:!1},handler:function(e,t){return{type:"enclose",mode:e.parser.mode,label:"\\angl",body:t[0]}}});var Rr={};function Er(e){for(var t=e.type,r=e.names,n=e.props,a=e.handler,i=e.htmlBuilder,o=e.mathmlBuilder,s={type:t,numArgs:n.numArgs||0,allowedInText:!1,numOptionalArgs:0,handler:a},l=0;l0&&(x+=.25),m.push({pos:x,isDashed:e[t]})}for(w(o[0]),r=0;r0&&(M<(B+=y)&&(M=B),B=0),e.addJot&&(M+=f),z.height=S,z.depth=M,x+=S,z.pos=x,x+=M+B,h[r]=z,w(o[r+1])}var q,N,C=x/2+t.fontMetrics().axisHeight,I=e.cols||[],O=[],R=[];if(e.addEqnNum)for(r=0;r=s)){var G=void 0;(a>0||e.hskipBeforeAndAfter)&&0!==(G=l.deflt(D.pregap,p))&&((q=je.makeSpan(["arraycolsep"],[])).style.width=G+"em",O.push(q));var U=[];for(r=0;r0){for(var _=je.makeLineSpan("hline",t,c),j=je.makeLineSpan("hdashline",t,c),$=[{type:"elem",elem:h,shift:0}];m.length>0;){var Z=m.pop(),K=Z.pos-C;Z.isDashed?$.push({type:"elem",elem:j,shift:K}):$.push({type:"elem",elem:_,shift:K})}h=je.makeVList({positionType:"individualShift",children:$},t)}if(e.addEqnNum){var J=je.makeVList({positionType:"individualShift",children:R},t);return J=je.makeSpan(["tag"],[J],t),je.makeFragment([h,J])}return je.makeSpan(["mord"],[h],t)},Vr={c:"center ",l:"left ",r:"right "},Gr=function(e,t){for(var r=[],n=new Mt.MathNode("mtd",[],["mtr-glue"]),a=new Mt.MathNode("mtd",[],["mml-eqn-num"]),i=0;i0){var p=e.cols,d="",f=!1,g=0,v=p.length;"separator"===p[0].type&&(c+="top ",g=1),"separator"===p[p.length-1].type&&(c+="bottom ",v-=1);for(var b=g;b0?"left ":"",c+=S[S.length-1].length>0?"right ":"";for(var M=1;M-1?"alignat":"align",o=Dr(e.parser,{cols:a,addJot:!0,addEqnNum:"align"===e.envName||"alignat"===e.envName,colSeparationType:i,maxNumCols:"split"===e.envName?2:void 0,leqno:e.parser.settings.leqno},"display"),s=0,l={type:"ordgroup",mode:e.mode,body:[]};if(t[0]&&"ordgroup"===t[0].type){for(var h="",m=0;m0&&c&&(d=1),a[u]={type:"align",align:p,pregap:d,postgap:0}}return o.colSeparationType=c?"align":"alignat",o};Er({type:"array",names:["array","darray"],props:{numArgs:1},handler:function(e,t){var r=(Gt(t[0])?[t[0]]:Ft(t[0],"ordgroup").body).map((function(e){var t=Vt(e).text;if(-1!=="lcr".indexOf(t))return{type:"align",align:t};if("|"===t)return{type:"separator",separator:"|"};if(":"===t)return{type:"separator",separator:":"};throw new n("Unknown column alignment: "+t,e)})),a={cols:r,hskipBeforeAndAfter:!0,maxNumCols:r.length};return Dr(e.parser,a,Pr(e.envName))},htmlBuilder:Fr,mathmlBuilder:Gr}),Er({type:"array",names:["matrix","pmatrix","bmatrix","Bmatrix","vmatrix","Vmatrix","matrix*","pmatrix*","bmatrix*","Bmatrix*","vmatrix*","Vmatrix*"],props:{numArgs:0},handler:function(e){var t={matrix:null,pmatrix:["(",")"],bmatrix:["[","]"],Bmatrix:["\\{","\\}"],vmatrix:["|","|"],Vmatrix:["\\Vert","\\Vert"]}[e.envName.replace("*","")],r="c",a={hskipBeforeAndAfter:!1,cols:[{type:"align",align:r}]};if("*"===e.envName.charAt(e.envName.length-1)){var i=e.parser;if(i.consumeSpaces(),"["===i.fetch().text){if(i.consume(),i.consumeSpaces(),r=i.fetch().text,-1==="lcr".indexOf(r))throw new n("Expected l or c or r",i.nextToken);i.consume(),i.consumeSpaces(),i.expect("]"),i.consume(),a.cols=[{type:"align",align:r}]}}var o=Dr(e.parser,a,Pr(e.envName));return o.cols=new Array(o.body[0].length).fill({type:"align",align:r}),t?{type:"leftright",mode:e.mode,body:[o],left:t[0],right:t[1],rightColor:void 0}:o},htmlBuilder:Fr,mathmlBuilder:Gr}),Er({type:"array",names:["smallmatrix"],props:{numArgs:0},handler:function(e){var t=Dr(e.parser,{arraystretch:.5},"script");return t.colSeparationType="small",t},htmlBuilder:Fr,mathmlBuilder:Gr}),Er({type:"array",names:["subarray"],props:{numArgs:1},handler:function(e,t){var r=(Gt(t[0])?[t[0]]:Ft(t[0],"ordgroup").body).map((function(e){var t=Vt(e).text;if(-1!=="lc".indexOf(t))return{type:"align",align:t};throw new n("Unknown column alignment: "+t,e)}));if(r.length>1)throw new n("{subarray} can contain only one column");var a={cols:r,hskipBeforeAndAfter:!1,arraystretch:.5};if((a=Dr(e.parser,a,"script")).body.length>0&&a.body[0].length>1)throw new n("{subarray} can contain only one column");return a},htmlBuilder:Fr,mathmlBuilder:Gr}),Er({type:"array",names:["cases","dcases","rcases","drcases"],props:{numArgs:0},handler:function(e){var t=Dr(e.parser,{arraystretch:1.2,cols:[{type:"align",align:"l",pregap:0,postgap:1},{type:"align",align:"l",pregap:0,postgap:0}]},Pr(e.envName));return{type:"leftright",mode:e.mode,body:[t],left:e.envName.indexOf("r")>-1?".":"\\{",right:e.envName.indexOf("r")>-1?"\\}":".",rightColor:void 0}},htmlBuilder:Fr,mathmlBuilder:Gr}),Er({type:"array",names:["align","align*","aligned","split"],props:{numArgs:0},handler:Ur,htmlBuilder:Fr,mathmlBuilder:Gr}),Er({type:"array",names:["gathered","gather","gather*"],props:{numArgs:0},handler:function(e){l.contains(["gather","gather*"],e.envName)&&Lr(e);var t={cols:[{type:"align",align:"c"}],addJot:!0,colSeparationType:"gather",addEqnNum:"gather"===e.envName,leqno:e.parser.settings.leqno};return Dr(e.parser,t,"display")},htmlBuilder:Fr,mathmlBuilder:Gr}),Er({type:"array",names:["alignat","alignat*","alignedat"],props:{numArgs:1},handler:Ur,htmlBuilder:Fr,mathmlBuilder:Gr}),Er({type:"array",names:["equation","equation*"],props:{numArgs:0},handler:function(e){Lr(e);var t={addEqnNum:"equation"===e.envName,singleRow:!0,maxNumCols:1,leqno:e.parser.settings.leqno};return Dr(e.parser,t,"display")},htmlBuilder:Fr,mathmlBuilder:Gr}),Er({type:"array",names:["CD"],props:{numArgs:0},handler:function(e){return Lr(e),function(e){var t=[];for(e.gullet.beginGroup(),e.gullet.macros.set("\\cr","\\\\\\relax"),e.gullet.beginGroup();;){t.push(e.parseExpression(!1,"\\\\")),e.gullet.endGroup(),e.gullet.beginGroup();var r=e.fetch().text;if("&"!==r&&"\\\\"!==r){if("\\end"===r){0===t[t.length-1].length&&t.pop();break}throw new n("Expected \\\\ or \\cr or \\end",e.nextToken)}e.consume()}for(var a,i,o=[],s=[o],l=0;l-1);else{if(!("<>AV".indexOf(u)>-1))throw new n('Expected one of "<>AV=|." after @',h[c]);for(var d=0;d<2;d++){for(var f=!0,g=c+1;g=b.SCRIPT.id?r.text():b.DISPLAY:"text"===e&&r.size===b.DISPLAY.size?r=b.TEXT:"script"===e?r=b.SCRIPT:"scriptscript"===e&&(r=b.SCRIPTSCRIPT),r},Qr=function(e,t){var r,n=Jr(e.size,t.style),a=n.fracNum(),i=n.fracDen();r=t.havingStyle(a);var o=bt(e.numer,r,t);if(e.continued){var s=8.5/t.fontMetrics().ptPerEm,l=3.5/t.fontMetrics().ptPerEm;o.height=o.height0?3*c:7*c,d=t.fontMetrics().denom1):(m>0?(u=t.fontMetrics().num2,p=c):(u=t.fontMetrics().num3,p=3*c),d=t.fontMetrics().denom2),h){var w=t.fontMetrics().axisHeight;u-o.depth-(w+.5*m)0&&(t="."===(t=e)?null:t),t};nt({type:"genfrac",names:["\\genfrac"],props:{numArgs:6,allowedInArgument:!0,argTypes:["math","math","size","text","math","math"]},handler:function(e,t){var r,n=e.parser,a=t[4],i=t[5],o=it(t[0]),s="atom"===o.type&&"open"===o.family?rn(o.text):null,l=it(t[1]),h="atom"===l.type&&"close"===l.family?rn(l.text):null,m=Ft(t[2],"size"),c=null;r=!!m.isBlank||(c=m.value).number>0;var u="auto",p=t[3];if("ordgroup"===p.type){if(p.body.length>0){var d=Ft(p.body[0],"textord");u=tn[Number(d.text)]}}else p=Ft(p,"textord"),u=tn[Number(p.text)];return{type:"genfrac",mode:n.mode,numer:a,denom:i,continued:!1,hasBarLine:r,barSize:c,leftDelim:s,rightDelim:h,size:u}},htmlBuilder:Qr,mathmlBuilder:en}),nt({type:"infix",names:["\\above"],props:{numArgs:1,argTypes:["size"],infix:!0},handler:function(e,t){var r=e.parser,n=(e.funcName,e.token);return{type:"infix",mode:r.mode,replaceWith:"\\\\abovefrac",size:Ft(t[0],"size").value,token:n}}}),nt({type:"genfrac",names:["\\\\abovefrac"],props:{numArgs:3,argTypes:["math","size","math"]},handler:function(e,t){var r=e.parser,n=(e.funcName,t[0]),a=function(e){if(!e)throw new Error("Expected non-null, but got "+String(e));return e}(Ft(t[1],"infix").size),i=t[2],o=a.number>0;return{type:"genfrac",mode:r.mode,numer:n,denom:i,continued:!1,hasBarLine:o,barSize:a,leftDelim:null,rightDelim:null,size:"auto"}},htmlBuilder:Qr,mathmlBuilder:en});var nn=function(e,t){var r,n,a=t.style;"supsub"===e.type?(r=e.sup?bt(e.sup,t.havingStyle(a.sup()),t):bt(e.sub,t.havingStyle(a.sub()),t),n=Ft(e.base,"horizBrace")):n=Ft(e,"horizBrace");var i,o=bt(n.base,t.havingBaseStyle(b.DISPLAY)),s=Pt(n,t);if(n.isOver?(i=je.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:o},{type:"kern",size:.1},{type:"elem",elem:s}]},t)).children[0].children[0].children[1].classes.push("svg-align"):(i=je.makeVList({positionType:"bottom",positionData:o.depth+.1+s.height,children:[{type:"elem",elem:s},{type:"kern",size:.1},{type:"elem",elem:o}]},t)).children[0].children[0].children[0].classes.push("svg-align"),r){var l=je.makeSpan(["mord",n.isOver?"mover":"munder"],[i],t);i=n.isOver?je.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:l},{type:"kern",size:.2},{type:"elem",elem:r}]},t):je.makeVList({positionType:"bottom",positionData:l.depth+.2+r.height+r.depth,children:[{type:"elem",elem:r},{type:"kern",size:.2},{type:"elem",elem:l}]},t)}return je.makeSpan(["mord",n.isOver?"mover":"munder"],[i],t)};nt({type:"horizBrace",names:["\\overbrace","\\underbrace"],props:{numArgs:1},handler:function(e,t){var r=e.parser,n=e.funcName;return{type:"horizBrace",mode:r.mode,label:n,isOver:/^\\over/.test(n),base:t[0]}},htmlBuilder:nn,mathmlBuilder:function(e,t){var r=Dt(e.label);return new Mt.MathNode(e.isOver?"mover":"munder",[Nt(e.base,t),r])}}),nt({type:"href",names:["\\href"],props:{numArgs:2,argTypes:["url","original"],allowedInText:!0},handler:function(e,t){var r=e.parser,n=t[1],a=Ft(t[0],"url").url;return r.settings.isTrusted({command:"\\href",url:a})?{type:"href",mode:r.mode,href:a,body:ot(n)}:r.formatUnsupportedCmd("\\href")},htmlBuilder:function(e,t){var r=ut(e.body,t,!1);return je.makeAnchor(e.href,[],r,t)},mathmlBuilder:function(e,t){var r=qt(e.body,t);return r instanceof kt||(r=new kt("mrow",[r])),r.setAttribute("href",e.href),r}}),nt({type:"href",names:["\\url"],props:{numArgs:1,argTypes:["url"],allowedInText:!0},handler:function(e,t){var r=e.parser,n=Ft(t[0],"url").url;if(!r.settings.isTrusted({command:"\\url",url:n}))return r.formatUnsupportedCmd("\\url");for(var a=[],i=0;i0&&(n=Le(e.totalheight,t)-r,n=Number(n.toFixed(2)));var a=0;e.width.number>0&&(a=Le(e.width,t));var i={height:r+n+"em"};a>0&&(i.width=a+"em"),n>0&&(i.verticalAlign=-n+"em");var o=new C(e.src,e.alt,i);return o.height=r,o.depth=n,o},mathmlBuilder:function(e,t){var r=new Mt.MathNode("mglyph",[]);r.setAttribute("alt",e.alt);var n=Le(e.height,t),a=0;if(e.totalheight.number>0&&(a=(a=Le(e.totalheight,t)-n).toFixed(2),r.setAttribute("valign","-"+a+"em")),r.setAttribute("height",n+a+"em"),e.width.number>0){var i=Le(e.width,t);r.setAttribute("width",i+"em")}return r.setAttribute("src",e.src),r}}),nt({type:"kern",names:["\\kern","\\mkern","\\hskip","\\mskip"],props:{numArgs:1,argTypes:["size"],primitive:!0,allowedInText:!0},handler:function(e,t){var r=e.parser,n=e.funcName,a=Ft(t[0],"size");if(r.settings.strict){var i="m"===n[1],o="mu"===a.value.unit;i?(o||r.settings.reportNonstrict("mathVsTextUnits","LaTeX's "+n+" supports only mu units, not "+a.value.unit+" units"),"math"!==r.mode&&r.settings.reportNonstrict("mathVsTextUnits","LaTeX's "+n+" works only in math mode")):o&&r.settings.reportNonstrict("mathVsTextUnits","LaTeX's "+n+" doesn't support mu units")}return{type:"kern",mode:r.mode,dimension:a.value}},htmlBuilder:function(e,t){return je.makeGlue(e.dimension,t)},mathmlBuilder:function(e,t){var r=Le(e.dimension,t);return new Mt.SpaceNode(r)}}),nt({type:"lap",names:["\\mathllap","\\mathrlap","\\mathclap"],props:{numArgs:1,allowedInText:!0},handler:function(e,t){var r=e.parser,n=e.funcName,a=t[0];return{type:"lap",mode:r.mode,alignment:n.slice(5),body:a}},htmlBuilder:function(e,t){var r;"clap"===e.alignment?(r=je.makeSpan([],[bt(e.body,t)]),r=je.makeSpan(["inner"],[r],t)):r=je.makeSpan(["inner"],[bt(e.body,t)]);var n=je.makeSpan(["fix"],[]),a=je.makeSpan([e.alignment],[r,n],t),i=je.makeSpan(["strut"]);return i.style.height=a.height+a.depth+"em",i.style.verticalAlign=-a.depth+"em",a.children.unshift(i),a=je.makeSpan(["thinbox"],[a],t),je.makeSpan(["mord","vbox"],[a],t)},mathmlBuilder:function(e,t){var r=new Mt.MathNode("mpadded",[Nt(e.body,t)]);if("rlap"!==e.alignment){var n="llap"===e.alignment?"-1":"-0.5";r.setAttribute("lspace",n+"width")}return r.setAttribute("width","0px"),r}}),nt({type:"styling",names:["\\(","$"],props:{numArgs:0,allowedInText:!0,allowedInMath:!1},handler:function(e,t){var r=e.funcName,n=e.parser,a=n.mode;n.switchMode("math");var i="\\("===r?"\\)":"$",o=n.parseExpression(!1,i);return n.expect(i),n.switchMode(a),{type:"styling",mode:n.mode,style:"text",body:o}}}),nt({type:"text",names:["\\)","\\]"],props:{numArgs:0,allowedInText:!0,allowedInMath:!1},handler:function(e,t){throw new n("Mismatched "+e.funcName)}});var on=function(e,t){switch(t.style.size){case b.DISPLAY.size:return e.display;case b.TEXT.size:return e.text;case b.SCRIPT.size:return e.script;case b.SCRIPTSCRIPT.size:return e.scriptscript;default:return e.text}};nt({type:"mathchoice",names:["\\mathchoice"],props:{numArgs:4,primitive:!0},handler:function(e,t){return{type:"mathchoice",mode:e.parser.mode,display:ot(t[0]),text:ot(t[1]),script:ot(t[2]),scriptscript:ot(t[3])}},htmlBuilder:function(e,t){var r=on(e,t),n=ut(r,t,!1);return je.makeFragment(n)},mathmlBuilder:function(e,t){var r=on(e,t);return qt(r,t)}});var sn=function(e,t,r,n,a,i,o){var s,l,h;if(e=je.makeSpan([],[e]),t){var m=bt(t,n.havingStyle(a.sup()),n);l={elem:m,kern:Math.max(n.fontMetrics().bigOpSpacing1,n.fontMetrics().bigOpSpacing3-m.depth)}}if(r){var c=bt(r,n.havingStyle(a.sub()),n);s={elem:c,kern:Math.max(n.fontMetrics().bigOpSpacing2,n.fontMetrics().bigOpSpacing4-c.height)}}if(l&&s){var u=n.fontMetrics().bigOpSpacing5+s.elem.height+s.elem.depth+s.kern+e.depth+o;h=je.makeVList({positionType:"bottom",positionData:u,children:[{type:"kern",size:n.fontMetrics().bigOpSpacing5},{type:"elem",elem:s.elem,marginLeft:-i+"em"},{type:"kern",size:s.kern},{type:"elem",elem:e},{type:"kern",size:l.kern},{type:"elem",elem:l.elem,marginLeft:i+"em"},{type:"kern",size:n.fontMetrics().bigOpSpacing5}]},n)}else if(s){var p=e.height-o;h=je.makeVList({positionType:"top",positionData:p,children:[{type:"kern",size:n.fontMetrics().bigOpSpacing5},{type:"elem",elem:s.elem,marginLeft:-i+"em"},{type:"kern",size:s.kern},{type:"elem",elem:e}]},n)}else{if(!l)return e;var d=e.depth+o;h=je.makeVList({positionType:"bottom",positionData:d,children:[{type:"elem",elem:e},{type:"kern",size:l.kern},{type:"elem",elem:l.elem,marginLeft:i+"em"},{type:"kern",size:n.fontMetrics().bigOpSpacing5}]},n)}return je.makeSpan(["mop","op-limits"],[h],n)},ln=["\\smallint"],hn=function(e,t){var r,n,a,i=!1;"supsub"===e.type?(r=e.sup,n=e.sub,a=Ft(e.base,"op"),i=!0):a=Ft(e,"op");var o,s=t.style,h=!1;if(s.size===b.DISPLAY.size&&a.symbol&&!l.contains(ln,a.name)&&(h=!0),a.symbol){var m=h?"Size2-Regular":"Size1-Regular",c="";if("\\oiint"!==a.name&&"\\oiiint"!==a.name||(c=a.name.substr(1),a.name="oiint"===c?"\\iint":"\\iiint"),o=je.makeSymbol(a.name,m,"math",t,["mop","op-symbol",h?"large-op":"small-op"]),c.length>0){var u=o.italic,p=je.staticSvg(c+"Size"+(h?"2":"1"),t);o=je.makeVList({positionType:"individualShift",children:[{type:"elem",elem:o,shift:0},{type:"elem",elem:p,shift:h?.08:0}]},t),a.name="\\"+c,o.classes.unshift("mop"),o.italic=u}}else if(a.body){var d=ut(a.body,t,!0);1===d.length&&d[0]instanceof O?(o=d[0]).classes[0]="mop":o=je.makeSpan(["mop"],d,t)}else{for(var f=[],g=1;g0){for(var s=a.body.map((function(e){var t=e.text;return"string"==typeof t?{type:"textord",mode:e.mode,text:t}:e})),l=ut(s,t.withFont("mathrm"),!0),h=0;h=0?s.setAttribute("height","+"+a+"em"):(s.setAttribute("height",a+"em"),s.setAttribute("depth","+"+-a+"em")),s.setAttribute("voffset",a+"em"),s}});var fn=["\\tiny","\\sixptsize","\\scriptsize","\\footnotesize","\\small","\\normalsize","\\large","\\Large","\\LARGE","\\huge","\\Huge"];nt({type:"sizing",names:fn,props:{numArgs:0,allowedInText:!0},handler:function(e,t){var r=e.breakOnTokenText,n=e.funcName,a=e.parser,i=a.parseExpression(!1,r);return{type:"sizing",mode:a.mode,size:fn.indexOf(n)+1,body:i}},htmlBuilder:function(e,t){var r=t.havingSize(e.size);return dn(e.body,r,t)},mathmlBuilder:function(e,t){var r=t.havingSize(e.size),n=Bt(e.body,r),a=new Mt.MathNode("mstyle",n);return a.setAttribute("mathsize",r.sizeMultiplier+"em"),a}}),nt({type:"smash",names:["\\smash"],props:{numArgs:1,numOptionalArgs:1,allowedInText:!0},handler:function(e,t,r){var n=e.parser,a=!1,i=!1,o=r[0]&&Ft(r[0],"ordgroup");if(o)for(var s="",l=0;lr.height+r.depth+i&&(i=(i+c-r.height-r.depth)/2);var u=l.height-r.height-i-h;r.style.paddingLeft=m+"em";var p=je.makeVList({positionType:"firstBaseline",children:[{type:"elem",elem:r,wrapperClasses:["svg-align"]},{type:"kern",size:-(r.height+u)},{type:"elem",elem:l},{type:"kern",size:h}]},t);if(e.index){var d=t.havingStyle(b.SCRIPTSCRIPT),f=bt(e.index,d,t),g=.6*(p.height-p.depth),v=je.makeVList({positionType:"shift",positionData:-g,children:[{type:"elem",elem:f}]},t),y=je.makeSpan(["root"],[v]);return je.makeSpan(["mord","sqrt"],[y,p],t)}return je.makeSpan(["mord","sqrt"],[p],t)},mathmlBuilder:function(e,t){var r=e.body,n=e.index;return n?new Mt.MathNode("mroot",[Nt(r,t),Nt(n,t)]):new Mt.MathNode("msqrt",[Nt(r,t)])}});var gn={display:b.DISPLAY,text:b.TEXT,script:b.SCRIPT,scriptscript:b.SCRIPTSCRIPT};nt({type:"styling",names:["\\displaystyle","\\textstyle","\\scriptstyle","\\scriptscriptstyle"],props:{numArgs:0,allowedInText:!0,primitive:!0},handler:function(e,t){var r=e.breakOnTokenText,n=e.funcName,a=e.parser,i=a.parseExpression(!0,r),o=n.slice(1,n.length-5);return{type:"styling",mode:a.mode,style:o,body:i}},htmlBuilder:function(e,t){var r=gn[e.style],n=t.havingStyle(r).withFont("");return dn(e.body,n,t)},mathmlBuilder:function(e,t){var r=gn[e.style],n=t.havingStyle(r),a=Bt(e.body,n),i=new Mt.MathNode("mstyle",a),o={display:["0","true"],text:["0","false"],script:["1","false"],scriptscript:["2","false"]}[e.style];return i.setAttribute("scriptlevel",o[0]),i.setAttribute("displaystyle",o[1]),i}});var vn=function(e,t){var r=e.base;return r?"op"===r.type?r.limits&&(t.style.size===b.DISPLAY.size||r.alwaysHandleSupSub)?hn:null:"operatorname"===r.type?r.alwaysHandleSupSub&&(t.style.size===b.DISPLAY.size||r.limits)?pn:null:"accent"===r.type?l.isCharacterBox(r.base)?Ut:null:"horizBrace"===r.type&&!e.sub===r.isOver?nn:null:null};at({type:"supsub",htmlBuilder:function(e,t){var r=vn(e,t);if(r)return r(e,t);var n,a,i,o=e.base,s=e.sup,h=e.sub,m=bt(o,t),c=t.fontMetrics(),u=0,p=0,d=o&&l.isCharacterBox(o);if(s){var f=t.havingStyle(t.style.sup());n=bt(s,f,t),d||(u=m.height-f.fontMetrics().supDrop*f.sizeMultiplier/t.sizeMultiplier)}if(h){var g=t.havingStyle(t.style.sub());a=bt(h,g,t),d||(p=m.depth+g.fontMetrics().subDrop*g.sizeMultiplier/t.sizeMultiplier)}i=t.style===b.DISPLAY?c.sup1:t.style.cramped?c.sup3:c.sup2;var v,y=t.sizeMultiplier,x=.5/c.ptPerEm/y+"em",w=null;if(a){var k=e.base&&"op"===e.base.type&&e.base.name&&("\\oiint"===e.base.name||"\\oiiint"===e.base.name);(m instanceof O||k)&&(w=-m.italic+"em")}if(n&&a){u=Math.max(u,i,n.depth+.25*c.xHeight),p=Math.max(p,c.sub2);var S=4*c.defaultRuleThickness;if(u-n.depth-(a.height-p)0&&(u+=M,p-=M)}var z=[{type:"elem",elem:a,shift:p,marginRight:x,marginLeft:w},{type:"elem",elem:n,shift:-u,marginRight:x}];v=je.makeVList({positionType:"individualShift",children:z},t)}else if(a){p=Math.max(p,c.sub1,a.height-.8*c.xHeight);var A=[{type:"elem",elem:a,marginLeft:w,marginRight:x}];v=je.makeVList({positionType:"shift",positionData:p,children:A},t)}else{if(!n)throw new Error("supsub must have either sup or sub.");u=Math.max(u,i,n.depth+.25*c.xHeight),v=je.makeVList({positionType:"shift",positionData:-u,children:[{type:"elem",elem:n,marginRight:x}]},t)}var T=gt(m,"right")||"mord";return je.makeSpan([T],[m,je.makeSpan(["msupsub"],[v])],t)},mathmlBuilder:function(e,t){var r,n=!1;e.base&&"horizBrace"===e.base.type&&!!e.sup===e.base.isOver&&(n=!0,r=e.base.isOver),!e.base||"op"!==e.base.type&&"operatorname"!==e.base.type||(e.base.parentIsSupSub=!0);var a,i=[Nt(e.base,t)];if(e.sub&&i.push(Nt(e.sub,t)),e.sup&&i.push(Nt(e.sup,t)),n)a=r?"mover":"munder";else if(e.sub)if(e.sup){var o=e.base;a=o&&"op"===o.type&&o.limits&&t.style===b.DISPLAY||o&&"operatorname"===o.type&&o.alwaysHandleSupSub&&(t.style===b.DISPLAY||o.limits)?"munderover":"msubsup"}else{var s=e.base;a=s&&"op"===s.type&&s.limits&&(t.style===b.DISPLAY||s.alwaysHandleSupSub)||s&&"operatorname"===s.type&&s.alwaysHandleSupSub&&(s.limits||t.style===b.DISPLAY)?"munder":"msub"}else{var l=e.base;a=l&&"op"===l.type&&l.limits&&(t.style===b.DISPLAY||l.alwaysHandleSupSub)||l&&"operatorname"===l.type&&l.alwaysHandleSupSub&&(l.limits||t.style===b.DISPLAY)?"mover":"msup"}return new Mt.MathNode(a,i)}}),at({type:"atom",htmlBuilder:function(e,t){return je.mathsym(e.text,e.mode,t,["m"+e.family])},mathmlBuilder:function(e,t){var r=new Mt.MathNode("mo",[zt(e.text,e.mode)]);if("bin"===e.family){var n=Tt(e,t);"bold-italic"===n&&r.setAttribute("mathvariant",n)}else"punct"===e.family?r.setAttribute("separator","true"):"open"!==e.family&&"close"!==e.family||r.setAttribute("stretchy","false");return r}});var bn={mi:"italic",mn:"normal",mtext:"normal"};at({type:"mathord",htmlBuilder:function(e,t){return je.makeOrd(e,t,"mathord")},mathmlBuilder:function(e,t){var r=new Mt.MathNode("mi",[zt(e.text,e.mode,t)]),n=Tt(e,t)||"italic";return n!==bn[r.type]&&r.setAttribute("mathvariant",n),r}}),at({type:"textord",htmlBuilder:function(e,t){return je.makeOrd(e,t,"textord")},mathmlBuilder:function(e,t){var r,n=zt(e.text,e.mode,t),a=Tt(e,t)||"normal";return r="text"===e.mode?new Mt.MathNode("mtext",[n]):/[0-9]/.test(e.text)?new Mt.MathNode("mn",[n]):"\\prime"===e.text?new Mt.MathNode("mo",[n]):new Mt.MathNode("mi",[n]),a!==bn[r.type]&&r.setAttribute("mathvariant",a),r}});var yn={"\\nobreak":"nobreak","\\allowbreak":"allowbreak"},xn={" ":{},"\\ ":{},"~":{className:"nobreak"},"\\space":{},"\\nobreakspace":{className:"nobreak"}};at({type:"spacing",htmlBuilder:function(e,t){if(xn.hasOwnProperty(e.text)){var r=xn[e.text].className||"";if("text"===e.mode){var a=je.makeOrd(e,t,"textord");return a.classes.push(r),a}return je.makeSpan(["mspace",r],[je.mathsym(e.text,e.mode,t)],t)}if(yn.hasOwnProperty(e.text))return je.makeSpan(["mspace",yn[e.text]],[],t);throw new n('Unknown type of space "'+e.text+'"')},mathmlBuilder:function(e,t){if(!xn.hasOwnProperty(e.text)){if(yn.hasOwnProperty(e.text))return new Mt.MathNode("mspace");throw new n('Unknown type of space "'+e.text+'"')}return new Mt.MathNode("mtext",[new Mt.TextNode("\xa0")])}});var wn=function(){var e=new Mt.MathNode("mtd",[]);return e.setAttribute("width","50%"),e};at({type:"tag",mathmlBuilder:function(e,t){var r=new Mt.MathNode("mtable",[new Mt.MathNode("mtr",[wn(),new Mt.MathNode("mtd",[qt(e.body,t)]),wn(),new Mt.MathNode("mtd",[qt(e.tag,t)])])]);return r.setAttribute("width","100%"),r}});var kn={"\\text":void 0,"\\textrm":"textrm","\\textsf":"textsf","\\texttt":"texttt","\\textnormal":"textrm"},Sn={"\\textbf":"textbf","\\textmd":"textmd"},Mn={"\\textit":"textit","\\textup":"textup"},zn=function(e,t){var r=e.font;return r?kn[r]?t.withTextFontFamily(kn[r]):Sn[r]?t.withTextFontWeight(Sn[r]):t.withTextFontShape(Mn[r]):t};nt({type:"text",names:["\\text","\\textrm","\\textsf","\\texttt","\\textnormal","\\textbf","\\textmd","\\textit","\\textup"],props:{numArgs:1,argTypes:["text"],allowedInArgument:!0,allowedInText:!0},handler:function(e,t){var r=e.parser,n=e.funcName,a=t[0];return{type:"text",mode:r.mode,body:ot(a),font:n}},htmlBuilder:function(e,t){var r=zn(e,t),n=ut(e.body,r,!0);return je.makeSpan(["mord","text"],n,r)},mathmlBuilder:function(e,t){var r=zn(e,t);return qt(e.body,r)}}),nt({type:"underline",names:["\\underline"],props:{numArgs:1,allowedInText:!0},handler:function(e,t){return{type:"underline",mode:e.parser.mode,body:t[0]}},htmlBuilder:function(e,t){var r=bt(e.body,t),n=je.makeLineSpan("underline-line",t),a=t.fontMetrics().defaultRuleThickness,i=je.makeVList({positionType:"top",positionData:r.height,children:[{type:"kern",size:a},{type:"elem",elem:n},{type:"kern",size:3*a},{type:"elem",elem:r}]},t);return je.makeSpan(["mord","underline"],[i],t)},mathmlBuilder:function(e,t){var r=new Mt.MathNode("mo",[new Mt.TextNode("\u203e")]);r.setAttribute("stretchy","true");var n=new Mt.MathNode("munder",[Nt(e.body,t),r]);return n.setAttribute("accentunder","true"),n}}),nt({type:"vcenter",names:["\\vcenter"],props:{numArgs:1,argTypes:["original"],allowedInText:!1},handler:function(e,t){return{type:"vcenter",mode:e.parser.mode,body:t[0]}},htmlBuilder:function(e,t){var r=bt(e.body,t),n=t.fontMetrics().axisHeight,a=.5*(r.height-n-(r.depth+n));return je.makeVList({positionType:"shift",positionData:a,children:[{type:"elem",elem:r}]},t)},mathmlBuilder:function(e,t){return new Mt.MathNode("mpadded",[Nt(e.body,t)],["vcenter"])}}),nt({type:"verb",names:["\\verb"],props:{numArgs:0,allowedInText:!0},handler:function(e,t,r){throw new n("\\verb ended by end of line instead of matching delimiter")},htmlBuilder:function(e,t){for(var r=An(e),n=[],a=t.havingStyle(t.style.text()),i=0;i0&&(this.undefStack[this.undefStack.length-1][e]=t)}else{var a=this.undefStack[this.undefStack.length-1];a&&!a.hasOwnProperty(e)&&(a[e]=this.current[e])}this.current[e]=t},e}(),Rn={},En=Rn;function Hn(e,t){Rn[e]=t}Hn("\\noexpand",(function(e){var t=e.popToken();return e.isExpandable(t.text)&&(t.noexpand=!0,t.treatAsRelax=!0),{tokens:[t],numArgs:0}})),Hn("\\expandafter",(function(e){var t=e.popToken();return e.expandOnce(!0),{tokens:[t],numArgs:0}})),Hn("\\@firstoftwo",(function(e){return{tokens:e.consumeArgs(2)[0],numArgs:0}})),Hn("\\@secondoftwo",(function(e){return{tokens:e.consumeArgs(2)[1],numArgs:0}})),Hn("\\@ifnextchar",(function(e){var t=e.consumeArgs(3);e.consumeSpaces();var r=e.future();return 1===t[0].length&&t[0][0].text===r.text?{tokens:t[1],numArgs:0}:{tokens:t[2],numArgs:0}})),Hn("\\@ifstar","\\@ifnextchar *{\\@firstoftwo{#1}}"),Hn("\\TextOrMath",(function(e){var t=e.consumeArgs(2);return"text"===e.mode?{tokens:t[0],numArgs:0}:{tokens:t[1],numArgs:0}}));var Ln={0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8,9:9,a:10,A:10,b:11,B:11,c:12,C:12,d:13,D:13,e:14,E:14,f:15,F:15};Hn("\\char",(function(e){var t,r=e.popToken(),a="";if("'"===r.text)t=8,r=e.popToken();else if('"'===r.text)t=16,r=e.popToken();else if("`"===r.text)if("\\"===(r=e.popToken()).text[0])a=r.text.charCodeAt(1);else{if("EOF"===r.text)throw new n("\\char` missing argument");a=r.text.charCodeAt(0)}else t=10;if(t){if(null==(a=Ln[r.text])||a>=t)throw new n("Invalid base-"+t+" digit "+r.text);for(var i;null!=(i=Ln[e.future().text])&&i":"\\dotsb","-":"\\dotsb","*":"\\dotsb",":":"\\dotsb","\\DOTSB":"\\dotsb","\\coprod":"\\dotsb","\\bigvee":"\\dotsb","\\bigwedge":"\\dotsb","\\biguplus":"\\dotsb","\\bigcap":"\\dotsb","\\bigcup":"\\dotsb","\\prod":"\\dotsb","\\sum":"\\dotsb","\\bigotimes":"\\dotsb","\\bigoplus":"\\dotsb","\\bigodot":"\\dotsb","\\bigsqcup":"\\dotsb","\\And":"\\dotsb","\\longrightarrow":"\\dotsb","\\Longrightarrow":"\\dotsb","\\longleftarrow":"\\dotsb","\\Longleftarrow":"\\dotsb","\\longleftrightarrow":"\\dotsb","\\Longleftrightarrow":"\\dotsb","\\mapsto":"\\dotsb","\\longmapsto":"\\dotsb","\\hookrightarrow":"\\dotsb","\\doteq":"\\dotsb","\\mathbin":"\\dotsb","\\mathrel":"\\dotsb","\\relbar":"\\dotsb","\\Relbar":"\\dotsb","\\xrightarrow":"\\dotsb","\\xleftarrow":"\\dotsb","\\DOTSI":"\\dotsi","\\int":"\\dotsi","\\oint":"\\dotsi","\\iint":"\\dotsi","\\iiint":"\\dotsi","\\iiiint":"\\dotsi","\\idotsint":"\\dotsi","\\DOTSX":"\\dotsx"};Hn("\\dots",(function(e){var t="\\dotso",r=e.expandAfterFuture().text;return r in Pn?t=Pn[r]:("\\not"===r.substr(0,4)||r in X.math&&l.contains(["bin","rel"],X.math[r].group))&&(t="\\dotsb"),t}));var Fn={")":!0,"]":!0,"\\rbrack":!0,"\\}":!0,"\\rbrace":!0,"\\rangle":!0,"\\rceil":!0,"\\rfloor":!0,"\\rgroup":!0,"\\rmoustache":!0,"\\right":!0,"\\bigr":!0,"\\biggr":!0,"\\Bigr":!0,"\\Biggr":!0,$:!0,";":!0,".":!0,",":!0};Hn("\\dotso",(function(e){return e.future().text in Fn?"\\ldots\\,":"\\ldots"})),Hn("\\dotsc",(function(e){var t=e.future().text;return t in Fn&&","!==t?"\\ldots\\,":"\\ldots"})),Hn("\\cdots",(function(e){return e.future().text in Fn?"\\@cdots\\,":"\\@cdots"})),Hn("\\dotsb","\\cdots"),Hn("\\dotsm","\\cdots"),Hn("\\dotsi","\\!\\cdots"),Hn("\\dotsx","\\ldots\\,"),Hn("\\DOTSI","\\relax"),Hn("\\DOTSB","\\relax"),Hn("\\DOTSX","\\relax"),Hn("\\tmspace","\\TextOrMath{\\kern#1#3}{\\mskip#1#2}\\relax"),Hn("\\,","\\tmspace+{3mu}{.1667em}"),Hn("\\thinspace","\\,"),Hn("\\>","\\mskip{4mu}"),Hn("\\:","\\tmspace+{4mu}{.2222em}"),Hn("\\medspace","\\:"),Hn("\\;","\\tmspace+{5mu}{.2777em}"),Hn("\\thickspace","\\;"),Hn("\\!","\\tmspace-{3mu}{.1667em}"),Hn("\\negthinspace","\\!"),Hn("\\negmedspace","\\tmspace-{4mu}{.2222em}"),Hn("\\negthickspace","\\tmspace-{5mu}{.277em}"),Hn("\\enspace","\\kern.5em "),Hn("\\enskip","\\hskip.5em\\relax"),Hn("\\quad","\\hskip1em\\relax"),Hn("\\qquad","\\hskip2em\\relax"),Hn("\\tag","\\@ifstar\\tag@literal\\tag@paren"),Hn("\\tag@paren","\\tag@literal{({#1})}"),Hn("\\tag@literal",(function(e){if(e.macros.get("\\df@tag"))throw new n("Multiple \\tag");return"\\gdef\\df@tag{\\text{#1}}"})),Hn("\\bmod","\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}\\mathbin{\\rm mod}\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}"),Hn("\\pod","\\allowbreak\\mathchoice{\\mkern18mu}{\\mkern8mu}{\\mkern8mu}{\\mkern8mu}(#1)"),Hn("\\pmod","\\pod{{\\rm mod}\\mkern6mu#1}"),Hn("\\mod","\\allowbreak\\mathchoice{\\mkern18mu}{\\mkern12mu}{\\mkern12mu}{\\mkern12mu}{\\rm mod}\\,\\,#1"),Hn("\\pmb","\\html@mathml{\\@binrel{#1}{\\mathrlap{#1}\\kern0.5px#1}}{\\mathbf{#1}}"),Hn("\\newline","\\\\\\relax"),Hn("\\TeX","\\textrm{\\html@mathml{T\\kern-.1667em\\raisebox{-.5ex}{E}\\kern-.125emX}{TeX}}");var Vn=D["Main-Regular"]["T".charCodeAt(0)][1]-.7*D["Main-Regular"]["A".charCodeAt(0)][1]+"em";Hn("\\LaTeX","\\textrm{\\html@mathml{L\\kern-.36em\\raisebox{"+Vn+"}{\\scriptstyle A}\\kern-.15em\\TeX}{LaTeX}}"),Hn("\\KaTeX","\\textrm{\\html@mathml{K\\kern-.17em\\raisebox{"+Vn+"}{\\scriptstyle A}\\kern-.15em\\TeX}{KaTeX}}"),Hn("\\hspace","\\@ifstar\\@hspacer\\@hspace"),Hn("\\@hspace","\\hskip #1\\relax"),Hn("\\@hspacer","\\rule{0pt}{0pt}\\hskip #1\\relax"),Hn("\\ordinarycolon",":"),Hn("\\vcentcolon","\\mathrel{\\mathop\\ordinarycolon}"),Hn("\\dblcolon",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-.9mu}\\vcentcolon}}{\\mathop{\\char"2237}}'),Hn("\\coloneqq",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}=}}{\\mathop{\\char"2254}}'),Hn("\\Coloneqq",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}=}}{\\mathop{\\char"2237\\char"3d}}'),Hn("\\coloneq",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}{\\mathop{\\char"3a\\char"2212}}'),Hn("\\Coloneq",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}{\\mathop{\\char"2237\\char"2212}}'),Hn("\\eqqcolon",'\\html@mathml{\\mathrel{=\\mathrel{\\mkern-1.2mu}\\vcentcolon}}{\\mathop{\\char"2255}}'),Hn("\\Eqqcolon",'\\html@mathml{\\mathrel{=\\mathrel{\\mkern-1.2mu}\\dblcolon}}{\\mathop{\\char"3d\\char"2237}}'),Hn("\\eqcolon",'\\html@mathml{\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\vcentcolon}}{\\mathop{\\char"2239}}'),Hn("\\Eqcolon",'\\html@mathml{\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\dblcolon}}{\\mathop{\\char"2212\\char"2237}}'),Hn("\\colonapprox",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\approx}}{\\mathop{\\char"3a\\char"2248}}'),Hn("\\Colonapprox",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\approx}}{\\mathop{\\char"2237\\char"2248}}'),Hn("\\colonsim",'\\html@mathml{\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\sim}}{\\mathop{\\char"3a\\char"223c}}'),Hn("\\Colonsim",'\\html@mathml{\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\sim}}{\\mathop{\\char"2237\\char"223c}}'),Hn("\u2237","\\dblcolon"),Hn("\u2239","\\eqcolon"),Hn("\u2254","\\coloneqq"),Hn("\u2255","\\eqqcolon"),Hn("\u2a74","\\Coloneqq"),Hn("\\ratio","\\vcentcolon"),Hn("\\coloncolon","\\dblcolon"),Hn("\\colonequals","\\coloneqq"),Hn("\\coloncolonequals","\\Coloneqq"),Hn("\\equalscolon","\\eqqcolon"),Hn("\\equalscoloncolon","\\Eqqcolon"),Hn("\\colonminus","\\coloneq"),Hn("\\coloncolonminus","\\Coloneq"),Hn("\\minuscolon","\\eqcolon"),Hn("\\minuscoloncolon","\\Eqcolon"),Hn("\\coloncolonapprox","\\Colonapprox"),Hn("\\coloncolonsim","\\Colonsim"),Hn("\\simcolon","\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\vcentcolon}"),Hn("\\simcoloncolon","\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\dblcolon}"),Hn("\\approxcolon","\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\vcentcolon}"),Hn("\\approxcoloncolon","\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\dblcolon}"),Hn("\\notni","\\html@mathml{\\not\\ni}{\\mathrel{\\char`\u220c}}"),Hn("\\limsup","\\DOTSB\\operatorname*{lim\\,sup}"),Hn("\\liminf","\\DOTSB\\operatorname*{lim\\,inf}"),Hn("\\injlim","\\DOTSB\\operatorname*{inj\\,lim}"),Hn("\\projlim","\\DOTSB\\operatorname*{proj\\,lim}"),Hn("\\varlimsup","\\DOTSB\\operatorname*{\\overline{lim}}"),Hn("\\varliminf","\\DOTSB\\operatorname*{\\underline{lim}}"),Hn("\\varinjlim","\\DOTSB\\operatorname*{\\underrightarrow{lim}}"),Hn("\\varprojlim","\\DOTSB\\operatorname*{\\underleftarrow{lim}}"),Hn("\\gvertneqq","\\html@mathml{\\@gvertneqq}{\u2269}"),Hn("\\lvertneqq","\\html@mathml{\\@lvertneqq}{\u2268}"),Hn("\\ngeqq","\\html@mathml{\\@ngeqq}{\u2271}"),Hn("\\ngeqslant","\\html@mathml{\\@ngeqslant}{\u2271}"),Hn("\\nleqq","\\html@mathml{\\@nleqq}{\u2270}"),Hn("\\nleqslant","\\html@mathml{\\@nleqslant}{\u2270}"),Hn("\\nshortmid","\\html@mathml{\\@nshortmid}{\u2224}"),Hn("\\nshortparallel","\\html@mathml{\\@nshortparallel}{\u2226}"),Hn("\\nsubseteqq","\\html@mathml{\\@nsubseteqq}{\u2288}"),Hn("\\nsupseteqq","\\html@mathml{\\@nsupseteqq}{\u2289}"),Hn("\\varsubsetneq","\\html@mathml{\\@varsubsetneq}{\u228a}"),Hn("\\varsubsetneqq","\\html@mathml{\\@varsubsetneqq}{\u2acb}"),Hn("\\varsupsetneq","\\html@mathml{\\@varsupsetneq}{\u228b}"),Hn("\\varsupsetneqq","\\html@mathml{\\@varsupsetneqq}{\u2acc}"),Hn("\\imath","\\html@mathml{\\@imath}{\u0131}"),Hn("\\jmath","\\html@mathml{\\@jmath}{\u0237}"),Hn("\\llbracket","\\html@mathml{\\mathopen{[\\mkern-3.2mu[}}{\\mathopen{\\char`\u27e6}}"),Hn("\\rrbracket","\\html@mathml{\\mathclose{]\\mkern-3.2mu]}}{\\mathclose{\\char`\u27e7}}"),Hn("\u27e6","\\llbracket"),Hn("\u27e7","\\rrbracket"),Hn("\\lBrace","\\html@mathml{\\mathopen{\\{\\mkern-3.2mu[}}{\\mathopen{\\char`\u2983}}"),Hn("\\rBrace","\\html@mathml{\\mathclose{]\\mkern-3.2mu\\}}}{\\mathclose{\\char`\u2984}}"),Hn("\u2983","\\lBrace"),Hn("\u2984","\\rBrace"),Hn("\\minuso","\\mathbin{\\html@mathml{{\\mathrlap{\\mathchoice{\\kern{0.145em}}{\\kern{0.145em}}{\\kern{0.1015em}}{\\kern{0.0725em}}\\circ}{-}}}{\\char`\u29b5}}"),Hn("\u29b5","\\minuso"),Hn("\\darr","\\downarrow"),Hn("\\dArr","\\Downarrow"),Hn("\\Darr","\\Downarrow"),Hn("\\lang","\\langle"),Hn("\\rang","\\rangle"),Hn("\\uarr","\\uparrow"),Hn("\\uArr","\\Uparrow"),Hn("\\Uarr","\\Uparrow"),Hn("\\N","\\mathbb{N}"),Hn("\\R","\\mathbb{R}"),Hn("\\Z","\\mathbb{Z}"),Hn("\\alef","\\aleph"),Hn("\\alefsym","\\aleph"),Hn("\\Alpha","\\mathrm{A}"),Hn("\\Beta","\\mathrm{B}"),Hn("\\bull","\\bullet"),Hn("\\Chi","\\mathrm{X}"),Hn("\\clubs","\\clubsuit"),Hn("\\cnums","\\mathbb{C}"),Hn("\\Complex","\\mathbb{C}"),Hn("\\Dagger","\\ddagger"),Hn("\\diamonds","\\diamondsuit"),Hn("\\empty","\\emptyset"),Hn("\\Epsilon","\\mathrm{E}"),Hn("\\Eta","\\mathrm{H}"),Hn("\\exist","\\exists"),Hn("\\harr","\\leftrightarrow"),Hn("\\hArr","\\Leftrightarrow"),Hn("\\Harr","\\Leftrightarrow"),Hn("\\hearts","\\heartsuit"),Hn("\\image","\\Im"),Hn("\\infin","\\infty"),Hn("\\Iota","\\mathrm{I}"),Hn("\\isin","\\in"),Hn("\\Kappa","\\mathrm{K}"),Hn("\\larr","\\leftarrow"),Hn("\\lArr","\\Leftarrow"),Hn("\\Larr","\\Leftarrow"),Hn("\\lrarr","\\leftrightarrow"),Hn("\\lrArr","\\Leftrightarrow"),Hn("\\Lrarr","\\Leftrightarrow"),Hn("\\Mu","\\mathrm{M}"),Hn("\\natnums","\\mathbb{N}"),Hn("\\Nu","\\mathrm{N}"),Hn("\\Omicron","\\mathrm{O}"),Hn("\\plusmn","\\pm"),Hn("\\rarr","\\rightarrow"),Hn("\\rArr","\\Rightarrow"),Hn("\\Rarr","\\Rightarrow"),Hn("\\real","\\Re"),Hn("\\reals","\\mathbb{R}"),Hn("\\Reals","\\mathbb{R}"),Hn("\\Rho","\\mathrm{P}"),Hn("\\sdot","\\cdot"),Hn("\\sect","\\S"),Hn("\\spades","\\spadesuit"),Hn("\\sub","\\subset"),Hn("\\sube","\\subseteq"),Hn("\\supe","\\supseteq"),Hn("\\Tau","\\mathrm{T}"),Hn("\\thetasym","\\vartheta"),Hn("\\weierp","\\wp"),Hn("\\Zeta","\\mathrm{Z}"),Hn("\\argmin","\\DOTSB\\operatorname*{arg\\,min}"),Hn("\\argmax","\\DOTSB\\operatorname*{arg\\,max}"),Hn("\\plim","\\DOTSB\\mathop{\\operatorname{plim}}\\limits"),Hn("\\bra","\\mathinner{\\langle{#1}|}"),Hn("\\ket","\\mathinner{|{#1}\\rangle}"),Hn("\\braket","\\mathinner{\\langle{#1}\\rangle}"),Hn("\\Bra","\\left\\langle#1\\right|"),Hn("\\Ket","\\left|#1\\right\\rangle"),Hn("\\angln","{\\angl n}"),Hn("\\blue","\\textcolor{##6495ed}{#1}"),Hn("\\orange","\\textcolor{##ffa500}{#1}"),Hn("\\pink","\\textcolor{##ff00af}{#1}"),Hn("\\red","\\textcolor{##df0030}{#1}"),Hn("\\green","\\textcolor{##28ae7b}{#1}"),Hn("\\gray","\\textcolor{gray}{#1}"),Hn("\\purple","\\textcolor{##9d38bd}{#1}"),Hn("\\blueA","\\textcolor{##ccfaff}{#1}"),Hn("\\blueB","\\textcolor{##80f6ff}{#1}"),Hn("\\blueC","\\textcolor{##63d9ea}{#1}"),Hn("\\blueD","\\textcolor{##11accd}{#1}"),Hn("\\blueE","\\textcolor{##0c7f99}{#1}"),Hn("\\tealA","\\textcolor{##94fff5}{#1}"),Hn("\\tealB","\\textcolor{##26edd5}{#1}"),Hn("\\tealC","\\textcolor{##01d1c1}{#1}"),Hn("\\tealD","\\textcolor{##01a995}{#1}"),Hn("\\tealE","\\textcolor{##208170}{#1}"),Hn("\\greenA","\\textcolor{##b6ffb0}{#1}"),Hn("\\greenB","\\textcolor{##8af281}{#1}"),Hn("\\greenC","\\textcolor{##74cf70}{#1}"),Hn("\\greenD","\\textcolor{##1fab54}{#1}"),Hn("\\greenE","\\textcolor{##0d923f}{#1}"),Hn("\\goldA","\\textcolor{##ffd0a9}{#1}"),Hn("\\goldB","\\textcolor{##ffbb71}{#1}"),Hn("\\goldC","\\textcolor{##ff9c39}{#1}"),Hn("\\goldD","\\textcolor{##e07d10}{#1}"),Hn("\\goldE","\\textcolor{##a75a05}{#1}"),Hn("\\redA","\\textcolor{##fca9a9}{#1}"),Hn("\\redB","\\textcolor{##ff8482}{#1}"),Hn("\\redC","\\textcolor{##f9685d}{#1}"),Hn("\\redD","\\textcolor{##e84d39}{#1}"),Hn("\\redE","\\textcolor{##bc2612}{#1}"),Hn("\\maroonA","\\textcolor{##ffbde0}{#1}"),Hn("\\maroonB","\\textcolor{##ff92c6}{#1}"),Hn("\\maroonC","\\textcolor{##ed5fa6}{#1}"),Hn("\\maroonD","\\textcolor{##ca337c}{#1}"),Hn("\\maroonE","\\textcolor{##9e034e}{#1}"),Hn("\\purpleA","\\textcolor{##ddd7ff}{#1}"),Hn("\\purpleB","\\textcolor{##c6b9fc}{#1}"),Hn("\\purpleC","\\textcolor{##aa87ff}{#1}"),Hn("\\purpleD","\\textcolor{##7854ab}{#1}"),Hn("\\purpleE","\\textcolor{##543b78}{#1}"),Hn("\\mintA","\\textcolor{##f5f9e8}{#1}"),Hn("\\mintB","\\textcolor{##edf2df}{#1}"),Hn("\\mintC","\\textcolor{##e0e5cc}{#1}"),Hn("\\grayA","\\textcolor{##f6f7f7}{#1}"),Hn("\\grayB","\\textcolor{##f0f1f2}{#1}"),Hn("\\grayC","\\textcolor{##e3e5e6}{#1}"),Hn("\\grayD","\\textcolor{##d6d8da}{#1}"),Hn("\\grayE","\\textcolor{##babec2}{#1}"),Hn("\\grayF","\\textcolor{##888d93}{#1}"),Hn("\\grayG","\\textcolor{##626569}{#1}"),Hn("\\grayH","\\textcolor{##3b3e40}{#1}"),Hn("\\grayI","\\textcolor{##21242c}{#1}"),Hn("\\kaBlue","\\textcolor{##314453}{#1}"),Hn("\\kaGreen","\\textcolor{##71B307}{#1}");var Gn={"\\relax":!0,"^":!0,_:!0,"\\limits":!0,"\\nolimits":!0},Un=function(){function e(e,t,r){this.settings=void 0,this.expansionCount=void 0,this.lexer=void 0,this.macros=void 0,this.stack=void 0,this.mode=void 0,this.settings=t,this.expansionCount=0,this.feed(e),this.macros=new On(En,t.macros),this.mode=r,this.stack=[]}var t=e.prototype;return t.feed=function(e){this.lexer=new In(e,this.settings)},t.switchMode=function(e){this.mode=e},t.beginGroup=function(){this.macros.beginGroup()},t.endGroup=function(){this.macros.endGroup()},t.future=function(){return 0===this.stack.length&&this.pushToken(this.lexer.lex()),this.stack[this.stack.length-1]},t.popToken=function(){return this.future(),this.stack.pop()},t.pushToken=function(e){this.stack.push(e)},t.pushTokens=function(e){var t;(t=this.stack).push.apply(t,e)},t.scanArgument=function(e){var t,r,n;if(e){if(this.consumeSpaces(),"["!==this.future().text)return null;t=this.popToken();var a=this.consumeArg(["]"]);n=a.tokens,r=a.end}else{var i=this.consumeArg();n=i.tokens,t=i.start,r=i.end}return this.pushToken(new qn("EOF",r.loc)),this.pushTokens(n),t.range(r,"")},t.consumeSpaces=function(){for(;;){if(" "!==this.future().text)break;this.stack.pop()}},t.consumeArg=function(e){var t=[],r=e&&e.length>0;r||this.consumeSpaces();var a,i=this.future(),o=0,s=0;do{if(a=this.popToken(),t.push(a),"{"===a.text)++o;else if("}"===a.text){if(-1===--o)throw new n("Extra }",a)}else if("EOF"===a.text)throw new n("Unexpected end of input in a macro argument, expected '"+(e&&r?e[s]:"}")+"'",a);if(e&&r)if((0===o||1===o&&"{"===e[s])&&a.text===e[s]){if(++s===e.length){t.splice(-s,s);break}}else s=0}while(0!==o||r);return"{"===i.text&&"}"===t[t.length-1].text&&(t.pop(),t.shift()),t.reverse(),{tokens:t,start:i,end:a}},t.consumeArgs=function(e,t){if(t){if(t.length!==e+1)throw new n("The length of delimiters doesn't match the number of args!");for(var r=t[0],a=0;athis.settings.maxExpand)throw new n("Too many expansions: infinite loop or need to increase maxExpand setting");var i=a.tokens,o=this.consumeArgs(a.numArgs,a.delimiters);if(a.numArgs)for(var s=(i=i.slice()).length-1;s>=0;--s){var l=i[s];if("#"===l.text){if(0===s)throw new n("Incomplete placeholder at end of macro body",l);if("#"===(l=i[--s]).text)i.splice(s+1,1);else{if(!/^[1-9]$/.test(l.text))throw new n("Not a valid argument number",l);var h;(h=i).splice.apply(h,[s,2].concat(o[+l.text-1]))}}}return this.pushTokens(i),i},t.expandAfterFuture=function(){return this.expandOnce(),this.future()},t.expandNextToken=function(){for(;;){var e=this.expandOnce();if(e instanceof qn){if("\\relax"!==e.text&&!e.treatAsRelax)return this.stack.pop();this.stack.pop()}}throw new Error},t.expandMacro=function(e){return this.macros.has(e)?this.expandTokens([new qn(e)]):void 0},t.expandTokens=function(e){var t=[],r=this.stack.length;for(this.pushTokens(e);this.stack.length>r;){var n=this.expandOnce(!0);n instanceof qn&&(n.treatAsRelax&&(n.noexpand=!1,n.treatAsRelax=!1),t.push(this.stack.pop()))}return t},t.expandMacroAsText=function(e){var t=this.expandMacro(e);return t?t.map((function(e){return e.text})).join(""):t},t._getExpansion=function(e){var t=this.macros.get(e);if(null==t)return t;var r="function"==typeof t?t(this):t;if("string"==typeof r){var n=0;if(-1!==r.indexOf("#"))for(var a=r.replace(/##/g,"");-1!==a.indexOf("#"+(n+1));)++n;for(var i=new In(r,this.settings),o=[],s=i.lex();"EOF"!==s.text;)o.push(s),s=i.lex();return o.reverse(),{tokens:o,numArgs:n}}return r},t.isDefined=function(e){return this.macros.has(e)||Tn.hasOwnProperty(e)||X.math.hasOwnProperty(e)||X.text.hasOwnProperty(e)||Gn.hasOwnProperty(e)},t.isExpandable=function(e){var t=this.macros.get(e);return null!=t?"string"==typeof t||"function"==typeof t||!t.unexpandable:Tn.hasOwnProperty(e)&&!Tn[e].primitive},e}(),Yn={"\u0301":{text:"\\'",math:"\\acute"},"\u0300":{text:"\\`",math:"\\grave"},"\u0308":{text:'\\"',math:"\\ddot"},"\u0303":{text:"\\~",math:"\\tilde"},"\u0304":{text:"\\=",math:"\\bar"},"\u0306":{text:"\\u",math:"\\breve"},"\u030c":{text:"\\v",math:"\\check"},"\u0302":{text:"\\^",math:"\\hat"},"\u0307":{text:"\\.",math:"\\dot"},"\u030a":{text:"\\r",math:"\\mathring"},"\u030b":{text:"\\H"}},Wn={"\xe1":"a\u0301","\xe0":"a\u0300","\xe4":"a\u0308","\u01df":"a\u0308\u0304","\xe3":"a\u0303","\u0101":"a\u0304","\u0103":"a\u0306","\u1eaf":"a\u0306\u0301","\u1eb1":"a\u0306\u0300","\u1eb5":"a\u0306\u0303","\u01ce":"a\u030c","\xe2":"a\u0302","\u1ea5":"a\u0302\u0301","\u1ea7":"a\u0302\u0300","\u1eab":"a\u0302\u0303","\u0227":"a\u0307","\u01e1":"a\u0307\u0304","\xe5":"a\u030a","\u01fb":"a\u030a\u0301","\u1e03":"b\u0307","\u0107":"c\u0301","\u010d":"c\u030c","\u0109":"c\u0302","\u010b":"c\u0307","\u010f":"d\u030c","\u1e0b":"d\u0307","\xe9":"e\u0301","\xe8":"e\u0300","\xeb":"e\u0308","\u1ebd":"e\u0303","\u0113":"e\u0304","\u1e17":"e\u0304\u0301","\u1e15":"e\u0304\u0300","\u0115":"e\u0306","\u011b":"e\u030c","\xea":"e\u0302","\u1ebf":"e\u0302\u0301","\u1ec1":"e\u0302\u0300","\u1ec5":"e\u0302\u0303","\u0117":"e\u0307","\u1e1f":"f\u0307","\u01f5":"g\u0301","\u1e21":"g\u0304","\u011f":"g\u0306","\u01e7":"g\u030c","\u011d":"g\u0302","\u0121":"g\u0307","\u1e27":"h\u0308","\u021f":"h\u030c","\u0125":"h\u0302","\u1e23":"h\u0307","\xed":"i\u0301","\xec":"i\u0300","\xef":"i\u0308","\u1e2f":"i\u0308\u0301","\u0129":"i\u0303","\u012b":"i\u0304","\u012d":"i\u0306","\u01d0":"i\u030c","\xee":"i\u0302","\u01f0":"j\u030c","\u0135":"j\u0302","\u1e31":"k\u0301","\u01e9":"k\u030c","\u013a":"l\u0301","\u013e":"l\u030c","\u1e3f":"m\u0301","\u1e41":"m\u0307","\u0144":"n\u0301","\u01f9":"n\u0300","\xf1":"n\u0303","\u0148":"n\u030c","\u1e45":"n\u0307","\xf3":"o\u0301","\xf2":"o\u0300","\xf6":"o\u0308","\u022b":"o\u0308\u0304","\xf5":"o\u0303","\u1e4d":"o\u0303\u0301","\u1e4f":"o\u0303\u0308","\u022d":"o\u0303\u0304","\u014d":"o\u0304","\u1e53":"o\u0304\u0301","\u1e51":"o\u0304\u0300","\u014f":"o\u0306","\u01d2":"o\u030c","\xf4":"o\u0302","\u1ed1":"o\u0302\u0301","\u1ed3":"o\u0302\u0300","\u1ed7":"o\u0302\u0303","\u022f":"o\u0307","\u0231":"o\u0307\u0304","\u0151":"o\u030b","\u1e55":"p\u0301","\u1e57":"p\u0307","\u0155":"r\u0301","\u0159":"r\u030c","\u1e59":"r\u0307","\u015b":"s\u0301","\u1e65":"s\u0301\u0307","\u0161":"s\u030c","\u1e67":"s\u030c\u0307","\u015d":"s\u0302","\u1e61":"s\u0307","\u1e97":"t\u0308","\u0165":"t\u030c","\u1e6b":"t\u0307","\xfa":"u\u0301","\xf9":"u\u0300","\xfc":"u\u0308","\u01d8":"u\u0308\u0301","\u01dc":"u\u0308\u0300","\u01d6":"u\u0308\u0304","\u01da":"u\u0308\u030c","\u0169":"u\u0303","\u1e79":"u\u0303\u0301","\u016b":"u\u0304","\u1e7b":"u\u0304\u0308","\u016d":"u\u0306","\u01d4":"u\u030c","\xfb":"u\u0302","\u016f":"u\u030a","\u0171":"u\u030b","\u1e7d":"v\u0303","\u1e83":"w\u0301","\u1e81":"w\u0300","\u1e85":"w\u0308","\u0175":"w\u0302","\u1e87":"w\u0307","\u1e98":"w\u030a","\u1e8d":"x\u0308","\u1e8b":"x\u0307","\xfd":"y\u0301","\u1ef3":"y\u0300","\xff":"y\u0308","\u1ef9":"y\u0303","\u0233":"y\u0304","\u0177":"y\u0302","\u1e8f":"y\u0307","\u1e99":"y\u030a","\u017a":"z\u0301","\u017e":"z\u030c","\u1e91":"z\u0302","\u017c":"z\u0307","\xc1":"A\u0301","\xc0":"A\u0300","\xc4":"A\u0308","\u01de":"A\u0308\u0304","\xc3":"A\u0303","\u0100":"A\u0304","\u0102":"A\u0306","\u1eae":"A\u0306\u0301","\u1eb0":"A\u0306\u0300","\u1eb4":"A\u0306\u0303","\u01cd":"A\u030c","\xc2":"A\u0302","\u1ea4":"A\u0302\u0301","\u1ea6":"A\u0302\u0300","\u1eaa":"A\u0302\u0303","\u0226":"A\u0307","\u01e0":"A\u0307\u0304","\xc5":"A\u030a","\u01fa":"A\u030a\u0301","\u1e02":"B\u0307","\u0106":"C\u0301","\u010c":"C\u030c","\u0108":"C\u0302","\u010a":"C\u0307","\u010e":"D\u030c","\u1e0a":"D\u0307","\xc9":"E\u0301","\xc8":"E\u0300","\xcb":"E\u0308","\u1ebc":"E\u0303","\u0112":"E\u0304","\u1e16":"E\u0304\u0301","\u1e14":"E\u0304\u0300","\u0114":"E\u0306","\u011a":"E\u030c","\xca":"E\u0302","\u1ebe":"E\u0302\u0301","\u1ec0":"E\u0302\u0300","\u1ec4":"E\u0302\u0303","\u0116":"E\u0307","\u1e1e":"F\u0307","\u01f4":"G\u0301","\u1e20":"G\u0304","\u011e":"G\u0306","\u01e6":"G\u030c","\u011c":"G\u0302","\u0120":"G\u0307","\u1e26":"H\u0308","\u021e":"H\u030c","\u0124":"H\u0302","\u1e22":"H\u0307","\xcd":"I\u0301","\xcc":"I\u0300","\xcf":"I\u0308","\u1e2e":"I\u0308\u0301","\u0128":"I\u0303","\u012a":"I\u0304","\u012c":"I\u0306","\u01cf":"I\u030c","\xce":"I\u0302","\u0130":"I\u0307","\u0134":"J\u0302","\u1e30":"K\u0301","\u01e8":"K\u030c","\u0139":"L\u0301","\u013d":"L\u030c","\u1e3e":"M\u0301","\u1e40":"M\u0307","\u0143":"N\u0301","\u01f8":"N\u0300","\xd1":"N\u0303","\u0147":"N\u030c","\u1e44":"N\u0307","\xd3":"O\u0301","\xd2":"O\u0300","\xd6":"O\u0308","\u022a":"O\u0308\u0304","\xd5":"O\u0303","\u1e4c":"O\u0303\u0301","\u1e4e":"O\u0303\u0308","\u022c":"O\u0303\u0304","\u014c":"O\u0304","\u1e52":"O\u0304\u0301","\u1e50":"O\u0304\u0300","\u014e":"O\u0306","\u01d1":"O\u030c","\xd4":"O\u0302","\u1ed0":"O\u0302\u0301","\u1ed2":"O\u0302\u0300","\u1ed6":"O\u0302\u0303","\u022e":"O\u0307","\u0230":"O\u0307\u0304","\u0150":"O\u030b","\u1e54":"P\u0301","\u1e56":"P\u0307","\u0154":"R\u0301","\u0158":"R\u030c","\u1e58":"R\u0307","\u015a":"S\u0301","\u1e64":"S\u0301\u0307","\u0160":"S\u030c","\u1e66":"S\u030c\u0307","\u015c":"S\u0302","\u1e60":"S\u0307","\u0164":"T\u030c","\u1e6a":"T\u0307","\xda":"U\u0301","\xd9":"U\u0300","\xdc":"U\u0308","\u01d7":"U\u0308\u0301","\u01db":"U\u0308\u0300","\u01d5":"U\u0308\u0304","\u01d9":"U\u0308\u030c","\u0168":"U\u0303","\u1e78":"U\u0303\u0301","\u016a":"U\u0304","\u1e7a":"U\u0304\u0308","\u016c":"U\u0306","\u01d3":"U\u030c","\xdb":"U\u0302","\u016e":"U\u030a","\u0170":"U\u030b","\u1e7c":"V\u0303","\u1e82":"W\u0301","\u1e80":"W\u0300","\u1e84":"W\u0308","\u0174":"W\u0302","\u1e86":"W\u0307","\u1e8c":"X\u0308","\u1e8a":"X\u0307","\xdd":"Y\u0301","\u1ef2":"Y\u0300","\u0178":"Y\u0308","\u1ef8":"Y\u0303","\u0232":"Y\u0304","\u0176":"Y\u0302","\u1e8e":"Y\u0307","\u0179":"Z\u0301","\u017d":"Z\u030c","\u1e90":"Z\u0302","\u017b":"Z\u0307","\u03ac":"\u03b1\u0301","\u1f70":"\u03b1\u0300","\u1fb1":"\u03b1\u0304","\u1fb0":"\u03b1\u0306","\u03ad":"\u03b5\u0301","\u1f72":"\u03b5\u0300","\u03ae":"\u03b7\u0301","\u1f74":"\u03b7\u0300","\u03af":"\u03b9\u0301","\u1f76":"\u03b9\u0300","\u03ca":"\u03b9\u0308","\u0390":"\u03b9\u0308\u0301","\u1fd2":"\u03b9\u0308\u0300","\u1fd1":"\u03b9\u0304","\u1fd0":"\u03b9\u0306","\u03cc":"\u03bf\u0301","\u1f78":"\u03bf\u0300","\u03cd":"\u03c5\u0301","\u1f7a":"\u03c5\u0300","\u03cb":"\u03c5\u0308","\u03b0":"\u03c5\u0308\u0301","\u1fe2":"\u03c5\u0308\u0300","\u1fe1":"\u03c5\u0304","\u1fe0":"\u03c5\u0306","\u03ce":"\u03c9\u0301","\u1f7c":"\u03c9\u0300","\u038e":"\u03a5\u0301","\u1fea":"\u03a5\u0300","\u03ab":"\u03a5\u0308","\u1fe9":"\u03a5\u0304","\u1fe8":"\u03a5\u0306","\u038f":"\u03a9\u0301","\u1ffa":"\u03a9\u0300"},Xn=function(){function e(e,t){this.mode=void 0,this.gullet=void 0,this.settings=void 0,this.leftrightDepth=void 0,this.nextToken=void 0,this.mode="math",this.gullet=new Un(e,t,this.mode),this.settings=t,this.leftrightDepth=0}var t=e.prototype;return t.expect=function(e,t){if(void 0===t&&(t=!0),this.fetch().text!==e)throw new n("Expected '"+e+"', got '"+this.fetch().text+"'",this.fetch());t&&this.consume()},t.consume=function(){this.nextToken=null},t.fetch=function(){return null==this.nextToken&&(this.nextToken=this.gullet.expandNextToken()),this.nextToken},t.switchMode=function(e){this.mode=e,this.gullet.switchMode(e)},t.parse=function(){this.settings.globalGroup||this.gullet.beginGroup(),this.settings.colorIsTextColor&&this.gullet.macros.set("\\color","\\textcolor");var e=this.parseExpression(!1);return this.expect("EOF"),this.settings.globalGroup||this.gullet.endGroup(),e},t.parseExpression=function(t,r){for(var n=[];;){"math"===this.mode&&this.consumeSpaces();var a=this.fetch();if(-1!==e.endOfExpression.indexOf(a.text))break;if(r&&a.text===r)break;if(t&&Tn[a.text]&&Tn[a.text].infix)break;var i=this.parseAtom(r);if(!i)break;"internal"!==i.type&&n.push(i)}return"text"===this.mode&&this.formLigatures(n),this.handleInfixNodes(n)},t.handleInfixNodes=function(e){for(var t,r=-1,a=0;a=0&&this.settings.reportNonstrict("unicodeTextInMathMode",'Latin-1/Unicode text character "'+t[0]+'" used in math mode',e);var s,l=X[this.mode][t].group,h=Bn.range(e);if(U.hasOwnProperty(l)){var m=l;s={type:"atom",mode:this.mode,family:m,loc:h,text:t}}else s={type:l,mode:this.mode,loc:h,text:t};i=s}else{if(!(t.charCodeAt(0)>=128))return null;this.settings.strict&&(w(t.charCodeAt(0))?"math"===this.mode&&this.settings.reportNonstrict("unicodeTextInMathMode",'Unicode text character "'+t[0]+'" used in math mode',e):this.settings.reportNonstrict("unknownSymbol",'Unrecognized Unicode character "'+t[0]+'" ('+t.charCodeAt(0)+")",e)),i={type:"textord",mode:"text",loc:Bn.range(e),text:t}}if(this.consume(),o)for(var c=0;c Date: Fri, 30 Apr 2021 10:59:11 -0500 Subject: [PATCH 063/113] bin/util.py: remove unused 'IMAGE_FILE_SUFFIX' var (#590) It should've been removed in 7e835fd. --- bin/util.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/bin/util.py b/bin/util.py index f3378f6b..ed760849 100644 --- a/bin/util.py +++ b/bin/util.py @@ -11,14 +11,6 @@ sys.exit(1) -# Things an image file's name can end with. -IMAGE_FILE_SUFFIX = { - '.gif', - '.jpg', - '.png', - '.svg' -} - # Files that shouldn't be present. UNWANTED_FILES = [ '.nojekyll' From d3e11aba9e87587e9ddf21bc87050da1d1022d27 Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Thu, 6 May 2021 10:37:26 -0500 Subject: [PATCH 064/113] bin/lesson_check.py: use proper function --- bin/lesson_check.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/lesson_check.py b/bin/lesson_check.py index 2259ee23..39ed1976 100644 --- a/bin/lesson_check.py +++ b/bin/lesson_check.py @@ -228,7 +228,7 @@ def read_references(reporter, ref_path): for (num, line) in enumerate(reader, 1): # Skip empty lines - if length(line.strip()) == 0: + if len(line.strip()) == 0: continue # Skip HTML comments From 0f1cec89ee03e2fed3ac8883e76838b6a5f3dfd4 Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Thu, 6 May 2021 11:12:34 -0500 Subject: [PATCH 065/113] bin/lesson_check.py: allow exceptions to line length limit Allow lines that contain a single image or a single link to go over the suggested line length limit. --- bin/lesson_check.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/bin/lesson_check.py b/bin/lesson_check.py index 39ed1976..2216fa70 100644 --- a/bin/lesson_check.py +++ b/bin/lesson_check.py @@ -56,6 +56,9 @@ # Pattern to match {% include ... %} statements P_INTERNAL_INCLUDE_LINK = re.compile(r'^{% include ([^ ]*) %}$') +# Pattern to match image-only and link-only lines +P_LINK_IMAGE_LINE = re.compile("^[> ]*(!?)\[([^]]+)\][([]([^)]+)[])][ ]*$") + # What kinds of blockquotes are allowed? KNOWN_BLOCKQUOTES = { 'callout', @@ -376,12 +379,19 @@ def check_line_lengths(self): """Check the raw text of the lesson body.""" if self.args.line_lengths: - over = [i for (i, l, n) in self.lines if ( - n > MAX_LINE_LEN) and (not l.startswith('!'))] - self.reporter.check(not over, + over_limit = [] + + for (i, l, n) in self.lines: + # Report lines that are longer than the suggested + # line length limit only if they're not + # link-only or image-only lines. + if n > MAX_LINE_LEN and not P_LINK_IMAGE_LINE.match(l): + over_limit.append(i) + + self.reporter.check(not over_limit, self.filename, 'Line(s) too long: {0}', - ', '.join([str(i) for i in over])) + ', '.join([str(i) for i in over_limit])) def check_trailing_whitespace(self): """Check for whitespace at the ends of lines.""" From 5b9bff41edf1b03943e959f92c9298fdf333ead5 Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Sun, 9 May 2021 02:50:44 -0500 Subject: [PATCH 066/113] lesson_check.py: harden single-line image/link pattern This change hardens the pattern that matches single-line image or link: 1. It extends the pattern to be matched in a heading 2. It allows the line to contain {: ...} customizations 3. It allows the line to end with \ --- bin/lesson_check.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/bin/lesson_check.py b/bin/lesson_check.py index 2216fa70..8416fa82 100644 --- a/bin/lesson_check.py +++ b/bin/lesson_check.py @@ -57,7 +57,16 @@ P_INTERNAL_INCLUDE_LINK = re.compile(r'^{% include ([^ ]*) %}$') # Pattern to match image-only and link-only lines -P_LINK_IMAGE_LINE = re.compile("^[> ]*(!?)\[([^]]+)\][([]([^)]+)[])][ ]*$") +P_LINK_IMAGE_LINE = re.compile(r''' + [> #]* # any number of '>', '#', and spaces + !? # ! or nothing + \[[^]]+\] # [any text] + [([] # ( or [ + [^])]+ # 1+ characters that are neither ] nor ) + [])] # ] or ) + (?:{:[^}]+})? # {:any text} or nothing + [ ]* # any number of spaces + \\?$ # \ or nothing + end of line''', re.VERBOSE) # What kinds of blockquotes are allowed? KNOWN_BLOCKQUOTES = { From a9271690d71cb232a15456d5d981f77b88bee9cf Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Tue, 11 May 2021 16:03:58 -0500 Subject: [PATCH 067/113] lesson_check.py: relax P_LINK_IMAGE_LINE pattern This PR allows up to 3 non-word (`\W` in Python's `re`-speak) characters in the beginning and end of the pattern that matches links and images. This is to allow lesson developers place punctuation marks, parentheses, or other symbols before or after the link or image on the same line in Markdown. --- bin/lesson_check.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bin/lesson_check.py b/bin/lesson_check.py index 8416fa82..90051c60 100644 --- a/bin/lesson_check.py +++ b/bin/lesson_check.py @@ -59,12 +59,14 @@ # Pattern to match image-only and link-only lines P_LINK_IMAGE_LINE = re.compile(r''' [> #]* # any number of '>', '#', and spaces + \W{,3} # up to 3 non-word characters !? # ! or nothing \[[^]]+\] # [any text] [([] # ( or [ [^])]+ # 1+ characters that are neither ] nor ) [])] # ] or ) (?:{:[^}]+})? # {:any text} or nothing + \W{,3} # up to 3 non-word characters [ ]* # any number of spaces \\?$ # \ or nothing + end of line''', re.VERBOSE) From ea9b44c1a2fd5a5f384bb54d7bb1b4c4f2c3d0b5 Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Fri, 7 May 2021 10:46:34 -0500 Subject: [PATCH 068/113] bin/util.py: Factor out reporter class. Define __all__ --- bin/lesson_check.py | 4 +-- bin/reporter.py | 75 +++++++++++++++++++++++++++++++++++++++++++++ bin/util.py | 75 +-------------------------------------------- 3 files changed, 78 insertions(+), 76 deletions(-) create mode 100644 bin/reporter.py diff --git a/bin/lesson_check.py b/bin/lesson_check.py index 90051c60..cbcaedc3 100644 --- a/bin/lesson_check.py +++ b/bin/lesson_check.py @@ -8,8 +8,8 @@ import re from argparse import ArgumentParser -from util import (Reporter, read_markdown, load_yaml, check_unwanted_files, - require) +from util import * +from reporter import Reporter __version__ = '0.3' diff --git a/bin/reporter.py b/bin/reporter.py new file mode 100644 index 00000000..550dbf05 --- /dev/null +++ b/bin/reporter.py @@ -0,0 +1,75 @@ +import sys + +class Reporter: + """Collect and report errors.""" + + # Marker to show that an expected value hasn't been provided. + # (Can't use 'None' because that might be a legitimate value.) + _DEFAULT_REPORTER = [] + + def __init__(self): + """Constructor.""" + self.messages = [] + + def check_field(self, filename, name, values, key, expected=_DEFAULT_REPORTER): + """Check that a dictionary has an expected value.""" + + if key not in values: + self.add(filename, '{0} does not contain {1}', name, key) + elif expected is self._DEFAULT_REPORTER: + pass + elif type(expected) in (tuple, set, list): + if values[key] not in expected: + self.add( + filename, '{0} {1} value {2} is not in {3}', name, key, values[key], expected) + elif values[key] != expected: + self.add(filename, '{0} {1} is {2} not {3}', + name, key, values[key], expected) + + def check(self, condition, location, fmt, *args): + """Append error if condition not met.""" + + if not condition: + self.add(location, fmt, *args) + + def add(self, location, fmt, *args): + """Append error unilaterally.""" + + self.messages.append((location, fmt.format(*args))) + + @staticmethod + def pretty(item): + location, message = item + if isinstance(location, type(None)): + return message + elif isinstance(location, str): + return location + ': ' + message + elif isinstance(location, tuple): + return '{0}:{1}: '.format(*location) + message + + print('Unknown item "{0}"'.format(item), file=sys.stderr) + return NotImplemented + + @staticmethod + def key(item): + location, message = item + if isinstance(location, type(None)): + return ('', -1, message) + elif isinstance(location, str): + return (location, -1, message) + elif isinstance(location, tuple): + return (location[0], location[1], message) + + print('Unknown item "{0}"'.format(item), file=sys.stderr) + return NotImplemented + + def report(self, stream=sys.stdout): + """Report all messages in order.""" + + if not self.messages: + return + + for m in sorted(self.messages, key=self.key): + print(self.pretty(m), file=stream) + + diff --git a/bin/util.py b/bin/util.py index ed760849..8a32fd95 100644 --- a/bin/util.py +++ b/bin/util.py @@ -10,86 +10,13 @@ print('Unable to import YAML module: please install PyYAML', file=sys.stderr) sys.exit(1) +__all__ = ['check_unwanted_files', 'load_yaml', 'read_markdown', 'require'] # Files that shouldn't be present. UNWANTED_FILES = [ '.nojekyll' ] -# Marker to show that an expected value hasn't been provided. -# (Can't use 'None' because that might be a legitimate value.) -REPORTER_NOT_SET = [] - - -class Reporter: - """Collect and report errors.""" - - def __init__(self): - """Constructor.""" - self.messages = [] - - def check_field(self, filename, name, values, key, expected=REPORTER_NOT_SET): - """Check that a dictionary has an expected value.""" - - if key not in values: - self.add(filename, '{0} does not contain {1}', name, key) - elif expected is REPORTER_NOT_SET: - pass - elif type(expected) in (tuple, set, list): - if values[key] not in expected: - self.add( - filename, '{0} {1} value {2} is not in {3}', name, key, values[key], expected) - elif values[key] != expected: - self.add(filename, '{0} {1} is {2} not {3}', - name, key, values[key], expected) - - def check(self, condition, location, fmt, *args): - """Append error if condition not met.""" - - if not condition: - self.add(location, fmt, *args) - - def add(self, location, fmt, *args): - """Append error unilaterally.""" - - self.messages.append((location, fmt.format(*args))) - - @staticmethod - def pretty(item): - location, message = item - if isinstance(location, type(None)): - return message - elif isinstance(location, str): - return location + ': ' + message - elif isinstance(location, tuple): - return '{0}:{1}: '.format(*location) + message - - print('Unknown item "{0}"'.format(item), file=sys.stderr) - return NotImplemented - - @staticmethod - def key(item): - location, message = item - if isinstance(location, type(None)): - return ('', -1, message) - elif isinstance(location, str): - return (location, -1, message) - elif isinstance(location, tuple): - return (location[0], location[1], message) - - print('Unknown item "{0}"'.format(item), file=sys.stderr) - return NotImplemented - - def report(self, stream=sys.stdout): - """Report all messages in order.""" - - if not self.messages: - return - - for m in sorted(self.messages, key=self.key): - print(self.pretty(m), file=stream) - - def read_markdown(parser, path): """ Get YAML and AST for Markdown file, returning From 4afcce8ab19e1dbcffb0a31f31f50969260b2a3e Mon Sep 17 00:00:00 2001 From: Renato Alves Date: Sat, 15 May 2021 00:01:24 +0200 Subject: [PATCH 069/113] Don't force hostname into relative_root_path --- _includes/base_path.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/_includes/base_path.html b/_includes/base_path.html index 41139587..4f343afa 100644 --- a/_includes/base_path.html +++ b/_includes/base_path.html @@ -7,7 +7,7 @@ 'site.url' is set to 'http://localhost:4000' and 'site.baseurl' is empty. -In both of the above cases we set 'relative_root_path' to 'site.url + site.baseurl'. +In both of the above cases we set 'relative_root_path' to 'site.baseurl'. When we build a website locally with `jekyll build`, both 'site.url' and 'site.baseurl' are empty. @@ -25,7 +25,7 @@ {%- endcomment -%} {% if site.url %} - {% assign relative_root_path = site.url | append: site.baseurl %} + {% assign relative_root_path = site.baseurl %} {% else %} {% assign last_char = page.url | slice: -1 %} {% if last_char == "/" %} From 5e8d0596899b4bbac22b91c59a4ee8a381c8941b Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Wed, 19 May 2021 12:30:50 -0500 Subject: [PATCH 070/113] lesson_check.py: add a comment about importing * from a package Co-authored-by: Zhian N. Kamvar --- bin/lesson_check.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bin/lesson_check.py b/bin/lesson_check.py index cbcaedc3..196743e4 100644 --- a/bin/lesson_check.py +++ b/bin/lesson_check.py @@ -8,6 +8,8 @@ import re from argparse import ArgumentParser +# This uses the `__all__` list in `util.py` to determine what objects to import +# see https://docs.python.org/3/tutorial/modules.html#importing-from-a-package from util import * from reporter import Reporter From 4c415a965ee8063144aed4ace18776dffbfce694 Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Wed, 19 May 2021 15:00:49 -0500 Subject: [PATCH 071/113] lesson.scss: define 'inline' class for images Define `inline` class for images that should not be displayed as block elements. By appending `{:class="inline"}` or `{: .inline}` to the image definition in Markdown, one can create an inline image that doesn't break the current line and is embedded in the paragraph. Useful for showing special symbols and hieroglyphs that we can't display by other means. --- assets/css/lesson.scss | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/assets/css/lesson.scss b/assets/css/lesson.scss index 68a35508..c982e529 100644 --- a/assets/css/lesson.scss +++ b/assets/css/lesson.scss @@ -258,6 +258,11 @@ article img { max-width: 100%; } +article img.inline { + display: inline-block; + margin: auto; +} + article h2 { margin: 48px 0 16px; border-bottom: solid 1px #eaecef; From 591953016126bbf62e1a8d376f8971dc60943549 Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Thu, 20 May 2021 10:12:06 -0500 Subject: [PATCH 072/113] Fix Reporter class imports --- bin/repo_check.py | 3 ++- bin/test_lesson_check.py | 4 ++-- bin/workshop_check.py | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/bin/repo_check.py b/bin/repo_check.py index 9bf5c597..6988ca59 100644 --- a/bin/repo_check.py +++ b/bin/repo_check.py @@ -9,7 +9,8 @@ import re from argparse import ArgumentParser -from util import Reporter, require +from util import require +from reporter import Reporter # Import this way to produce a more useful error message. try: diff --git a/bin/test_lesson_check.py b/bin/test_lesson_check.py index 0981720a..7a6d603a 100644 --- a/bin/test_lesson_check.py +++ b/bin/test_lesson_check.py @@ -1,12 +1,12 @@ import unittest import lesson_check -import util +import reporter class TestFileList(unittest.TestCase): def setUp(self): - self.reporter = util.Reporter() # TODO: refactor reporter class. + self.reporter = reporter.Reporter() # TODO: refactor reporter class. def test_file_list_has_expected_entries(self): # For first pass, simply assume that all required files are present diff --git a/bin/workshop_check.py b/bin/workshop_check.py index 2c8dddf3..312b1a1d 100644 --- a/bin/workshop_check.py +++ b/bin/workshop_check.py @@ -7,7 +7,8 @@ import os import re from datetime import date -from util import Reporter, split_metadata, load_yaml, check_unwanted_files +from util import split_metadata, load_yaml, check_unwanted_files +from reporter import Reporter # Metadata field patterns. EMAIL_PATTERN = r'[^@]+@[^@]+\.[^@]+' From da771119b6c4adc61dea3e33786a3c8179600cb1 Mon Sep 17 00:00:00 2001 From: "Zhian N. Kamvar" Date: Fri, 21 May 2021 03:38:07 -0700 Subject: [PATCH 073/113] update R dependency search; Allow Bioconductor packages (#600) --- .github/workflows/template.yml | 12 ++++--- .github/workflows/website.yml | 11 +++--- bin/dependencies.R | 63 +++++++++++++++++++++++++++++----- 3 files changed, 67 insertions(+), 19 deletions(-) diff --git a/.github/workflows/template.yml b/.github/workflows/template.yml index 3e91db6b..9ff0d662 100644 --- a/.github/workflows/template.yml +++ b/.github/workflows/template.yml @@ -137,9 +137,10 @@ jobs: - name: Install needed packages if: steps.check-rmd.outputs.count != 0 + working-directory: lesson run: | - packages = setdiff(c('remotes', 'rprojroot', 'renv', 'desc', 'rmarkdown', 'knitr'), rownames(installed.packages())) - install.packages(packages, repo="https://cran.rstudio.com/") + source('bin/dependencies.R') + install_required_packages(.libPaths()[1]) shell: Rscript {0} - name: Query dependencies @@ -149,13 +150,14 @@ jobs: source('bin/dependencies.R') deps <- identify_dependencies() create_description(deps) + use_bioc_repos() saveRDS(remotes::dev_package_deps(dependencies = TRUE), ".github/depends.Rds", version = 2) writeLines(sprintf("R-%i.%i", getRversion()$major, getRversion()$minor), ".github/R-version") shell: Rscript {0} - - name: Cache R packages + - name: Restore Package Cache if: runner.os != 'Windows' && steps.check-rmd.outputs.count != 0 - uses: actions/cache@v1 + uses: actions/cache@v2 with: path: ${{ env.R_LIBS_USER }} key: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-${{ hashFiles('.github/depends.Rds') }} @@ -172,7 +174,7 @@ jobs: run: | while read -r cmd do - eval sudo $cmd + eval sudo $cmd || echo "Nothing to update" done < <(Rscript -e 'cat(remotes::system_requirements("ubuntu", "20.04"), sep = "\n")') - run: make site diff --git a/.github/workflows/website.yml b/.github/workflows/website.yml index 246d4c70..9d47e300 100644 --- a/.github/workflows/website.yml +++ b/.github/workflows/website.yml @@ -52,9 +52,9 @@ jobs: with: r-version: 'release' - - name: Cache R packages + - name: Restore R Cache if: steps.check-rmd.outputs.count != 0 - uses: actions/cache@v1 + uses: actions/cache@v2 with: path: ${{ env.R_LIBS_USER }} key: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-${{ hashFiles('.github/depends.Rds') }} @@ -63,8 +63,8 @@ jobs: - name: Install needed packages if: steps.check-rmd.outputs.count != 0 run: | - packages = setdiff(c('remotes', 'rprojroot', 'renv', 'desc', 'rmarkdown', 'knitr'), rownames(installed.packages())) - install.packages(packages, repo="https://cran.rstudio.com/") + source('bin/dependencies.R') + install_required_packages() shell: Rscript {0} - name: Query dependencies @@ -73,6 +73,7 @@ jobs: source('bin/dependencies.R') deps <- identify_dependencies() create_description(deps) + use_bioc_repos() saveRDS(remotes::dev_package_deps(dependencies = TRUE), ".github/depends.Rds", version = 2) writeLines(sprintf("R-%i.%i", getRversion()$major, getRversion()$minor), ".github/R-version") shell: Rscript {0} @@ -83,7 +84,7 @@ jobs: run: | while read -r cmd do - eval sudo $cmd + eval sudo $cmd || echo "Nothing to update" done < <(Rscript -e 'cat(remotes::system_requirements("ubuntu", "20.04"), sep = "\n")') - name: Render the markdown and confirm that the site can be built diff --git a/bin/dependencies.R b/bin/dependencies.R index ee9d38a8..4eeeb215 100644 --- a/bin/dependencies.R +++ b/bin/dependencies.R @@ -1,17 +1,19 @@ install_required_packages <- function(lib = NULL, repos = getOption("repos", default = c(CRAN = "https://cran.rstudio.com/"))) { if (is.null(lib)) { - lib <- .libPaths() + lib <- .libPaths()[[1]] } message("lib paths: ", paste(lib, collapse = ", ")) - required_pkgs <- c("rprojroot", "desc", "remotes", "renv") + # Note: RMarkdown is needed for renv to detect packages in Rmd documents. + required_pkgs <- c("rprojroot", "desc", "remotes", "renv", "BiocManager", "rmarkdown") installed_pkgs <- rownames(installed.packages(lib.loc = lib)) missing_pkgs <- setdiff(required_pkgs, installed_pkgs) - # The default installation of R will have "@CRAN@" as the default repository, which directs contrib.url() to either - # force the user to choose a mirror if interactive or fail if not. Since we are not interactve, we need to force the - # mirror here. + # The default installation of R will have "@CRAN@" as the default repository, + # which directs contrib.url() to either force the user to choose a mirror if + # interactive or fail if not. Since we are not interactve, we need to force + # the mirror here. if ("@CRAN@" %in% repos) { repos <- c(CRAN = "https://cran.rstudio.com/") } @@ -29,15 +31,42 @@ find_root <- function() { root } +# set the BiocManager repositories and return a function that resets the default +# repositories. +# +# @example +# bioc_repos_example <- function() { +# message("User repos") +# as.data.frame(getOption("repos")) +# reset_repos <- use_bioc_repos() +# on.exit(reset_repos()) +# message("Bioc repos") +# as.data.frame(getOption("repos")) +# } +# bioc_repos_example() +# as.data.frame(getOption("repos") +use_bioc_repos <- function() { + repos <- getOption("repos") + suppressMessages(options(repos = BiocManager::repositories())) + function() { + options(repos = repos) + } +} + identify_dependencies <- function() { root <- find_root() + reset_repos <- use_bioc_repos() + on.exit(reset_repos(), add = TRUE) + eps <- file.path(root, "_episodes_rmd") + bin <- file.path(root, "bin") + required_pkgs <- unique(c( ## Packages for episodes - renv::dependencies(file.path(root, "_episodes_rmd"), progress = FALSE, error = "ignore")$Package, + renv::dependencies(eps, progress = FALSE, error = "ignored")$Package, ## Packages for tools - renv::dependencies(file.path(root, "bin"), progress = FALSE, error = "ignore")$Package + renv::dependencies(bin, progress = FALSE, error = "ignored")$Package )) required_pkgs @@ -45,14 +74,30 @@ identify_dependencies <- function() { create_description <- function(required_pkgs) { d <- desc::description$new("!new") - lapply(required_pkgs, function(x) d$set_dep(x)) + d$set_deps(data.frame(type = "Imports", package = required_pkgs, version = "*")) d$write("DESCRIPTION") + # We have to write the description twice to get the hidden dependencies + # because renv only considers explicit dependencies. + # + # This is needed because some of the hidden dependencis will require system + # libraries to be configured. + suppressMessages(repo <- BiocManager::repositories()) + deps <- remotes::dev_package_deps(dependencies = TRUE, repos = repo) + deps <- deps$package[deps$diff < 0] + if (length(deps)) { + # only create new DESCRIPTION file if there are dependencies to install + d$set_deps(data.frame(type = "Imports", package = deps, version = "*")) + d$write("DESCRIPTION") + } } install_dependencies <- function(required_pkgs, ...) { + reset_repos <- use_bioc_repos() + on.exit(reset_repos(), add = TRUE) + create_description(required_pkgs) - on.exit(file.remove("DESCRIPTION")) + on.exit(file.remove("DESCRIPTION"), add = TRUE) remotes::install_deps(dependencies = TRUE, ...) if (require("knitr") && packageVersion("knitr") < '1.9.19') { From 929c1a752f4bcf714e675a32e0bd53ade326f8dd Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Sat, 5 Jun 2021 11:35:11 -0500 Subject: [PATCH 074/113] Automatically add deep anchor links using AnchorJS --- _includes/javascript.html | 12 ++++++++++++ assets/js/anchor.min.js | 9 +++++++++ 2 files changed, 21 insertions(+) create mode 100644 assets/js/anchor.min.js diff --git a/_includes/javascript.html b/_includes/javascript.html index 77080ae5..1c4877a6 100644 --- a/_includes/javascript.html +++ b/_includes/javascript.html @@ -4,6 +4,7 @@ + + {% if page.math %} {% endif %} +{%- comment -%} +AnchorJS: A JavaScript utility for adding deep anchor links +https://github.com/bryanbraun/anchorjs +https://cdn.jsdelivr.net/npm/anchor-js/anchor.min.js +{%- endcomment -%} + + + diff --git a/assets/js/anchor.min.js b/assets/js/anchor.min.js new file mode 100644 index 00000000..1c2b86fa --- /dev/null +++ b/assets/js/anchor.min.js @@ -0,0 +1,9 @@ +// @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt Expat +// +// AnchorJS - v4.3.1 - 2021-04-17 +// https://www.bryanbraun.com/anchorjs/ +// Copyright (c) 2021 Bryan Braun; Licensed MIT +// +// @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt Expat +!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}}}); +// @license-end \ No newline at end of file From b33336be5186c9b439c19f4125e28ab6ec77332a Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Thu, 24 Jun 2021 03:33:52 -0500 Subject: [PATCH 075/113] Makefile: require index.md (#607) --- Makefile | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 8b02ab11..2068f87a 100644 --- a/Makefile +++ b/Makefile @@ -41,11 +41,11 @@ endif .PHONY: site docker-serve repo-check clean clean-rmd ## * serve : render website and run a local server -serve : lesson-md +serve : lesson-md index.md ${JEKYLL} serve ## * site : build website but do not run a server -site : lesson-md +site : lesson-md index.md ${JEKYLL} build ## * docker-serve : use Docker to serve the site @@ -172,3 +172,10 @@ ifeq (, $(PYTHON)) else @: endif + +index.md : +ifeq (, $(wildcard index.md)) + $(error index.md not found) +else + @: +endif From d222b47db3feb1d683b5c8dcff4fac5d1d66511f Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Fri, 25 Jun 2021 03:17:40 -0500 Subject: [PATCH 076/113] Makefile: docker-serve target: ensure Docker is installed (#608) --- Makefile | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 2068f87a..6bf02c6d 100644 --- a/Makefile +++ b/Makefile @@ -7,6 +7,9 @@ JEKYLL=bundle config set --local path .vendor/bundle && bundle install && bundle PARSER=bin/markdown_ast.rb DST=_site +# Find Docker +DOCKER := $(shell which docker 2>/dev/null) + # Check Python 3 is installed and determine if it's called via python3 or python # (https://stackoverflow.com/a/4933395) PYTHON3_EXE := $(shell which python3 2>/dev/null) @@ -50,14 +53,18 @@ site : lesson-md index.md ## * docker-serve : use Docker to serve the site docker-serve : - @docker pull carpentries/lesson-docker:latest - @docker run --rm -it \ +ifeq (, $(DOCKER)) + $(error Your system does not appear to have Docker installed) +else + @$(DOCKER) pull carpentries/lesson-docker:latest + @$(DOCKER) run --rm -it \ -v $${PWD}:/home/rstudio \ -p 4000:4000 \ -p 8787:8787 \ -e USERID=$$(id -u) \ -e GROUPID=$$(id -g) \ carpentries/lesson-docker:latest +endif ## * repo-check : check repository settings repo-check : python From 9d1442f4fc03af3747c51879d6b35803e56ace6e Mon Sep 17 00:00:00 2001 From: "K.E. Koziar" Date: Sat, 3 Jul 2021 07:21:50 -0700 Subject: [PATCH 077/113] Fix broken "How to contribute" link --- bin/boilerplate/CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/boilerplate/CONTRIBUTING.md b/bin/boilerplate/CONTRIBUTING.md index a997b350..8c095d86 100644 --- a/bin/boilerplate/CONTRIBUTING.md +++ b/bin/boilerplate/CONTRIBUTING.md @@ -141,7 +141,7 @@ You can also [reach us by email][email]. [github]: https://github.com [github-flow]: https://guides.github.com/introduction/flow/ [github-join]: https://github.com/join -[how-contribute]: https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github +[how-contribute]: https://app.egghead.io/playlists/how-to-contribute-to-an-open-source-project-on-github [issues]: https://guides.github.com/features/issues/ [swc-issues]: https://github.com/issues?q=user%3Aswcarpentry [swc-lessons]: https://software-carpentry.org/lessons/ From a7d50e1946ad976cc82c889be2d323b900aef449 Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Fri, 9 Jul 2021 15:31:50 -0500 Subject: [PATCH 078/113] lesson_check.py: report check status at the end --- bin/lesson_check.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/bin/lesson_check.py b/bin/lesson_check.py index 196743e4..846671a6 100644 --- a/bin/lesson_check.py +++ b/bin/lesson_check.py @@ -6,6 +6,7 @@ import os import glob import re +import sys from argparse import ArgumentParser # This uses the `__all__` list in `util.py` to determine what objects to import @@ -142,8 +143,16 @@ def main(): checker.check() args.reporter.report() - if args.reporter.messages and not args.permissive: - exit(1) + if args.reporter.messages: + if args.permissive: + print("Problems detected but ignored (permissive mode).") + else: + print("Problems detected.") + sys.exit(1) + else: + print("No problems found.") + + return def parse_args(): From 2735d4e49ff512e282a00ea68ec93bf35466dc8c Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Fri, 9 Jul 2021 15:51:47 -0500 Subject: [PATCH 079/113] util.py: load_yaml: Don't fail when it's not necessary Also, make 'require()' function not fail by default. The only case where we really need to fail is when 'kramdown' parser is not specified. This is a highly unlikely scenario, tbh (because arguments to `lesson_check.py` are set in the Makefile), but we can think about reworking/optimizing this part later. --- bin/lesson_check.py | 3 ++- bin/util.py | 22 +++++++++++++--------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/bin/lesson_check.py b/bin/lesson_check.py index 196743e4..78884ee6 100644 --- a/bin/lesson_check.py +++ b/bin/lesson_check.py @@ -180,7 +180,8 @@ def parse_args(): args, extras = parser.parse_known_args() require(args.parser is not None, - 'Path to Markdown parser not provided') + 'Path to Markdown parser not provided', + True) require(not extras, 'Unexpected trailing command-line arguments "{0}"'.format(extras)) diff --git a/bin/util.py b/bin/util.py index 8a32fd95..1398c378 100644 --- a/bin/util.py +++ b/bin/util.py @@ -65,9 +65,8 @@ def split_metadata(path, text): try: metadata_yaml = yaml.load(metadata_raw, Loader=yaml.SafeLoader) except yaml.YAMLError as e: - print('Unable to parse YAML header in {0}:\n{1}'.format( - path, e), file=sys.stderr) - sys.exit(1) + message = 'Unable to parse YAML header in {0}:\n{1}' + print(message.format(path, e), file=sys.stderr) return metadata_raw, metadata_yaml, text @@ -81,11 +80,14 @@ def load_yaml(filename): try: with open(filename, 'r', encoding='utf-8') as reader: return yaml.load(reader, Loader=yaml.SafeLoader) - except (yaml.YAMLError, IOError) as e: - print('Unable to load YAML file {0}:\n{1}'.format( - filename, e), file=sys.stderr) - sys.exit(1) + except yaml.YAMLError as e: + message = 'ERROR: Unable to load YAML file {0}:\n{1}' + print(message.format(filename, e), file=sys.stderr) + except (FileNotFoundError, IOError): + message = 'ERROR: File {} not found' + print(message.format(filename), file=sys.stderr) + return {} def check_unwanted_files(dir_path, reporter): """ @@ -99,9 +101,11 @@ def check_unwanted_files(dir_path, reporter): "Unwanted file found") -def require(condition, message): +def require(condition, message, fatal=False): """Fail if condition not met.""" if not condition: print(message, file=sys.stderr) - sys.exit(1) + + if fatal: + sys.exit(1) From 8498d313ef1d7b4f59fa171e9546435c13ec7087 Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Fri, 9 Jul 2021 16:17:49 -0500 Subject: [PATCH 080/113] lesson_check.py: fix error message for the 'defaults' check --- bin/lesson_check.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/bin/lesson_check.py b/bin/lesson_check.py index 196743e4..cfe1224e 100644 --- a/bin/lesson_check.py +++ b/bin/lesson_check.py @@ -208,9 +208,14 @@ def check_config(reporter, source_dir): {'values': {'root': '..', 'layout': 'episode'}, 'scope': {'type': 'episodes', 'path': ''}}, {'values': {'root': '..', 'layout': 'page'}, 'scope': {'type': 'extras', 'path': ''}} ]: - reporter.check(defaults in config.get('defaults', []), - 'configuration', - '"root" not set to "." in configuration') + error_text = 'incorrect settings for: root "{0}" layout "{1}"' + root = defaults["values"]["root"] + layout = defaults["values"]["layout"] + error_message = error_text.format(root, layout) + + defaults_test = defaults in config.get('defaults', []) + reporter.check(defaults_test, 'configuration', error_message) + if 'life_cycle' not in config: config['life_cycle'] = None return config['life_cycle'] From 19dc8e3c012638ca15e5f48fcbbd7db194c7d769 Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Fri, 9 Jul 2021 21:56:28 -0500 Subject: [PATCH 081/113] lesson_check.py: use proper regex for matching episode files --- bin/lesson_check.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bin/lesson_check.py b/bin/lesson_check.py index 196743e4..7f950a44 100644 --- a/bin/lesson_check.py +++ b/bin/lesson_check.py @@ -533,7 +533,7 @@ def check(self): """Run extra tests.""" super().check() - if not using_remote_theme(args.source_dir): + if not using_remote_theme(self.args.source_dir): self.check_reference_inclusion() def check_metadata(self): @@ -601,7 +601,8 @@ def __init__(self, args, filename, metadata, metadata_len, text, lines, doc): (re.compile(r'README\.md'), CheckNonJekyll), (re.compile(r'index\.md'), CheckIndex), (re.compile(r'reference\.md'), CheckReference), - (re.compile(os.path.join('_episodes', '*\.md')), CheckEpisode), + # '.' below is what's passed on the command line via '-s' flag + (re.compile(os.path.join('.','_episodes', '[^/]*\.md')), CheckEpisode), (re.compile(r'.*\.md'), CheckGeneric) ] From e3808e8060680c182578e3f40a8723057f290e52 Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Mon, 12 Jul 2021 14:35:08 -0500 Subject: [PATCH 082/113] lesson-check.py: read `config.yml` only once 1. Read `config.yml` file only once and store the contents in a global variable `CONFIG`. We're currently reading this file twice. 2. Detect lesson life cycle in `main` instead of making `check_config` return it. 3. Replace `using_remote_theme` function with a single test that checks that `remote_theme` keyword is present in `_config.yml` 4. CheckEpisode class: `check` method: move "remote theme test" inside the `check_reference_inclusion`. 5. main: mvoe "remote theme test" inside the `read_references` --- bin/lesson_check.py | 54 +++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/bin/lesson_check.py b/bin/lesson_check.py index f223ccfe..86e42495 100644 --- a/bin/lesson_check.py +++ b/bin/lesson_check.py @@ -9,7 +9,7 @@ import sys from argparse import ArgumentParser -# This uses the `__all__` list in `util.py` to determine what objects to import +# This uses the `__all__` list in `util.py` to determine what objects to import # see https://docs.python.org/3/tutorial/modules.html#importing-from-a-package from util import * from reporter import Reporter @@ -119,21 +119,29 @@ # Please keep this in sync with .editorconfig! MAX_LINE_LEN = 100 +# Contents of _config.yml +CONFIG = {} def main(): """Main driver.""" args = parse_args() args.reporter = Reporter() - life_cycle = check_config(args.reporter, args.source_dir) + + global CONFIG + config_file = os.path.join(args.source_dir, '_config.yml') + CONFIG = load_yaml(config_file) + CONFIG["config_file"] = config_file + + life_cycle = CONFIG.get('life_cycle', None) # pre-alpha lessons should report without error if life_cycle == "pre-alpha": args.permissive = True + + check_config(args.reporter) check_source_rmd(args.reporter, args.source_dir, args.parser) - args.references = {} - if not using_remote_theme(args.source_dir): - args.references = read_references(args.reporter, args.reference_path) + args.references = read_references(args.reporter, args.reference_path) docs = read_all_markdown(args.source_dir, args.parser) check_fileset(args.source_dir, args.reporter, list(docs.keys())) @@ -196,22 +204,15 @@ def parse_args(): return args -def using_remote_theme(source_dir): - config_file = os.path.join(source_dir, '_config.yml') - config = load_yaml(config_file) - return 'remote_theme' in config - -def check_config(reporter, source_dir): +def check_config(reporter): """Check configuration file.""" - config_file = os.path.join(source_dir, '_config.yml') - config = load_yaml(config_file) - reporter.check_field(config_file, 'configuration', - config, 'kind', 'lesson') - reporter.check_field(config_file, 'configuration', - config, 'carpentry', ('swc', 'dc', 'lc', 'cp', 'incubator')) - reporter.check_field(config_file, 'configuration', config, 'title') - reporter.check_field(config_file, 'configuration', config, 'email') + reporter.check_field(CONFIG["config_file"], 'configuration', + CONFIG, 'kind', 'lesson') + reporter.check_field(CONFIG["config_file"], 'configuration', + CONFIG, 'carpentry', ('swc', 'dc', 'lc', 'cp', 'incubator')) + reporter.check_field(CONFIG["config_file"], 'configuration', CONFIG, 'title') + reporter.check_field(CONFIG["config_file"], 'configuration', CONFIG, 'email') for defaults in [ {'values': {'root': '.', 'layout': 'page'}}, @@ -223,13 +224,9 @@ def check_config(reporter, source_dir): layout = defaults["values"]["layout"] error_message = error_text.format(root, layout) - defaults_test = defaults in config.get('defaults', []) + defaults_test = defaults in CONFIG.get('defaults', []) reporter.check(defaults_test, 'configuration', error_message) - if 'life_cycle' not in config: - config['life_cycle'] = None - return config['life_cycle'] - def check_source_rmd(reporter, source_dir, parser): """Check that Rmd episode files include `source: Rmd`""" @@ -249,6 +246,9 @@ def read_references(reporter, ref_path): {symbolic_name : URL} """ + if 'remote_theme' in CONFIG: + return {} + if not ref_path: raise Warning("No filename has been provided.") @@ -548,8 +548,7 @@ def check(self): """Run extra tests.""" super().check() - if not using_remote_theme(self.args.source_dir): - self.check_reference_inclusion() + self.check_reference_inclusion() def check_metadata(self): super().check_metadata() @@ -579,6 +578,9 @@ def check_metadata_fields(self, expected): def check_reference_inclusion(self): """Check that links file has been included.""" + if 'remote_theme' in CONFIG: + return + if not self.args.reference_path: return From 1019f1234b70f0b0bcd59c5c7cc7b42a1efbfc25 Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Tue, 20 Jul 2021 04:43:06 -0500 Subject: [PATCH 083/113] 404.md: expand contractions (#620) --- 404.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/404.md b/404.md index 2038a508..c1cf9dd4 100644 --- a/404.md +++ b/404.md @@ -5,12 +5,12 @@ permalink: 404.html title: "Page not found" --- -# Oops! We can't find that page. +# Oops! We cannot find that page. {: style="text-align: center;"} > ## Our apologies! > -> We can't seem to find the page you're looking for. +> We cannot seem to find the page you are looking for. > Try going back to the previous page or > navigate to any other page using the navigation bar above > {%- if site.kind == "lesson" -%} or the schedule below {%- endif -%}. From 523728542393eda93f07bb44f0e48018e763c9ef Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Tue, 20 Jul 2021 04:45:32 -0500 Subject: [PATCH 084/113] Syllabus: add conditional intructor training pre-/post- surveys (#618) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Port of carpentries/instructor-training@f488d248d55637f05bea3f9592451f887a3a7c83 Co-authored-by: François Michonneau Co-authored-by: François Michonneau --- _includes/syllabus.html | 19 +++++++++++++++++++ bin/boilerplate/_config.yml | 2 ++ 2 files changed, 21 insertions(+) diff --git a/_includes/syllabus.html b/_includes/syllabus.html index 6f113460..35f9c4f4 100644 --- a/_includes/syllabus.html +++ b/_includes/syllabus.html @@ -30,6 +30,14 @@

Schedule

Setup Download files required for the lesson + {% if site.instructor_training %} + + {% if multiday %}{% endif %} + + Pre-training survey + Please fill out our pre-training survey before the start of the course. + + {% endif %} {% for lesson_episode in lesson_episodes %} {% if site.episode_order %} {% assign episode = site.episodes | where: "slug", lesson_episode | first %} @@ -78,6 +86,17 @@

Schedule

{% endfor %} {% assign hours = current | divided_by: 60 %} {% assign minutes = current | modulo: 60 %} + {% if site.instructor_training %} + + {% if multiday %}{% endif %} + {% if hours < 10 %}0{% endif %}{{ hours }}:{% if minutes < 10 %}0{% endif +++ %}{{ minutes }} + Post-training survey + Please fill out our post-training survey after the course. + + {% assign current = current | plus: 15 %} + {% assign hours = current | divided_by: 60 %} + {% assign minutes = current | modulo: 60 %} + {% endif %} {% if multiday %}{% endif %} {% if hours < 10 %}0{% endif %}{{ hours }}:{% if minutes < 10 %}0{% endif %}{{ minutes }} diff --git a/bin/boilerplate/_config.yml b/bin/boilerplate/_config.yml index 6aa17f69..242699cf 100644 --- a/bin/boilerplate/_config.yml +++ b/bin/boilerplate/_config.yml @@ -57,6 +57,8 @@ post_survey: "https://carpentries.typeform.com/to/UgVdRQ?slug=" instructor_pre_survey: "https://www.surveymonkey.com/r/instructor_training_pre_survey?workshop_id=" instructor_post_survey: "https://www.surveymonkey.com/r/instructor_training_post_survey?workshop_id=" +# Set to 'true' for instructor training websites only. +instructor_training: false # Start time in minutes (0 to be clock-independent, 540 to show a start at 09:00 am). start_time: 0 From 674025cc64592395e76871052a00675427b5ac33 Mon Sep 17 00:00:00 2001 From: Maxim Belkin Date: Tue, 20 Jul 2021 04:47:18 -0500 Subject: [PATCH 085/113] Navigation bar: allow excluding extras (#617) Port of carpentries/instructor-training@dc1b52ab11fa7d247db32df0523e0656faf74dc5 Co-authored-by: maneesha sane Co-authored-by: maneesha sane --- _includes/navbar.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/_includes/navbar.html b/_includes/navbar.html index 9db636a2..5e7d20eb 100644 --- a/_includes/navbar.html +++ b/_includes/navbar.html @@ -80,7 +80,9 @@ {% else %} {% assign extra = lesson_extra %} {% endif %} -
  • {{ extra.title }}
  • + {% unless extra.exclude %} +
  • {{ extra.title }}
  • + {% endunless %} {% endfor %} From 332145f0c10b015f9b14ee199f94248eef2c939e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Michonneau?= Date: Thu, 22 Jul 2021 16:53:26 +0200 Subject: [PATCH 086/113] add styling for lesson in The Carpentries Lab Co-authored-by: Toby Hodges --- _includes/life_cycle.html | 14 +- _includes/navbar.html | 4 + assets/css/lesson.scss | 5 + assets/img/carpentrieslab.svg | 249 ++++++++++++++++++++++++++++++++++ 4 files changed, 271 insertions(+), 1 deletion(-) create mode 100644 assets/img/carpentrieslab.svg diff --git a/_includes/life_cycle.html b/_includes/life_cycle.html index efc5b6d9..72756b30 100644 --- a/_includes/life_cycle.html +++ b/_includes/life_cycle.html @@ -28,7 +28,19 @@ {% elsif site.life_cycle == "stable" %} {% comment %} -We don't do anything special for now +We don't do anything special unless this is a Carpentries Lab lesson {% endcomment %} +{% if site.carpentry == "lab" %} +{% if site.doi contains "zenodo" %}{% assign listing=" on Zenodo" %} +{% elsif site.doi contains "jose" %}{% assign listing=" in JOSE" %} +{% else %}{% assign listing="none" %} +{% endif %} + +
    +
    + This lesson has passed peer-review! {% if site.doi != "" %}See the publication{{ listing }}.{% endif %} +
    +
    +{% endif %} {% endif %} diff --git a/_includes/navbar.html b/_includes/navbar.html index 5e7d20eb..a8e3d596 100644 --- a/_includes/navbar.html +++ b/_includes/navbar.html @@ -32,6 +32,10 @@ + {% elsif site.carpentry == "lab" %} + + + {% endif %} {% comment %} Always show link to home page. {% endcomment %} diff --git a/assets/css/lesson.scss b/assets/css/lesson.scss index c982e529..3f8e758d 100644 --- a/assets/css/lesson.scss +++ b/assets/css/lesson.scss @@ -357,6 +357,11 @@ div.life-cycle { background: #d9edf7; } +.published { + color: #354711; + background: #effbd7; +} + // Remove border around spans of text within code blocks // that the highlighter (rouge) failed to recognize. pre.highlight span.err { diff --git a/assets/img/carpentrieslab.svg b/assets/img/carpentrieslab.svg new file mode 100644 index 00000000..018b270d --- /dev/null +++ b/assets/img/carpentrieslab.svg @@ -0,0 +1,249 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 69f1d0aa21941adab238c613555df6f8895e681b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Michonneau?= Date: Fri, 3 Sep 2021 05:08:24 -0400 Subject: [PATCH 087/113] remove contractions --- aio.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aio.md b/aio.md index 0ab72ea5..8d1806d2 100644 --- a/aio.md +++ b/aio.md @@ -3,8 +3,8 @@ permalink: /aio/index.html --- {% comment %} -As a maintainer, you don't need to edit this file. -If you notice that something doesn't work, please +As a maintainer, you do not need to edit this file. +If you notice that something does not work, please open an issue: https://github.com/carpentries/styles/issues/new {% endcomment %} From 1632471d0aa15cf5f9a8e15e9ecb4916f4fd1170 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Michonneau?= Date: Fri, 3 Sep 2021 05:09:00 -0400 Subject: [PATCH 088/113] remove contraction --- _includes/life_cycle.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_includes/life_cycle.html b/_includes/life_cycle.html index 72756b30..37a1259c 100644 --- a/_includes/life_cycle.html +++ b/_includes/life_cycle.html @@ -28,7 +28,7 @@ {% elsif site.life_cycle == "stable" %} {% comment %} -We don't do anything special unless this is a Carpentries Lab lesson +We do not do anything special unless this is a Carpentries Lab lesson {% endcomment %} {% if site.carpentry == "lab" %} From e867adfc86c7e51a7b800341b81b951b4ddccfad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Michonneau?= Date: Fri, 3 Sep 2021 05:11:04 -0400 Subject: [PATCH 089/113] remove contraction --- _includes/manual_episode_order.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_includes/manual_episode_order.html b/_includes/manual_episode_order.html index 79086271..9729ac50 100644 --- a/_includes/manual_episode_order.html +++ b/_includes/manual_episode_order.html @@ -3,7 +3,7 @@ GitHub Pages switches to Jekyll that supports it without any major hackery. Note, some logic will be required even when this transition happens - but it won't be as involved as what we have to do + but it will not be as involved as what we have to do in this file. To order lesson episodes or extras manually From 44241215a5d0aa197e267f6cefbc594607961d02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Michonneau?= Date: Wed, 8 Sep 2021 23:00:12 -0400 Subject: [PATCH 090/113] remove funding file to use organization's --- .github/FUNDING.yml | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index 2ee9d0ee..00000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,2 +0,0 @@ -github: [carpentries, swcarpentry, datacarpentry, librarycarpentry] -custom: ["https://carpentries.wedid.it"] From 811d30e8740561ff0cdcf4e665c02f6885c44c79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Michonneau?= Date: Thu, 9 Sep 2021 11:04:27 +0200 Subject: [PATCH 091/113] remove travis --- bin/boilerplate/.travis.yml | 57 ------------------------------------- bin/lesson_initialize.py | 1 - 2 files changed, 58 deletions(-) delete mode 100644 bin/boilerplate/.travis.yml diff --git a/bin/boilerplate/.travis.yml b/bin/boilerplate/.travis.yml deleted file mode 100644 index f6885e9a..00000000 --- a/bin/boilerplate/.travis.yml +++ /dev/null @@ -1,57 +0,0 @@ -# Travis CI is only used to check the lesson and is not involved in its deployment -dist: bionic -language: ruby -rvm: - - 2.7.1 - -branches: - only: - - gh-pages - - /.*/ - -cache: - apt: true - bundler: true - directories: - - /home/travis/.rvm/ - - $R_LIBS_USER - - $HOME/.cache/pip - -env: - global: - - NOKOGIRI_USE_SYSTEM_LIBRARIES=true # speeds up installation of html-proofer - - R_LIBS_USER=~/R/Library - - R_LIBS_SITE=/usr/local/lib/R/site-library:/usr/lib/R/site-library - - R_VERSION=4.0.2 - -before_install: - ## Install R + pandoc + dependencies - - sudo add-apt-repository -y "ppa:marutter/rrutter4.0" - - sudo add-apt-repository -y "ppa:c2d4u.team/c2d4u4.0+" - - sudo add-apt-repository -y "ppa:ubuntugis/ppa" - - sudo add-apt-repository -y "ppa:cran/travis" - - travis_apt_get_update - - sudo apt-get install -y --no-install-recommends build-essential gcc g++ libblas-dev liblapack-dev libncurses5-dev libreadline-dev libjpeg-dev libpcre3-dev libpng-dev zlib1g-dev libbz2-dev liblzma-dev libicu-dev cdbs qpdf texinfo libssh2-1-dev gfortran jq python3.5 python3-pip r-base - - export PATH=${TRAVIS_HOME}/R-bin/bin:$PATH - - export LD_LIBRARY_PATH=${TRAVIS_HOME}/R-bin/lib:$LD_LIBRARY_PATH - - sudo mkdir -p /usr/local/lib/R/site-library $R_LIBS_USER - - sudo chmod 2777 /usr/local/lib/R /usr/local/lib/R/site-library $R_LIBS_USER - - echo 'options(repos = c(CRAN = "https://packagemanager.rstudio.com/all/__linux__/bionic/latest"))' > ~/.Rprofile.site - - export R_PROFILE=~/.Rprofile.site - - curl -fLo /tmp/texlive.tar.gz https://github.com/jimhester/ubuntu-bin/releases/download/latest/texlive.tar.gz - - tar xzf /tmp/texlive.tar.gz -C ~ - - export PATH=${TRAVIS_HOME}/texlive/bin/x86_64-linux:$PATH - - tlmgr update --self - - curl -fLo /tmp/pandoc-2.2-1-amd64.deb https://github.com/jgm/pandoc/releases/download/2.2/pandoc-2.2-1-amd64.deb - - sudo dpkg -i /tmp/pandoc-2.2-1-amd64.deb - - sudo apt-get install -f - - rm /tmp/pandoc-2.2-1-amd64.deb - - Rscript -e "install.packages(setdiff(c('renv', 'rprojroot'), installed.packages()), loc = Sys.getenv('R_LIBS_USER')); update.packages(lib.loc = Sys.getenv('R_LIBS_USER'), ask = FALSE, checkBuilt = TRUE)" - - Rscript -e 'sessionInfo()' - ## Install python and dependencies - - python3 -m pip install --upgrade pip setuptools wheel - - python3 -m pip install pyyaml - -script: - - make lesson-check-all - - make --always-make site diff --git a/bin/lesson_initialize.py b/bin/lesson_initialize.py index 2f7b8e67..79ec05cf 100644 --- a/bin/lesson_initialize.py +++ b/bin/lesson_initialize.py @@ -6,7 +6,6 @@ import shutil BOILERPLATE = ( - '.travis.yml', 'AUTHORS', 'CITATION', 'CONTRIBUTING.md', From cf805b3633c4720aade19212b0e7201b83894be4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Michonneau?= Date: Wed, 15 Sep 2021 14:22:05 +0200 Subject: [PATCH 092/113] switch to using typeform for instructor training --- bin/boilerplate/_config.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bin/boilerplate/_config.yml b/bin/boilerplate/_config.yml index 242699cf..ed0df5ea 100644 --- a/bin/boilerplate/_config.yml +++ b/bin/boilerplate/_config.yml @@ -52,10 +52,10 @@ workshop_site: "https://carpentries.github.io/workshop-template" cc_by_human: "https://creativecommons.org/licenses/by/4.0/" # Surveys. -pre_survey: "https://carpentries.typeform.com/to/wi32rS?slug=" -post_survey: "https://carpentries.typeform.com/to/UgVdRQ?slug=" -instructor_pre_survey: "https://www.surveymonkey.com/r/instructor_training_pre_survey?workshop_id=" -instructor_post_survey: "https://www.surveymonkey.com/r/instructor_training_post_survey?workshop_id=" +pre_survey: "https://carpentries.typeform.com/to/wi32rS#slug=" +post_survey: "https://carpentries.typeform.com/to/UgVdRQ#slug=" +instructor_pre_survey: "https://carpentries.typeform.com/to/QVOarK#slug=" +instructor_post_survey: "https://carpentries.typeform.com/to/cjJ9UP#slug=" # Set to 'true' for instructor training websites only. instructor_training: false From 25a5b9f8c249fc3d34dce1572b39f2eb707fc444 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Michonneau?= Date: Wed, 6 Oct 2021 16:40:58 +0200 Subject: [PATCH 093/113] switch analytics to using matomo --- _includes/javascript.html | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/_includes/javascript.html b/_includes/javascript.html index 1c4877a6..3e1dc246 100644 --- a/_includes/javascript.html +++ b/_includes/javascript.html @@ -5,14 +5,27 @@ +{% if site.kind == "lesson" %} + + +{% endif %} {% if page.math %} From 2a9f189d04669ac12c3614b26bcc1b8c5f1d7b4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Michonneau?= Date: Wed, 6 Oct 2021 17:17:08 +0200 Subject: [PATCH 094/113] update text in License to reflect new trademarks --- LICENSE.md | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/LICENSE.md b/LICENSE.md index e6a3398d..98a94b28 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -23,13 +23,15 @@ license terms. Under the following terms: -* **Attribution**---You must give appropriate credit (mentioning that - your work is derived from work that is Copyright © Software - Carpentry and, where practical, linking to - http://software-carpentry.org/), provide a [link to the - license][cc-by-human], and indicate if changes were made. You may do - so in any reasonable manner, but not in any way that suggests the - licensor endorses you or your use. +* **Attribution**---You must give appropriate credit by: + - mentioning that your work is derived from work that is + Copyright © Software Carpentry, Data Carpentry, Library Carpentry, + or The Carpentries. + - where practical, linking to the respective lesson program website + (https://software-carpentry.org/, https://datacarpentry.org, https://librarycarpentry.org, or + https://carpentries.org), provide a [link to the license][cc-by-human] + - and indicate if changes were made. You may do so in any reasonable manner, but not in any way + that suggests the licensor endorses you or your use. **No additional restrictions**---You may not apply legal terms or technological measures that legally restrict others from doing @@ -73,8 +75,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ## Trademark -"Software Carpentry" and "Data Carpentry" and their respective logos -are registered trademarks of [Community Initiatives][CI]. +"The Carpentries", "Software Carpentry" and "Data Carpentry" and their respective logos are +registered trademarks of [Community Initiatives][CI]. [cc-by-human]: https://creativecommons.org/licenses/by/4.0/ [cc-by-legal]: https://creativecommons.org/licenses/by/4.0/legalcode From ca35a7cbedfc5b9b5bdfc097b3cd7b3e10731146 Mon Sep 17 00:00:00 2001 From: Ashwin Vishnu Date: Fri, 8 Oct 2021 22:12:19 +0200 Subject: [PATCH 095/113] Show solution while printing lessons Printing to paper or PDF via the browser would invoke the @media print CSS query. It is useful to show all solution while doing so --- assets/css/lesson.scss | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/assets/css/lesson.scss b/assets/css/lesson.scss index 3f8e758d..db6b6cf5 100644 --- a/assets/css/lesson.scss +++ b/assets/css/lesson.scss @@ -389,3 +389,13 @@ kbd { white-space: nowrap; font-style: normal; } + +//------------------------------------------ +// Show solution while printing (Ctrl + P) +// ----------------------------------------- + +@media print { + blockquote.solution > * { + display: unset !important; + } +} From 6f490499686e871d56d2aacdbdae5797385f1238 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Michonneau?= Date: Wed, 13 Oct 2021 01:36:07 -0400 Subject: [PATCH 096/113] add librarycarpentry.org to matomo settings --- _includes/javascript.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_includes/javascript.html b/_includes/javascript.html index 3e1dc246..0832664f 100644 --- a/_includes/javascript.html +++ b/_includes/javascript.html @@ -11,7 +11,7 @@ var _paq = window._paq = window._paq || []; /* tracker methods like "setCustomDimension" should be called before "trackPageView" */ _paq.push(["setDocumentTitle", document.domain + "/" + document.title]); - _paq.push(["setDomains", ["*.lessons.carpentries.org","*.datacarpentry.github.io","*.datacarpentry.org","*.librarycarpentry.github.io","*.swcarpentry.github.io"]]); + _paq.push(["setDomains", ["*.lessons.carpentries.org","*.datacarpentry.github.io","*.datacarpentry.org","*.librarycarpentry.github.io","*.librarycarpentry.org","*.swcarpentry.github.io"]]); _paq.push(["setDoNotTrack", true]); _paq.push(["disableCookies"]); _paq.push(['trackPageView']); From 85f39ffe86917809ebc6be89bdd7aba5d3691a3e Mon Sep 17 00:00:00 2001 From: Sarah Brown Date: Fri, 21 Jan 2022 14:07:28 -0500 Subject: [PATCH 097/113] change address --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 07aadca2..d3368998 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -4,7 +4,7 @@ Thanks for contributing! :heart: If this contribution is for instructor training, please email the link to this contribution to -checkout@carpentries.org so we can record your progress. You've completed your contribution +instructor.training@carpentries.org so we can record your progress. You've completed your contribution step for instructor checkout by submitting this contribution! Keep in mind that **lesson maintainers are volunteers** and it may take them some time to From 74d1c065a7dee2129bb550bdfd625d6797ef1b49 Mon Sep 17 00:00:00 2001 From: Renato Alves Date: Mon, 21 Feb 2022 16:11:45 +0100 Subject: [PATCH 098/113] Use a pixelated rendering instead of default blur Workaround to a CSS resize blur rendering problem affecting Google Chrome/Chromium when the resolution of the image is larger than the image view See https://stackoverflow.com/a/69156216 and https://github.com/carpentries-incubator/jekyll-pages-novice/issues/274 for additional context. --- assets/css/lesson.scss | 3 +++ 1 file changed, 3 insertions(+) diff --git a/assets/css/lesson.scss b/assets/css/lesson.scss index db6b6cf5..166604c3 100644 --- a/assets/css/lesson.scss +++ b/assets/css/lesson.scss @@ -321,6 +321,9 @@ span.fold-unfold { opacity: 0.5; } +img { + image-rendering: pixelated; +} p.image-with-shadow img, img.image-with-shadow { From 1322a2610f371eb87dd60b0473705ed1f14e5888 Mon Sep 17 00:00:00 2001 From: Renato Alves Date: Mon, 21 Feb 2022 18:29:57 +0100 Subject: [PATCH 099/113] Add comment to explain pixelated rendering CSS setting --- assets/css/lesson.scss | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/assets/css/lesson.scss b/assets/css/lesson.scss index 166604c3..c70fc713 100644 --- a/assets/css/lesson.scss +++ b/assets/css/lesson.scss @@ -321,6 +321,12 @@ span.fold-unfold { opacity: 0.5; } +/* + Force a pixelated rendering of images when original resolution is bigger than + the viewport to avoid a blurring effect that makes it difficult to read the image. + This issue affects primarily Chrome based browsers (as of 2021). + See https://github.com/carpentries/styles/pull/636 for the original report and related links +*/ img { image-rendering: pixelated; } From 106e502fe21fc37c0592560dcfd53996a9da7f0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Michonneau?= Date: Wed, 30 Mar 2022 19:01:57 +0200 Subject: [PATCH 100/113] add link to CoC --- bin/boilerplate/_config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/bin/boilerplate/_config.yml b/bin/boilerplate/_config.yml index ed0df5ea..3fab917c 100644 --- a/bin/boilerplate/_config.yml +++ b/bin/boilerplate/_config.yml @@ -34,6 +34,7 @@ repository: / email: "team@carpentries.org" # Sites. +coc: "https://docs.carpentries.org/topic_folders/policies/code-of-conduct.html" amy_site: "https://amy.carpentries.org/" carpentries_github: "https://github.com/carpentries" carpentries_pages: "https://carpentries.github.io" From 2a6d5851269d97de4f4ad4b1df3103d21ba5ad32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Michonneau?= Date: Mon, 4 Apr 2022 17:53:36 +0200 Subject: [PATCH 101/113] add new steps to transition lessons to Workbench --- _includes/check_transition_variables.html | 17 +++++++++ _includes/lesson_footer.html | 6 ++-- _includes/life_cycle.html | 44 +++++++++++++++++++++-- _includes/navbar.html | 8 ++--- _layouts/base.html | 6 +++- bin/boilerplate/_config.yml | 16 +++++++++ 6 files changed, 87 insertions(+), 10 deletions(-) create mode 100644 _includes/check_transition_variables.html diff --git a/_includes/check_transition_variables.html b/_includes/check_transition_variables.html new file mode 100644 index 00000000..9a1c045f --- /dev/null +++ b/_includes/check_transition_variables.html @@ -0,0 +1,17 @@ +{% assign date = include.need_transition_date %} + +{% unless site.transition_url %} +
    + you need to specify the variable transition_url + in _config.yml. +
    +{% endunless %} + +{% if date == "true" %} +{% unless site.transition_date %} +
    + you need to specify the variable transition_date + in _config.yml. +
    +{% endunless %} +{% endif %} diff --git a/_includes/lesson_footer.html b/_includes/lesson_footer.html index b0eb2991..979d1d7f 100644 --- a/_includes/lesson_footer.html +++ b/_includes/lesson_footer.html @@ -28,10 +28,10 @@ {% endif %} {% endif %} -{% endif %} diff --git a/_includes/navbar.html b/_includes/navbar.html index a8e3d596..12f75e86 100644 --- a/_includes/navbar.html +++ b/_includes/navbar.html @@ -94,12 +94,12 @@ {% comment %} Always show license. {% endcomment %}
  • License
  • - {% if page.source %} - {% if page.source == "Rmd" %} + {% if site.life_cycle contains 'transition_step' %} +
  • Improve this page
  • + {% elsif page.source == "Rmd" %}
  • Improve this page
  • - {% endif %} {% else %} -
  • Improve this page
  • +
  • Improve this page
  • {% endif %}