diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..da25b21 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,58 @@ +name: Build and Deploy + +on: + push: + branches: ["**"] + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +env: + FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true + +concurrency: + group: pages + cancel-in-progress: false + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install uv + uses: astral-sh/setup-uv@v5 + with: + enable-cache: true + + - name: Install dependencies + run: uv sync --frozen + + - name: Generate publications page + run: uv run python bin/create_pubs.py + + - name: Build site + run: uv run pelican content -s publishconf.py + + - name: Copy CNAME to output + run: cp CNAME output/ + + - name: Upload Pages artifact + uses: actions/upload-pages-artifact@v3 + with: + path: output/ + + deploy: + needs: build + if: github.ref == 'refs/heads/main' + runs-on: ubuntu-latest + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/.gitignore b/.gitignore index e43b0f9..7cb682c 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,7 @@ .DS_Store +.venv/ +output/ +__pycache__/ +*.pyc +cache/ +.pelican_cache/ diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/404.md b/404.md deleted file mode 100644 index 97b5953..0000000 --- a/404.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "404" -excerpt: "Page Not Found" -permalink: 404.html -indexing: false -sitemap: false ---- - -Sorry, but the page could not be found. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..e0f3601 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,138 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## What This Is + +Pelican static site for the MSU Computing Education Research Lab, hosted on GitHub Pages at `msucerl.org`. The Python environment is managed with `uv`. Pushing to `main` triggers automatic GitHub Pages build and deploy. + +## Local Development + +```bash +uv sync # install / sync dependencies +uv run pelican content -s pelicanconf.py # one-shot build → output/ +uv run pelican --listen --autoreload # build + live-reload dev server +``` + +For a production build (sets `SITEURL`, deletes `output/` first): + +```bash +uv run pelican content -s publishconf.py +``` + +## Site Architecture + +Static pages live under `content/pages/` and news posts under `content/posts/`, all as Markdown files with Pelican metadata headers (plain `Key: Value` lines, no YAML fences). The custom theme is in `themes/`. + +**Content pages:** + +- `content/pages/home.md` — homepage (uses `index.html` template with aside sidebar) +- `content/pages/people.md` — group roster (most commonly edited) +- `content/pages/projects.md` — active research projects +- `content/pages/pubs.md` — publications (**auto-generated; do not hand-edit**) +- `content/pages/curriculumdev.md` — curriculum development efforts +- `content/pages/outreach.md` — outreach activities + +**News & Perspectives posts:** + +- `content/posts/` — one Markdown file per post; served at `/news/{year}/{slug}/` + +**Theme (`themes/`):** + +- `templates/base.html` — shared header/footer, nav, canonical link +- `templates/index.html` — extends base; adds aside sidebar +- `templates/page.html` — extends base; standard content page +- `templates/news.html` — news index listing all posts +- `templates/article.html` — individual post page +- `static/css/style.css` — layout/typography; no hardcoded colors +- `static/css/theme-msu.css` / `static/css/theme-cerl.css` — color tokens per scheme + +**Config:** + +- `pelicanconf.py` — development config (no absolute URLs) +- `publishconf.py` — production config (sets `SITEURL`, deletes output) +- `MENUITEMS`, `SITE_DESCRIPTION`, and `COLOR_SCHEME` are all set in `pelicanconf.py` + +**Static files:** + +`STATIC_PATHS = ["assets"]` in `pelicanconf.py` tells Pelican to copy the entire `content/assets/` directory to `output/assets/`. Any images, PDFs, or other files placed under `content/assets/` will be served. Files outside that directory will not be included in the build. + +## Switching the Color Theme + +Set `COLOR_SCHEME` in `pelicanconf.py` before building (no need to touch `publishconf.py` — it inherits the value via `from pelicanconf import *`): + +```python +COLOR_SCHEME = "msu" # MSU brand colors (Spartan Green) +COLOR_SCHEME = "cerl" # CERL logo colors (teal, grey, black) +``` + +The value is baked into the theme CSS filename at build time — no JavaScript involved. + +## Pelican Page Metadata Format + +Each page starts with plain key-value metadata followed by a blank line: + +``` +Title: Page Title +Slug: url-slug + +Content here... +``` + +The homepage uses two extra keys: + +``` +Save_as: index.html +Template: index +``` + +## Adding or Updating People + +Edit `content/pages/people.md`. Sections are: Group Leaders → Group Members → External Collaborators → CERL Squirrel Alumni. Each entry follows this pattern: + +```markdown +#### Firstname Lastname (pronouns) +Firstname Lastname +Bio text here. +``` + +Place headshot images in `content/assets/img/`. The `` tag is optional — some members have no photo. + +## Writing News & Perspectives Posts + +Create a new Markdown file in `content/posts/`. The filename becomes the source file only — the URL is controlled by the `Slug` metadata field. + +``` +Title: Post Title Here +Date: 2026-01-15 +Author: Firstname Lastname +Slug: short-url-slug +Summary: One or two sentences shown on the news index page. + +Full post content starts here... +``` + +- **Title** — displayed as the page heading and linked from the news index +- **Date** — controls sort order and URL path (`/news/{year}/{slug}/`) +- **Author** — optional; shown in the byline on the index and post page +- **Slug** — required; determines the URL (use lowercase-with-hyphens) +- **Summary** — optional but recommended; shown as the excerpt on `/news/` + +Posts are automatically listed at `/news/` in reverse chronological order. No other configuration is needed. + +## Typogrify + +`TYPOGRIFY = True` is set in `pelicanconf.py`. Typogrify post-processes rendered HTML to improve typography (smart quotes, em-dashes, ampersand styling, etc.). This is generally transparent but has one known gotcha: **it will mangle double-quoted HTML attributes** if the attribute value contains characters it interprets as quotation marks. Avoid interpolating Pelican variables directly into double-quoted HTML attributes in templates — use `aria-hidden`, `tabindex`, or other attribute-based approaches instead of `aria-label` when the value contains dynamic text. + +## Publications Workflow + +Publications are generated from a BibTeX file — do not manually edit `content/pages/pubs.md`. + +1. Add new entries to `content/assets/bib/group_publications.bib` +2. Run from anywhere in the repo: + +```bash +uv run python bin/create_pubs.py +``` + +The script uses `pypandoc` (bundled binary, no system install needed) with `--citeproc` to render APA citations, groups them by year descending, and writes `content/pages/pubs.md` with Pelican metadata. `bin/create_pubs.sh` is kept as a reference for the old shell-based workflow. diff --git a/Gemfile b/Gemfile deleted file mode 100644 index e2ca6cd..0000000 --- a/Gemfile +++ /dev/null @@ -1,13 +0,0 @@ -source "https://rubygems.org" - -gem "jekyll", "~> 3.8" -gem "jekyll-sitemap", "~> 0.13" -gem "jekyll-mentions", "~> 1.2" -gem "jekyll-paginate", "~> 1.1" -gem "jekyll-seo-tag", "~> 2.3" -gem "jekyll-redirect-from", "~> 0.12" -gem "jekyll-default-layout", "~> 0.1" -gem "jekyll-feed", "~> 0.9" -gem "jemoji", "~> 0.9" -gem "jekyll-remote-theme", "~> 0.3" -gem "kramdown-parser-gfm" diff --git a/Gemfile.lock b/Gemfile.lock deleted file mode 100644 index a954eeb..0000000 --- a/Gemfile.lock +++ /dev/null @@ -1,162 +0,0 @@ -GEM - remote: https://rubygems.org/ - specs: - activesupport (8.0.2) - base64 - benchmark (>= 0.3) - bigdecimal - concurrent-ruby (~> 1.0, >= 1.3.1) - connection_pool (>= 2.2.5) - drb - i18n (>= 1.6, < 2) - logger (>= 1.4.2) - minitest (>= 5.1) - securerandom (>= 0.3) - tzinfo (~> 2.0, >= 2.0.5) - uri (>= 0.13.1) - addressable (2.8.7) - public_suffix (>= 2.0.2, < 7.0) - base64 (0.3.0) - benchmark (0.4.1) - bigdecimal (3.2.2) - colorator (1.1.0) - concurrent-ruby (1.3.5) - connection_pool (2.5.3) - csv (3.3.5) - drb (2.2.3) - em-websocket (0.5.3) - eventmachine (>= 0.12.9) - http_parser.rb (~> 0) - eventmachine (1.2.7) - ffi (1.17.2-aarch64-linux-gnu) - ffi (1.17.2-aarch64-linux-musl) - ffi (1.17.2-arm-linux-gnu) - ffi (1.17.2-arm-linux-musl) - ffi (1.17.2-arm64-darwin) - ffi (1.17.2-x86_64-darwin) - ffi (1.17.2-x86_64-linux-gnu) - ffi (1.17.2-x86_64-linux-musl) - forwardable-extended (2.6.0) - gemoji (4.1.0) - html-pipeline (2.14.3) - activesupport (>= 2) - nokogiri (>= 1.4) - http_parser.rb (0.8.0) - i18n (1.14.7) - concurrent-ruby (~> 1.0) - jekyll (3.10.0) - addressable (~> 2.4) - colorator (~> 1.0) - csv (~> 3.0) - em-websocket (~> 0.5) - i18n (>= 0.7, < 2) - jekyll-sass-converter (~> 1.0) - jekyll-watch (~> 2.0) - kramdown (>= 1.17, < 3) - liquid (~> 4.0) - mercenary (~> 0.3.3) - pathutil (~> 0.9) - rouge (>= 1.7, < 4) - safe_yaml (~> 1.0) - webrick (>= 1.0) - jekyll-default-layout (0.1.5) - jekyll (>= 3.0, < 5.0) - jekyll-feed (0.17.0) - jekyll (>= 3.7, < 5.0) - jekyll-mentions (1.6.0) - html-pipeline (~> 2.3) - jekyll (>= 3.7, < 5.0) - jekyll-paginate (1.1.0) - jekyll-redirect-from (0.16.0) - jekyll (>= 3.3, < 5.0) - jekyll-remote-theme (0.4.3) - addressable (~> 2.0) - jekyll (>= 3.5, < 5.0) - jekyll-sass-converter (>= 1.0, <= 3.0.0, != 2.0.0) - rubyzip (>= 1.3.0, < 3.0) - jekyll-sass-converter (1.5.2) - sass (~> 3.4) - jekyll-seo-tag (2.8.0) - jekyll (>= 3.8, < 5.0) - jekyll-sitemap (0.13.0) - jekyll (~> 3.3) - jekyll-watch (2.2.1) - listen (~> 3.0) - jemoji (0.13.0) - gemoji (>= 3, < 5) - html-pipeline (~> 2.2) - jekyll (>= 3.0, < 5.0) - kramdown (2.5.1) - rexml (>= 3.3.9) - kramdown-parser-gfm (1.1.0) - kramdown (~> 2.0) - liquid (4.0.4) - listen (3.9.0) - rb-fsevent (~> 0.10, >= 0.10.3) - rb-inotify (~> 0.9, >= 0.9.10) - logger (1.7.0) - mercenary (0.3.6) - minitest (5.25.5) - nokogiri (1.18.8-aarch64-linux-gnu) - racc (~> 1.4) - nokogiri (1.18.8-aarch64-linux-musl) - racc (~> 1.4) - nokogiri (1.18.8-arm-linux-gnu) - racc (~> 1.4) - nokogiri (1.18.8-arm-linux-musl) - racc (~> 1.4) - nokogiri (1.18.8-arm64-darwin) - racc (~> 1.4) - nokogiri (1.18.8-x86_64-darwin) - racc (~> 1.4) - nokogiri (1.18.8-x86_64-linux-gnu) - racc (~> 1.4) - nokogiri (1.18.8-x86_64-linux-musl) - racc (~> 1.4) - pathutil (0.16.2) - forwardable-extended (~> 2.6) - public_suffix (6.0.2) - racc (1.8.1) - rb-fsevent (0.11.2) - rb-inotify (0.11.1) - ffi (~> 1.0) - rexml (3.4.1) - rouge (3.30.0) - rubyzip (2.4.1) - safe_yaml (1.0.5) - sass (3.7.4) - sass-listen (~> 4.0.0) - sass-listen (4.0.0) - rb-fsevent (~> 0.9, >= 0.9.4) - rb-inotify (~> 0.9, >= 0.9.7) - securerandom (0.4.1) - tzinfo (2.0.6) - concurrent-ruby (~> 1.0) - uri (1.0.3) - webrick (1.9.1) - -PLATFORMS - aarch64-linux-gnu - aarch64-linux-musl - arm-linux-gnu - arm-linux-musl - arm64-darwin - x86_64-darwin - x86_64-linux-gnu - x86_64-linux-musl - -DEPENDENCIES - jekyll (~> 3.8) - jekyll-default-layout (~> 0.1) - jekyll-feed (~> 0.9) - jekyll-mentions (~> 1.2) - jekyll-paginate (~> 1.1) - jekyll-redirect-from (~> 0.12) - jekyll-remote-theme (~> 0.3) - jekyll-seo-tag (~> 2.3) - jekyll-sitemap (~> 0.13) - jemoji (~> 0.9) - kramdown-parser-gfm - -BUNDLED WITH - 2.6.9 diff --git a/README.md b/README.md index 00dcbfe..0d1565c 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,78 @@ -# Computational Education Research Lab at MSU +# Computing Education Research Lab at MSU -This is the website for the Computational Education Research Lab at Michigan State University. +This is the website for the Computing Education Research Lab at Michigan State University. It is built with [Pelican](https://getpelican.com) (a Python static site generator) and hosted on GitHub Pages. The Python environment is managed with [uv](https://docs.astral.sh/uv/). + +## Prerequisites + +Install `uv` if you don’t have it: + +```bash +curl -LsSf https://astral.sh/uv/install.sh | sh +``` + +Alternatively, `uv` can be installed via a package manager (e.g. `brew install uv` on macOS). See the [official installation docs](https://docs.astral.sh/uv/getting-started/installation/) for all options. ## Building the website locally -In order to work on the website locally so that you can check if things are rendering correctly before you push them to GitHub, you need to do a install few things. For mac users, this guide overall seems to be the most useful for getting things up and running: https://jekyllrb.com/docs/installation/macos/ (for other OS users, you can check the corresponding guide here: https://jekyllrb.com/docs/installation/). -But basically it boils down to making sure you have the following installed: +Clone the repo and install dependencies: + +```bash +git clone https://github.com/msu-cerl/msu-cerl.github.io +cd msu-cerl.github.io +uv sync +``` + +Then start a live-reloading local server: + +```bash +uv run pelican --listen --autoreload +``` + +The site will be available at `http://localhost:8000`. Changes to content files are picked up automatically. + +To do a one-shot build without serving: + +```bash +uv run pelican content -s pelicanconf.py +``` + +Pushing to `main` triggers an automatic GitHub Pages build and deploy (takes a few minutes). -* Ruby - * If you’re on a Mac, the easiest option is problem to install this with Homebrew. For GitHub pages, they need to be built with Ruby 2.7 (which is pretty out of date at this point), so you’ll want to do `brew install ruby@2.7`. Info on this issue is here: https://github.com/github/pages-gem/issues/752 - * Originally, I found these two resources are probably useful, but they recommend different ways of install ruby and will result in installing newer versions of Ruby, which won’t work. I’m keeping them for posterity: -https://www.ruby-lang.org/en/documentation/installation/#homebrew -https://jekyllrb.com/docs/installation/macos/ - * For other operating systems, it might be useful to start here (know that as a Mac user, I cannot attest to any of this as actually functioning!): https://jekyllrb.com/docs/installation/ or here: https://www.ruby-lang.org/en/documentation/installation/ +## Adding a news post -* Jekyll - * Should be able to install with `gem install jekyll` once you have Ruby installed and functional +Create a new Markdown file in `content/posts/` with the following metadata at the top: -* Bundler - * Should be able to do `gem install bundler` +``` +Title: Post Title Here +Date: 2026-01-15 +Author: Firstname Lastname +Slug: short-url-slug +Summary: One or two sentences shown on the news index page. -Once you get these things installed, you should be able to clone the repo (https://github.com/msu-cerl/msu-cerl.github.io). Then when you’re in that directory, just run to build it locally: +Full post content starts here... ``` -bundle install -bundle exec jekyll serve + +The post will appear automatically at `/news/` in reverse chronological order. The URL will be `/news/{year}/{slug}/`. + +## Updating publications + +Publications are generated from `content/assets/bib/group_publications.bib`. After adding new BibTeX entries, regenerate the publications page with: + +```bash +uv run python bin/create_pubs.py ``` -When you’re working in the repo and making changes to update the website, generally speaking you shouldn’t have to commit anything in the “_” folders (e.g. _site) to the GitHub repo because GitHub pages will build and deploy those files once you push new changes (though this process takes a few minutes). -Let me know if you run into issues when working with the website. If you have content you’d like to have featured on the website, but would rather not go down the path of updating the repo yourself, just send that along to me and I’ll get it up there. +Then commit the updated `content/pages/pubs.md` along with your bib changes. + +## GitHub Pages setup + +The site deploys automatically via GitHub Actions on every push to `main`. One-time setup required in the repository settings: + +1. Go to **Settings → Pages** +2. Under **Source**, select **GitHub Actions** (not "Deploy from a branch") + +After that, pushing to `main` triggers the workflow, which builds the Pelican site and deploys the output. You can also trigger a deploy manually from the **Actions** tab using the "Run workflow" button. + +## Questions or contributions + +Let me know if you run into issues when working with the website. If you have content you’d like to have featured on the website, but would rather not go down the path of updating the repo yourself, just send that along and I’ll get it up there. diff --git a/_config.yml b/_config.yml deleted file mode 100644 index 8cd466a..0000000 --- a/_config.yml +++ /dev/null @@ -1,68 +0,0 @@ -# Set theme -remote_theme: daviddarnes/alembic - -# File excludes -exclude: -- README.md -- Gemfile -- Gemfile.lock - -# Set plugins -plugins: -- jekyll-sitemap -- jekyll-mentions -- jekyll-paginate -- jekyll-seo-tag -- jekyll-redirect-from -- jekyll-default-layout -- jekyll-feed -- jemoji -- jekyll-remote-theme - -# Site settings -url: 'https://msu-cerl.github.io' -baseurl: '' -title: 'MSU CERL' -description: | - We're working to demystify how college students learn to do computational work. -
-
- Interested in joining us? -
- Send an email to dsilvia@msu.edu. -permalink: pretty -logo: "/assets/img/logo.png" - -# Pagination -paginate: 5 -paginate_path: /blog/page:num - -# Header nav -navigation_header: -- title: Home - url: / -- title: People - url: /people/ -- title: Projects - url: /projects/ -- title: Curriculum Development - url: /curriculumdev/ -- title: Publications - url: /pubs/ -- title: Outreach - url: /outreach/ - -# Footer nav -navigation_footer: -- title: Return to Home - url: . - -# Collections -collections: - posts: - title: Posts - output: true - description: "My thoughts and ideas" - feature_text: | - Welcome to my blog - feature_image: "https://picsum.photos/2560/600?image=866" diff --git a/_includes/figure.html b/_includes/figure.html deleted file mode 100644 index 18b3aba..0000000 --- a/_includes/figure.html +++ /dev/null @@ -1,4 +0,0 @@ -
- {{ include.alt | default: include.caption }} - {% if include.caption %}
{{ include.caption }}
{% endif %} -
diff --git a/_includes/site-aside.html b/_includes/site-aside.html deleted file mode 100644 index b97358c..0000000 --- a/_includes/site-aside.html +++ /dev/null @@ -1,23 +0,0 @@ - diff --git a/about.md b/about.md deleted file mode 100644 index 53c5930..0000000 --- a/about.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -layout: page -title: About this website ---- - -I'm not sure yet what this website is about, but I'm sure I'll work it out soon. diff --git a/bin/create_pubs.py b/bin/create_pubs.py new file mode 100644 index 0000000..fe88e2f --- /dev/null +++ b/bin/create_pubs.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python3 +"""Generate content/pages/pubs.md from the group bibliography. + +Replaces bin/create_pubs.sh — no system pandoc or gawk required. +Run from anywhere: uv run python bin/create_pubs.py +""" + +import re +from pathlib import Path + +import pypandoc + +REPO = Path(__file__).parent.parent +INFILE = REPO / "templates" / "pubs-template.md" +BIBFILE = REPO / "content" / "assets" / "bib" / "group_publications.bib" +CSLFILE = REPO / "templates" / "apa.csl" +OUTFILE = REPO / "content" / "pages" / "pubs.md" + + +def extract_year(paragraph: str) -> str: + m = re.search(r"\(([12][0-9]{3})[a-z]?\)", paragraph) or re.search( + r"\. ([12][0-9]{3})[a-z]?\.", paragraph + ) + return m.group(1) if m else "Unknown" + + +def main() -> None: + raw = pypandoc.convert_file( + str(INFILE), + "markdown_strict", + extra_args=[ + "--citeproc", + f"--bibliography={BIBFILE}", + f"--csl={CSLFILE}", + ], + ) + + paragraphs = [p.strip() for p in re.split(r"\n\n+", raw) if p.strip()] + + year_refs: dict[str, list[str]] = {} + for para in paragraphs: + year_refs.setdefault(extract_year(para), []).append(para) + + lines = ["Title: CERL Publications", "Slug: pubs", ""] + for year in sorted((y for y in year_refs if y != "Unknown"), reverse=True): + lines += [f"## {year}", ""] + for ref in year_refs[year]: + lines += [ref, ""] + + if "Unknown" in year_refs: + lines += ["## Unknown", ""] + for ref in year_refs["Unknown"]: + lines += [ref, ""] + + OUTFILE.write_text("\n".join(lines) + "\n", encoding="utf-8") + print(f"Wrote {len(paragraphs)} references to {OUTFILE}") + + +if __name__ == "__main__": + main() diff --git a/bin/create_pubs.sh b/bin/create_pubs.sh index 0de8cff..1405264 100755 --- a/bin/create_pubs.sh +++ b/bin/create_pubs.sh @@ -3,7 +3,7 @@ # Set output file TEMPLATE="../templates/yaml-metadata.template" INFILE="../templates/pubs-template.md" -OUTFILE="../pubs.md" +OUTFILE="../content/pages/pubs.md" # Run pandoc pandoc -t markdown_strict --citeproc -s --template="$TEMPLATE" -i "$INFILE" -o "$OUTFILE" @@ -11,12 +11,11 @@ pandoc -t markdown_strict --citeproc -s --template="$TEMPLATE" -i "$INFILE" -o " # Get today's date in YYYY-MM-DD format TODAY=$(date +%F) -# Create new front matter +# Create new front matter (Pelican metadata format) cat < frontmatter.tmp ---- -layout: page -title: CERL Publications ---- +Title: CERL Publications +Slug: pubs + EOF # Remove existing YAML front matter from pubs.md diff --git a/assets/bib/group_publications.bib b/content/assets/bib/group_publications.bib similarity index 100% rename from assets/bib/group_publications.bib rename to content/assets/bib/group_publications.bib diff --git a/assets/img/AlexReynolds.png b/content/assets/img/AlexReynolds.png similarity index 100% rename from assets/img/AlexReynolds.png rename to content/assets/img/AlexReynolds.png diff --git a/assets/img/Amanda_headshot.jpg b/content/assets/img/Amanda_headshot.jpg similarity index 100% rename from assets/img/Amanda_headshot.jpg rename to content/assets/img/Amanda_headshot.jpg diff --git a/assets/img/BrianOShea_headshot.jpg b/content/assets/img/BrianOShea_headshot.jpg similarity index 100% rename from assets/img/BrianOShea_headshot.jpg rename to content/assets/img/BrianOShea_headshot.jpg diff --git a/content/assets/img/CERL_squirrel_logo_v1.png b/content/assets/img/CERL_squirrel_logo_v1.png new file mode 100644 index 0000000..b8dbead Binary files /dev/null and b/content/assets/img/CERL_squirrel_logo_v1.png differ diff --git a/content/assets/img/CERL_squirrel_logo_v1_nobackground_blacktext.png b/content/assets/img/CERL_squirrel_logo_v1_nobackground_blacktext.png new file mode 100644 index 0000000..f6e4dcc Binary files /dev/null and b/content/assets/img/CERL_squirrel_logo_v1_nobackground_blacktext.png differ diff --git a/content/assets/img/CERL_squirrel_nobackground_whitetext_v2.png b/content/assets/img/CERL_squirrel_nobackground_whitetext_v2.png new file mode 100644 index 0000000..004ff7a Binary files /dev/null and b/content/assets/img/CERL_squirrel_nobackground_whitetext_v2.png differ diff --git a/assets/img/Cassie-headshot.jpg b/content/assets/img/Cassie-headshot.jpg similarity index 100% rename from assets/img/Cassie-headshot.jpg rename to content/assets/img/Cassie-headshot.jpg diff --git a/assets/img/CassieHeadshotCats.jpeg b/content/assets/img/CassieHeadshotCats.jpeg similarity index 100% rename from assets/img/CassieHeadshotCats.jpeg rename to content/assets/img/CassieHeadshotCats.jpeg diff --git a/assets/img/DannyCaballero_headshot.jpeg b/content/assets/img/DannyCaballero_headshot.jpeg similarity index 100% rename from assets/img/DannyCaballero_headshot.jpeg rename to content/assets/img/DannyCaballero_headshot.jpeg diff --git a/assets/img/DevinSilvia_headshot.jpg b/content/assets/img/DevinSilvia_headshot.jpg similarity index 100% rename from assets/img/DevinSilvia_headshot.jpg rename to content/assets/img/DevinSilvia_headshot.jpg diff --git a/assets/img/EmilyBolger_Headshot.jpg b/content/assets/img/EmilyBolger_Headshot.jpg similarity index 100% rename from assets/img/EmilyBolger_Headshot.jpg rename to content/assets/img/EmilyBolger_Headshot.jpg diff --git a/assets/img/EmilyBolger_Headshot2.jpg b/content/assets/img/EmilyBolger_Headshot2.jpg similarity index 100% rename from assets/img/EmilyBolger_Headshot2.jpg rename to content/assets/img/EmilyBolger_Headshot2.jpg diff --git a/assets/img/EmilyBolger_headshot3.jpg b/content/assets/img/EmilyBolger_headshot3.jpg similarity index 100% rename from assets/img/EmilyBolger_headshot3.jpg rename to content/assets/img/EmilyBolger_headshot3.jpg diff --git a/assets/img/Finzell_Headshot.png b/content/assets/img/Finzell_Headshot.png similarity index 100% rename from assets/img/Finzell_Headshot.png rename to content/assets/img/Finzell_Headshot.png diff --git a/assets/img/IMG_0221.jpg b/content/assets/img/IMG_0221.jpg similarity index 100% rename from assets/img/IMG_0221.jpg rename to content/assets/img/IMG_0221.jpg diff --git a/assets/img/IMG_0450.jpg b/content/assets/img/IMG_0450.jpg similarity index 100% rename from assets/img/IMG_0450.jpg rename to content/assets/img/IMG_0450.jpg diff --git a/assets/img/IMG_8218.jpg b/content/assets/img/IMG_8218.jpg similarity index 100% rename from assets/img/IMG_8218.jpg rename to content/assets/img/IMG_8218.jpg diff --git a/assets/img/Jacob_headshot.jpg b/content/assets/img/Jacob_headshot.jpg similarity index 100% rename from assets/img/Jacob_headshot.jpg rename to content/assets/img/Jacob_headshot.jpg diff --git a/assets/img/KrithiSachithanand_headshot.jpg b/content/assets/img/KrithiSachithanand_headshot.jpg similarity index 100% rename from assets/img/KrithiSachithanand_headshot.jpg rename to content/assets/img/KrithiSachithanand_headshot.jpg diff --git a/assets/img/KyleeSokacz.jpg b/content/assets/img/KyleeSokacz.jpg similarity index 100% rename from assets/img/KyleeSokacz.jpg rename to content/assets/img/KyleeSokacz.jpg diff --git a/assets/img/PattiHamerski_headshot.jpg b/content/assets/img/PattiHamerski_headshot.jpg similarity index 100% rename from assets/img/PattiHamerski_headshot.jpg rename to content/assets/img/PattiHamerski_headshot.jpg diff --git a/assets/img/RachelRoca_headshot.jpg b/content/assets/img/RachelRoca_headshot.jpg similarity index 100% rename from assets/img/RachelRoca_headshot.jpg rename to content/assets/img/RachelRoca_headshot.jpg diff --git a/assets/img/SarahCastle_headshot.jpeg b/content/assets/img/SarahCastle_headshot.jpeg similarity index 100% rename from assets/img/SarahCastle_headshot.jpeg rename to content/assets/img/SarahCastle_headshot.jpeg diff --git a/assets/img/SarahCastle_headshot.jpg b/content/assets/img/SarahCastle_headshot.jpg similarity index 100% rename from assets/img/SarahCastle_headshot.jpg rename to content/assets/img/SarahCastle_headshot.jpg diff --git a/assets/img/Sona_headshot.JPG b/content/assets/img/Sona_headshot.JPG similarity index 100% rename from assets/img/Sona_headshot.JPG rename to content/assets/img/Sona_headshot.JPG diff --git a/assets/img/TomFinzell_headshot.jpg b/content/assets/img/TomFinzell_headshot.jpg similarity index 100% rename from assets/img/TomFinzell_headshot.jpg rename to content/assets/img/TomFinzell_headshot.jpg diff --git a/assets/img/ajk.jpg b/content/assets/img/ajk.jpg similarity index 100% rename from assets/img/ajk.jpg rename to content/assets/img/ajk.jpg diff --git a/assets/img/alia.jpg b/content/assets/img/alia.jpg similarity index 100% rename from assets/img/alia.jpg rename to content/assets/img/alia.jpg diff --git a/assets/img/cassie_lem_headshot.JPG b/content/assets/img/cassie_lem_headshot.JPG similarity index 100% rename from assets/img/cassie_lem_headshot.JPG rename to content/assets/img/cassie_lem_headshot.JPG diff --git a/assets/img/dc.jpeg b/content/assets/img/dc.jpeg similarity index 100% rename from assets/img/dc.jpeg rename to content/assets/img/dc.jpeg diff --git a/assets/img/devin.jpg b/content/assets/img/devin.jpg similarity index 100% rename from assets/img/devin.jpg rename to content/assets/img/devin.jpg diff --git a/assets/img/foggy_michigan.jpg b/content/assets/img/foggy_michigan.jpg similarity index 100% rename from assets/img/foggy_michigan.jpg rename to content/assets/img/foggy_michigan.jpg diff --git a/assets/img/frisbie_headshot.jpg b/content/assets/img/frisbie_headshot.jpg similarity index 100% rename from assets/img/frisbie_headshot.jpg rename to content/assets/img/frisbie_headshot.jpg diff --git a/assets/img/headshot_reduced.jpg b/content/assets/img/headshot_reduced.jpg similarity index 100% rename from assets/img/headshot_reduced.jpg rename to content/assets/img/headshot_reduced.jpg diff --git a/assets/img/justin_gambrell_headshot.jpeg b/content/assets/img/justin_gambrell_headshot.jpeg similarity index 100% rename from assets/img/justin_gambrell_headshot.jpeg rename to content/assets/img/justin_gambrell_headshot.jpeg diff --git a/assets/img/logo.png b/content/assets/img/logo.png similarity index 100% rename from assets/img/logo.png rename to content/assets/img/logo.png diff --git a/assets/img/oshea-headshot.jpg b/content/assets/img/oshea-headshot.jpg similarity index 100% rename from assets/img/oshea-headshot.jpg rename to content/assets/img/oshea-headshot.jpg diff --git a/assets/img/pdp2020_headshot_frisbie.jpg b/content/assets/img/pdp2020_headshot_frisbie.jpg similarity index 100% rename from assets/img/pdp2020_headshot_frisbie.jpg rename to content/assets/img/pdp2020_headshot_frisbie.jpg diff --git a/assets/img/projects/CompareDegreeTies.png b/content/assets/img/projects/CompareDegreeTies.png similarity index 100% rename from assets/img/projects/CompareDegreeTies.png rename to content/assets/img/projects/CompareDegreeTies.png diff --git a/assets/img/tor.jpg b/content/assets/img/tor.jpg similarity index 100% rename from assets/img/tor.jpg rename to content/assets/img/tor.jpg diff --git a/assets/styles.scss b/content/assets/styles.scss similarity index 100% rename from assets/styles.scss rename to content/assets/styles.scss diff --git a/curriculumdev.md b/content/pages/curriculumdev.md similarity index 70% rename from curriculumdev.md rename to content/pages/curriculumdev.md index 31f0021..0f724e3 100644 --- a/curriculumdev.md +++ b/content/pages/curriculumdev.md @@ -1,19 +1,15 @@ ---- -layout: page -title: Curriculum Development Efforts ---- ---- +Title: Curriculum Development Efforts +Slug: curriculumdev -#### Adding Visual Aids to CMSE 201 -##### Folks Involved: E. Bolger (lead), D. Silvia +## Adding Visual Aids to CMSE 201 +### Folks Involved: E. Bolger (lead), D. Silvia For her Mentored Teaching Project as a part of the [Certificate of College Teaching](https://grad.msu.edu/cctp), Emily integrated visual aids in the CMSE 201 course materials to help students strengthen their understanding of coding practices like lists, data frames, and two-dimensional arrays, particularly in relation to indexing with those tools. The purpose of the visual aids was to help students conceptualize the structure of the object as well as walk through examples that showed information retrieval from these objects. We also embedded guided questions for students to practice explaining their coding choices and implementations. Specifically, we were looking to study how students think about and explain code using descriptive language to their instructors, fellow coding classmates, and non-coders. To assess the modifications implemented in the CMSE 201 curriculum, we used three methods: bi-semesterly survey, in-class student observations, and class assignment observations. While we struggled to encourage students to respond to the written critical thinking questions, we noticed that the students asked more targeted, thoughtful questions and referred to the visual aids frequently throughout the course. -#### Ethical Impact of STEM Professionals on the Holocaust and Beyond -##### Folks Involved: R. Roca, E. Bolger, R. Frisbie, V. Piercey +## Ethical Impact of STEM Professionals on the Holocaust and Beyond +### Folks Involved: R. Roca, E. Bolger, R. Frisbie, V. Piercey -Roca, Bolger, and Frisbie have begun a [collaboration](https://www.ferris.edu/news/archive/2025/may/ferris-state-stem-holocaust-partnership.htm) with professor and Honors Program Director Piercey, historians at Ferris State University, and the Zekelman Holocaust Center in Detroit. Honors students from CMSE at MSU and the Math Department at FSU will have the opportunity to study the ethical impact of STEM innovation in the Holocaust. Students will research a STEM professional involved in the Holocaust, visit the Zekelman Holocaust center, discuss their research with students from the other school, and present their findings at both universities. We anticipate this timely experience to be highly impactful for our students, giving them the space to grapple with their impact as a future STEM professional by considering the past. +Roca, Bolger, and Frisbie have begun a [collaboration](https://www.ferris.edu/news/archive/2025/may/ferris-state-stem-holocaust-partnership.htm) with professor and Honors Program Director Piercey, historians at Ferris State University, and the Zekelman Holocaust Center in Detroit. Honors students from CMSE at MSU and the Math Department at FSU will have the opportunity to study the ethical impact of STEM innovation in the Holocaust. Students will research a STEM professional involved in the Holocaust, visit the Zekelman Holocaust center, discuss their research with students from the other school, and present their findings at both universities. We anticipate this timely experience to be highly impactful for our students, giving them the space to grapple with their impact as a future STEM professional by considering the past. - -#### Data Literacy and Ethics in CMSE 201 -##### Folks Involved: Emily Bolger and Rachel Roca +## Data Literacy and Ethics in CMSE 201 +### Folks Involved: Emily Bolger and Rachel Roca Following a class assignment, Rachel and Emily developed a research backed CMSE 201 assignment to help students learn about bias that's inherent in data and the implications it can have on hiring practices. Students interact with the simulation ["Survival of the Best Fit"](https://www.survivalofthebestfit.com/) developed by Gabor Csapo, Jihyun Kim, Miha Klasinc, and Alia ElKattan and take a deeper dive into the data creation. This assignment explores the nuances of impact vs. intent of using AI, interrogates how bias shows up in data and algorithms, and celebrates students' abilities to read and interact with outside code while supporting their self-efficacy. Their materials can be found [here](https://github.com/RachelRoca/DataLiteracyEducationTask/). diff --git a/content/pages/home.md b/content/pages/home.md new file mode 100644 index 0000000..cf718d3 --- /dev/null +++ b/content/pages/home.md @@ -0,0 +1,10 @@ +Title: Computing Education Research Lab @ MSU +Slug: home +Save_as: index.html +Template: index + +The Computing Education Research Lab (CERL) at [Michigan State University](https://msu.edu) studies how undergraduate students learn to use computation as a tool for doing science — and what shapes their experience along the way. Our work sits at the intersection of computing, disciplinary learning, and student affect, with a particular focus on students who encounter computation for the first time outside of traditional computer science courses. + +Our research draws on a range of methods, including qualitative interviews, social network analysis, natural language processing, and assessment development, to investigate questions about how students think, problem-solve, and develop confidence with computational tools. We also work directly on curriculum design, bringing research findings back into the classroom to improve student outcomes and promote more equitable and inclusive learning environments. + +CERL is housed in the [Department of Computational Mathematics, Science and Engineering](https://cmse.msu.edu), but is an interdisciplinary collaboration spanning the College of Natural Science, the College of Engineering, and the College of Education at MSU. The lab includes faculty, graduate students, and undergraduates working together on projects that range from foundational questions about student cognition to applied curriculum development and community outreach. diff --git a/outreach.md b/content/pages/outreach.md similarity index 77% rename from outreach.md rename to content/pages/outreach.md index 50372d0..f2316ff 100644 --- a/outreach.md +++ b/content/pages/outreach.md @@ -1,10 +1,8 @@ ---- -layout: page -title: Past and Present Outreach Efforts ---- ---- -### Current Outreach +Title: Past and Present Outreach Efforts +Slug: outreach -#### Blurred Realities Exhibit Workshop - MSU Museum -##### Folks Involved: Rachel Roca, Emily Bolger, Sona Chitchyan, Dawson Kinsman, Cassie Lem +## Current Outreach + +### Blurred Realities Exhibit Workshop - MSU Museum +#### Folks Involved: Rachel Roca, Emily Bolger, Sona Chitchyan, Dawson Kinsman, Cassie Lem We will be hosting a workshop as part of the MSU Museum's upcoming exhibition, Blurred Realities, in January 2026. Our workshop, tentatively titled _AI and the Art of Distinguishing Reality: Understanding the Power of Data Visualizations in a Digital World_, will give audience members the opportunity to explore the differentiation between fabrication and factual information, specifically in the context of GenerativeAI. We will present claims to visitors that highlight different data-centered aspects of the MSU community - some of which will be rooted in fact and others will be fabricated using GenAI. The workshop will also aim to provide actionable strategies to guide audience members through using evidence through data and visualizations to prove or disprove claims presented. diff --git a/people.md b/content/pages/people.md similarity index 51% rename from people.md rename to content/pages/people.md index 447d1e9..01aac3c 100644 --- a/people.md +++ b/content/pages/people.md @@ -1,116 +1,113 @@ ---- -layout: page -title: The awesome folks in CERL ---- ---- -### Group Leaders - -#### [Danny Caballero](https://dannycab.github.io/) (he/him) -{% include figure.html image="/assets/img/DannyCaballero_headshot.jpeg" position="left" width="120px" %} +Title: The awesome folks in CERL +Slug: people + +## Group Leaders + +### [Danny Caballero](https://dannycab.github.io/) (he/him) +Danny Caballero Danny is an associate professor in the [Department of Physics and Astronomy](https://pa.msu.edu) and the [Department of Computational Mathematics, Science and Engineering](https://cmse.msu.edu). He holds the Lappan-Phillips Chair of Physics Education, co-directs the [Physics Education Research Lab](https://perl.natsci.msu.edu), and is the principal investigator of the [Learning Machines Lab](https://learningmachineslab.github.io). He earned his Bachelor's degree in physics from the [University of Texas at Austin](https://ph.utexas.edu), and his Master's and PhD in physics from the [Georgia Institute of Technology](https://physics.gatech.edu). Danny worked as a Science Teaching Postdoctoral Fellow at the [University of Colorado Boulder](https://www.colorado.edu/physics) before joining the faculty at Michigan State. His research focuses on computational education and the use of data science to address questions in STEM education. In his free time, he bikes, skateboards, and barbecues. -#### Rachel Frisbie (she/her) -{% include figure.html image="/assets/img/frisbie_headshot.jpg" position="left" width="120px" %} +### Rachel Frisbie (she/her) +Rachel Frisbie -Rachel is an assistant professor in the Computational Education Research Lab (CERL). She earned her Bachelor’s degree in Physics from The University of Scranton, and she earned her PhD in Astrophysics from Michigan State University in 2020. Since 2020, she has been teaching courses in CMSE and engaging in computational science education research with the Computational Education Research Lab (CERL) at MSU. Her current research interests include qualitative approaches to exploring how students problem solve using computational concepts as they progress through their education as well as how those findings can be applied to courses like the ones we teach in CMSE to improve student outcomes. She also is interested in investigating the impact of weekly group and individual feedback on students’ experiences in class. Elsewhere on campus, Rachel is a [STEM Teaching and Learning Fellow](https://3dl4us.org/) and helps run [Astronomy on Tap - Lansing](https://www.facebook.com/AoTLansing). Outside of work, Rachel enjoys exploring with her spouse, toddler, and dog, playing oboe and ukulele, powerlifting, and tin smithing. +Rachel is an assistant professor in the Computational Education Research Lab (CERL). She earned her Bachelor's degree in Physics from The University of Scranton, and she earned her PhD in Astrophysics from Michigan State University in 2020. Since 2020, she has been teaching courses in CMSE and engaging in computational science education research with the Computational Education Research Lab (CERL) at MSU. Her current research interests include qualitative approaches to exploring how students problem solve using computational concepts as they progress through their education as well as how those findings can be applied to courses like the ones we teach in CMSE to improve student outcomes. She also is interested in investigating the impact of weekly group and individual feedback on students' experiences in class. Elsewhere on campus, Rachel is a [STEM Teaching and Learning Fellow](https://3dl4us.org/) and helps run [Astronomy on Tap - Lansing](https://www.facebook.com/AoTLansing). Outside of work, Rachel enjoys exploring with her spouse, toddler, and dog, playing oboe and ukulele, powerlifting, and tin smithing. -#### Brian O'Shea (he/him) -{% include figure.html image="/assets/img/BrianOShea_headshot.jpg" position="left" width="120px" %} -Brian is a professor in the [Department of Computational Mathematics, Science and Engineering](https://cmse.msu.edu) and the [Department of Physics and Astronomy](https://pa.msu.edu). He is also a member of the [National Superconducting Cyclotron Laboratory](https://nscl.msu.edu/) and the current Director of MSU's [Institute for Cyber-Enabled Research](https://icer.msu.edu/). Prior to joining MSU, he received his PhD in physics from the [University of Illinois at Urbana-Champaign](https://physics.illinois.edu/) and was a postdoc at [Los Alamos National Laboratory](https://lanl.gov/) in the Theoretical Astrophysics Group and Applied Physics Division. His research interests include galaxy formation, turbulence, plasma physics, and computational science education. In his free time, he enjoys cooking, gardening, biking, and hiking. His website can be found [here](https://web.pa.msu.edu/people/osheabr/). +### Brian O'Shea (he/him) +Brian O'Shea +Brian is a professor in the [Department of Computational Mathematics, Science and Engineering](https://cmse.msu.edu) and the [Department of Physics and Astronomy](https://pa.msu.edu). He is also a member of the [National Superconducting Cyclotron Laboratory](https://nscl.msu.edu/) and the current Director of MSU's [Institute for Cyber-Enabled Research](https://icer.msu.edu/). Prior to joining MSU, he received his PhD in physics from the [University of Illinois at Urbana-Champaign](https://physics.illinois.edu/) and was a postdoc at [Los Alamos National Laboratory](https://lanl.gov/) in the Theoretical Astrophysics Group and Applied Physics Division. His research interests include galaxy formation, turbulence, plasma physics, and computational science education. In his free time, he enjoys cooking, gardening, biking, and hiking. His website can be found [here](https://web.pa.msu.edu/people/osheabr/). -#### [Devin Silvia](www.devinsilvia.com) (he/him) -{% include figure.html image="/assets/img/DevinSilvia_headshot.jpg" position="left" width="120px" %} +### [Devin Silvia](https://www.devinsilvia.com) (he/him) +Devin Silvia Devin is the Director of Undergraduate Studies and a teaching specialist in the [Department of Computational Mathematics, Science and Engineering](https://cmse.msu.edu). He received his PhD in [Astrophysical and Planetary Sciences](https://www.colorado.edu/aps/) from the [University of Colorado](https://www.colorado.edu) where he worked as a computational astrophysicist running simulations aimed at understanding various facets of chemical evolution in the universe. He then worked as a National Science Foundation Astronomy and Astrophysics postdoctoral fellow at MSU before joining the ranks of the CMSE faculty in 2017. In addition to his computational astrophysics research, Devin is passionate about STEM education and creating more equitable and inclusive STEM classrooms. When he's not working, he enjoys brewing beer, roasting coffee, and running all over the greater Lansing area. -#### [Aman Yadav](https://www.amanyadav.org/) (he/him) -{% include figure.html image="/assets/img/IMG_0450.jpg" position="left" width="120px" %} +### [Aman Yadav](https://www.amanyadav.org/) (he/him) +Aman Yadav Aman Yadav is the Lappan-Phillips Professor of Computing Education in the College of Education and College of Natural Science at Michigan State University with extensive experience in research, evaluation, and teacher professional development. His research and teaching focus on supporting educators to understand, apply, and critically evaluate the use of computing in K-12 classrooms. He leads several projects that design, implement, and assess how professional learning experiences can support teachers to bring computational tools and practices to support their disciplinary teaching. His co-edited book, [Computational Thinking in Education: A Pedagogical Perspective](https://www.routledge.com/Computational-Thinking-in-Education-A-Pedagogical-Perspective/Yadav-Berthelsen/p/book/9780367610357) tackles how to integrate computational thinking, coding, and subject matter in relevant and meaningful ways. His website is [here](https://www.amanyadav.org/). -### Group Members +## Group Members -#### Justin Gambrell (he/him) -{% include figure.html image="/assets/img/justin_gambrell_headshot.jpeg" position="left" width="120px" %} -Justin is a fixed-term assistant professor in CMSE and is a member of CERL. Justin earned his Bachelor’s degree in Physics from Michigan State University along with a minor in Mathematics in 2018. In 2024 he earned his PhD in Physics from Drexel University specializing in Physics Education Research. Justin is currently teaching CMSE 201 and 202. His research has focused on assessment development of computational thinking in introductory physics. Justin’s current research interests are in expanding assessment development in terms of exploring student affect, and examining differences in computational thinking based on the computational environment used. In his free time he enjoys playing video games, catching up on a massive watch list, and propagating house plants. +### Justin Gambrell (he/him) +Justin Gambrell +Justin is a fixed-term assistant professor in CMSE and is a member of CERL. Justin earned his Bachelor's degree in Physics from Michigan State University along with a minor in Mathematics in 2018. In 2024 he earned his PhD in Physics from Drexel University specializing in Physics Education Research. Justin is currently teaching CMSE 201 and 202. His research has focused on assessment development of computational thinking in introductory physics. Justin's current research interests are in expanding assessment development in terms of exploring student affect, and examining differences in computational thinking based on the computational environment used. In his free time he enjoys playing video games, catching up on a massive watch list, and propagating house plants. -#### Emily Bolger (she/her) -{% include figure.html image="/assets/img/EmilyBolger_headshot3.jpg" position="left" width="120px" %} Emily is a PhD student in the Computational Mathematics, Science and Engineering (CMSE) Department. She earned her bachelor's degree in Mathematics from Moravian College. Her current research uses computational tools, specifically Social Network Analysis and Natural Language Processing, to analyze education-related data. Her most recent project involves using Natural Language Processing to analyze literature published on change strategies for improving undergraduate STEM instruction. The project is multi-method synthesis in collaboration with four other research institutions. In addition to research, she has been a Teaching Assistant for CMSE 201 and CMSE 381. In her free time, she enjoys reading, crocheting, and dancing. Her website can be found [here](https://egbolger.github.io/). +### Emily Bolger (she/her) +Emily Bolger +Emily is a PhD student in the Computational Mathematics, Science and Engineering (CMSE) Department. She earned her bachelor's degree in Mathematics from Moravian College. Her current research uses computational tools, specifically Social Network Analysis and Natural Language Processing, to analyze education-related data. Her most recent project involves using Natural Language Processing to analyze literature published on change strategies for improving undergraduate STEM instruction. The project is multi-method synthesis in collaboration with four other research institutions. In addition to research, she has been a Teaching Assistant for CMSE 201 and CMSE 381. In her free time, she enjoys reading, crocheting, and dancing. Her website can be found [here](https://egbolger.github.io/). -#### Sona Chitchyan (she/they) -{% include figure.html image="/assets/img/Sona_headshot.JPG" position="left" width="120px" %} -Sona is a PhD student at CMSE working in CERL, focusing on studying the process of teaching computation in the context of astrophysics. In 2024-2025, Sona created an interactive homework assignment for CMSE 202, exploring how usage of astronomy context in agent-based modeling affects student learning. Currently, Sona is working on Feedback Engagement and Analysis in the asSessmenTs (FEAST) project, exploring what actionable feedback looks like in an introductory computing course and how the process of providing feedback can be improved. They enjoy playing racquetball, researching coffee, baking bread, and watching TV shows in their free time. Sona is also interested in contributing to open-source codes in astrophysics. +### Sona Chitchyan (she/they) +Sona Chitchyan +Sona is a PhD student at CMSE working in CERL, focusing on studying the process of teaching computation in the context of astrophysics. In 2024-2025, Sona created an interactive homework assignment for CMSE 202, exploring how usage of astronomy context in agent-based modeling affects student learning. Currently, Sona is working on Feedback Engagement and Analysis in the asSessmenTs (FEAST) project, exploring what actionable feedback looks like in an introductory computing course and how the process of providing feedback can be improved. They enjoy playing racquetball, researching coffee, baking bread, and watching TV shows in their free time. Sona is also interested in contributing to open-source codes in astrophysics. -#### Ishita -{% include figure.html image="/assets/img/IMG_0221.jpg" position="left" width="120px" %} +### Ishita +Ishita Ishita is an undergraduate student at Michigan State University, majoring in Computational Data Science and Statistics. She is involved in educational research under Rachel Roca, focusing on student identity in data science classrooms. In her free time, Ishita enjoys reading books, playing chess and taking piano lessons. -#### [Dawson Kinsman](https://dawson-kinsman.netlify.app) (she/her) +### [Dawson Kinsman](https://dawson-kinsman.netlify.app) (she/her) Dawson is a PhD student in CMSE. She received her undergraduate degree in Mathematics and Applied Statistics from the University of Michigan-Dearborn, where she also received master's degree in Applied and Computational Mathematics. Her research interests include applied statistical and machine learning methods, especially with social science and education data. Prior to joining MSU, Dawson's projects focused on applying statistical and topological data analysis methods to Shotspotter and police shooting data from Detroit, Michigan. Outside of research, Dawson enjoys rock climbing, hiking, discovering new music, and hanging out with friends and family. -#### Anthony Kosinski (he/him) -{% include figure.html image="/assets/img/ajk.jpg" position="left" width="120px" %} +### Anthony Kosinski (he/him) +Anthony Kosinski Anthony is an undergraduate student at Michigan State University, studying Computational Data Science with a minor in German. He conducts research under Emily Bolger, with a focus on using computational methods to analyze STEM research papers. In his free time, Anthony enjoys taking long bike rides, learning about history, and playing the accordion. -#### Cassie Lem (she/her) -{% include figure.html image="/assets/img/CassieHeadshotCats.jpeg" position="left" width="120px" %} +### Cassie Lem (she/her) +Cassie Lem Cassie is a PhD student in CMSE. She earned a B.S. in applied math from UC Santa Barbara in 2021. Cassie is currently working on a project studying the impacts of course transformations on undergraduate students in NatSci departments. She has previously been a graduate assistant with [Knowledge Commons](https://hcommons.org/) at MSU. In her free time, Cassie enjoys reading, swing dancing, playing board/card games, and spending time with friends and family. -#### Maddy Nomer (she/her) -Maddy is currently a masters student in the MSDS program. She earned her bachelor's degree in Psychology with a minor in Social Science Quantitative Data Analysis. Throughout her time at MSU, Maddy has worked as an undergraduate learning assistant and a teaching assistant for CMSE 201. Prior to joining CERL, Maddy’s research focused on sleep, specifically how melatonin impacted sleep and cognition in healthy young adults. In her free time, Maddy enjoys playing with her cat and reading. +### Maddy Nomer (she/her) +Maddy is currently a masters student in the MSDS program. She earned her bachelor's degree in Psychology with a minor in Social Science Quantitative Data Analysis. Throughout her time at MSU, Maddy has worked as an undergraduate learning assistant and a teaching assistant for CMSE 201. Prior to joining CERL, Maddy's research focused on sleep, specifically how melatonin impacted sleep and cognition in healthy young adults. In her free time, Maddy enjoys playing with her cat and reading. -#### Alex Reynolds (she/they) -{% include figure.html image="/assets/img/AlexReynolds.png" position="left" width="120px" %} -Alex Reynolds is a graduate student in the [Physics Education Research Lab](https://perl.natsci.msu.edu) and CERL, and their current research interests are around supporting integration of a variation in computing practices in the physics classroom through the PICUP project. They also research accessibility in physics spaces, including experiences of students with ADHD in physics group work. In the past, they have researched student’s mathematical reasoning in online labs and developed curriculum around teaching coding in physics labs. Alex received a Bachelor’s in Comprehensive and Teaching Physics in 2023 from the University of Washington and taught high school conceptual and AP physics before coming to graduate school at MSU. In their free time, Alex participates in many yarn-based crafts, plays board games and TTRPGs, and hikes. +### Alex Reynolds (she/they) +Alex Reynolds +Alex Reynolds is a graduate student in the [Physics Education Research Lab](https://perl.natsci.msu.edu) and CERL, and their current research interests are around supporting integration of a variation in computing practices in the physics classroom through the PICUP project. They also research accessibility in physics spaces, including experiences of students with ADHD in physics group work. In the past, they have researched student's mathematical reasoning in online labs and developed curriculum around teaching coding in physics labs. Alex received a Bachelor's in Comprehensive and Teaching Physics in 2023 from the University of Washington and taught high school conceptual and AP physics before coming to graduate school at MSU. In their free time, Alex participates in many yarn-based crafts, plays board games and TTRPGs, and hikes. -#### Rachel Roca (she/they) -{% include figure.html image="/assets/img/RachelRoca_headshot.jpg" position="left" width="120px" %} +### Rachel Roca (she/they) +Rachel Roca [Rachel](https://sites.google.com/msu.edu/rachel-e-roca/home) is a PhD student in CMSE. She earned her bachelor's degree in mathematics from Manhattan College in 2021, where she also minored in computer science and Spanish. Their research interests are interdisciplinary and span three areas: topological data analysis (the study of the shape of data), computational education, and humanistic mathematics for social good. Currently, their interests focus on studying identity and ethics in undergraduate courses. Rachel has TAed and developed assignments for CMSE 201, CMSE 381, and CMSE 402, and this past summer, she was an instructor of record for CMSE 201. Outside of research, Rachel is involved in various DEI and outreach programs and is the president of the MSU State Swing Society. In her free time, Rachel loves to read, go to the beach, travel, and have good food and drink with good people. ### Kylee Sokacz (she/her) -{% include figure.html image="/assets/img/KyleeSokacz.jpg" position="left" width="120px" %} -Kylee is an undergraduate student at Michigan State University, studying Mathematics and Data Science. She works as an Undergraduate Learning Assistant in CMSE 201 and conducts educational research under Rachel Frisbie, focusing on the interactions and utilization of AI in the CMSE 201 classroom. In her free time, Kylee enjoys playing piano, fostering cats, and spending time with her friends. +Kylee Sokacz +Kylee is an undergraduate student at Michigan State University, studying Mathematics and Data Science. She works as an Undergraduate Learning Assistant in CMSE 201 and conducts educational research under Rachel Frisbie, focusing on the interactions and utilization of AI in the CMSE 201 classroom. In her free time, Kylee enjoys playing piano, fostering cats, and spending time with her friends. -### External Collaborators +## External Collaborators -#### Tor Ole Odden (he/him) -{% include figure.html image="/assets/img/tor.jpg" position="left" width="120px" %} -Tor is a postdoc at the [University of Oslo, Norway](https://www.uio.no/english/), where he studies how computation can be used to improve physics teaching and how machine learning methods can be applied to science education research. He holds a bachelor’s degree in physics from [St. Olaf College](https://wp.stolaf.edu/), a master’s in physics from the [University of Wisconsin-Madison](https://www.wisc.edu/), and a PhD in physics education also from the University of Wisconsin-Madison. In his spare time Tor is an active fiddle player, cross-country skier, wood-carver, and graphic novel enthusiast. +### Tor Ole Odden (he/him) +Tor Ole Odden +Tor is a postdoc at the [University of Oslo, Norway](https://www.uio.no/english/), where he studies how computation can be used to improve physics teaching and how machine learning methods can be applied to science education research. He holds a bachelor's degree in physics from [St. Olaf College](https://wp.stolaf.edu/), a master's in physics from the [University of Wisconsin-Madison](https://www.wisc.edu/), and a PhD in physics education also from the University of Wisconsin-Madison. In his spare time Tor is an active fiddle player, cross-country skier, wood-carver, and graphic novel enthusiast. -### CERL Squirrel Alumni! +## CERL Squirrel Alumni! -#### [Alia Valentine](https://valentine-alia.github.io/) (she/her) -{% include figure.html image="/assets/img/alia.jpg" position="left" width="120px" %} +### [Alia Valentine](https://valentine-alia.github.io/) (she/her) +Alia Valentine Alia is a PhD student at the Center for Applied Mathematics at Cornell University. She earned a BS in Physics and Math with a minor in CMSE from MSU in 2024. She is interested in dynamical systems, mathematical biology, and math/computation education. In her spare time she plays bass, takes photos of birds, and designs TTRPGs. -#### Amanda Bowerman (she/her) -{% include figure.html image="/assets/img/Amanda_headshot.jpg" position="left" width="120px" %} -Amanda is currently working on a PhD at the University of Oslo in the Mathematics and Natural Sciences Department. She earned her bachelor’s degree in Data Science with a minor in Cognitive Sciences in 2022 from MSU. She also completed her master’s degree in Computational Mathematics Science and Engineering in 2024. Her current research explores the methodology behind utilizing Natural Language Processing to aid in doing deductive coding of qualitative data. Amanda did curriculum development for CMSE 201 and CMSE 202, as well as having taught a number of entry level data science courses during her time at MSU. Outside of her research, she enjoys spending her time with her cat, playing guitar, learning Norwegian, and exploring Oslo! +### Amanda Bowerman (she/her) +Amanda Bowerman +Amanda is currently working on a PhD at the University of Oslo in the Mathematics and Natural Sciences Department. She earned her bachelor's degree in Data Science with a minor in Cognitive Sciences in 2022 from MSU. She also completed her master's degree in Computational Mathematics Science and Engineering in 2024. Her current research explores the methodology behind utilizing Natural Language Processing to aid in doing deductive coding of qualitative data. Amanda did curriculum development for CMSE 201 and CMSE 202, as well as having taught a number of entry level data science courses during her time at MSU. Outside of her research, she enjoys spending her time with her cat, playing guitar, learning Norwegian, and exploring Oslo! -#### Sarah Castle (she/her) -{% include figure.html image="/assets/img/SarahCastle_headshot.jpg" position="left" width="120px" %} -Sarah earned her masters in Mathematics and PhD in Mathematics Education from Michigan State University in 2023. She earned her bachelor’s degrees in Mathematics and Engineering Physics from Whitworth University. During this time her research projects were at the intersection of mathematics, engineering, and computation, including modeling biological fluid shifts in microgravity and evaluating electric propulsion systems for asteroid and comet sample-return missions. Sarah continued this research at Princeton in the Mechanical and Aerospace Engineering program before turning to mathematics education research. Her passion is exploring how computation enacted through coding in undergraduate mathematics classrooms can bring about deeper understandings of mathematical structures and develop mathematical creativity. Her most recent project focuses on introducing CMSE 201 students to linear algebra through a series of modules in Jupyter Notebooks and the relation with mathematical creativity. In her free time, she enjoys hiking, swimming, playing with her cats, and crafting. +### Sarah Castle (she/her) +Sarah Castle +Sarah earned her masters in Mathematics and PhD in Mathematics Education from Michigan State University in 2023. She earned her bachelor's degrees in Mathematics and Engineering Physics from Whitworth University. During this time her research projects were at the intersection of mathematics, engineering, and computation, including modeling biological fluid shifts in microgravity and evaluating electric propulsion systems for asteroid and comet sample-return missions. Sarah continued this research at Princeton in the Mechanical and Aerospace Engineering program before turning to mathematics education research. Her passion is exploring how computation enacted through coding in undergraduate mathematics classrooms can bring about deeper understandings of mathematical structures and develop mathematical creativity. Her most recent project focuses on introducing CMSE 201 students to linear algebra through a series of modules in Jupyter Notebooks and the relation with mathematical creativity. In her free time, she enjoys hiking, swimming, playing with her cats, and crafting. -#### Tom Finzell (he/him) -{% include figure.html image="/assets/img/TomFinzell_headshot.jpg" position="left" width="120px" %} +### Tom Finzell (he/him) +Tom Finzell Tom is a assistant professor in CMSE working in CERL. His research focuses on how students learn the computational data manipulation tools ubiquitous across all STEM disciplines, emphasizing equitably and inclusively. Tom has also worked on integrating computation into the core curriculum of physics, and more broadly, in STEM and beyond. He believes that a lack of preparation in computation can propagate historical and structural barriers that stand in the way of success for disenfranchised groups. Tom's Ph.D. work was in astronomy, focused on modeling multi-wavelength observations of gamma-ray-emitting Classical Novae, specifically focusing on the V1324 Sco. Tom used radio observations to probe the extensive properties of nova ejecta, optical data as a diagnostic of the plasma, and gamma-ray data to constrain the dynamics of the event. +### Patti Hamerski (she/her) +Patti Hamerski +Patti is an assistant professor in CMSE. Her research is based out of CERL and she teaches CMSE 201 and STT 180. She finished her PhD in 2021 doing physics education research at MSU, studying how high school students perceive and deal with affect-based challenges when learning physics through computation. She is interested broadly in the intersection of computing, disciplinary learning, and affect. Her current research focuses on CMSE 201 (an introductory interdisciplinary computing course), and involves students' perspectives on self-efficacy for interdisciplinary computing, the impact of personalized written feedback on students, and curriculum design for three-dimensional learning and sustainability. Outside of work, Patti loves to play with her German shorthaired pointer, explore Michigan's parks and breweries, and make linocuts. -#### Patti Hamerski (she/her) -{% include figure.html image="/assets/img/PattiHamerski_headshot.jpg" position="left" width="120px" %} -Patti is an assistant professor in CMSE. Her research is based out of CERL and she teaches CMSE 201 and STT 180. She finished her PhD in 2021 doing physics education research at MSU, studying how high school students perceive and deal with affect-based challenges when learning physics through computation. She is interested broadly in the intersection of computing, disciplinary learning, and affect. Her current research focuses on CMSE 201 (an introductory interdisciplinary computing course), and involves students’ perspectives on self-efficacy for interdisciplinary computing, the impact of personalized written feedback on students, and curriculum design for three-dimensional learning and sustainability. Outside of work, Patti loves to play with her German shorthaired pointer, explore Michigan’s parks and breweries, and make linocuts. +### Paige Tourangeau (she/her) +Paige is an undergraduate student studying statistics at Michigan State University. Her research interests surround studying various aspects of student experience and perception of their success in the classroom. In her free time, she enjoys doing yoga, trying new foods, and watching reality TV. -#### Paige Tourangeau (she/her) -Paige is an undergraduate student studying statistics at Michigan State University. Her research interests surround studying various aspects of student experience and perception of their success in the classroom. In her free time, she enjoys doing yoga, trying new foods, and watching reality TV. - -#### Jacob Underwood (he/him) -{% include figure.html image="/assets/img/Jacob_headshot.jpg" position="left" width="120px" %} +### Jacob Underwood (he/him) +Jacob Underwood Jacob is an undergraduate student studying computer science from Arizona State University. His research interests include computer programming education and natural language processing. In his free time, he likes reading science fiction, exploring nature, and learning a new language. Jacob joined CERL for the [2023 ACRES REU Program](https://icer-acres.msu.edu/)! - -#### Krithi Sachithanand (she/her) -{% include figure.html image="/assets/img/KrithiSachithanand_headshot.jpg" position="left" width="120px" %} +### Krithi Sachithanand (she/her) +Krithi Sachithanand Krithi is an undergraduate student studying Computational Data Science at Michigan State University. Her research interests include studying user experience through classroom application. Outside of work, she likes trying different flavors of ice-cream, karaoke and crafting. -#### Nat Hawkins (he/him) -{% include figure.html image="/assets/img/headshot_reduced.jpg" position="left" width="120px" %} +### Nat Hawkins (he/him) +Nat Hawkins Nat is a former post-bac researcher with CERL. He completed a Masters in CMSE and is now working as a Business Intelligence Analyst for the Kellogg Company. diff --git a/projects.md b/content/pages/projects.md similarity index 60% rename from projects.md rename to content/pages/projects.md index ee84ad3..2be9c44 100644 --- a/projects.md +++ b/content/pages/projects.md @@ -1,27 +1,27 @@ ---- -layout: page -title: Past and Present Research Efforts ---- ---- -### Current Projects - -#### Exploring the Impact of Unsupervised Clustering Methods in Systematic Literature Reviews -##### Folks Involved: E. Bolger, D. Kinsman, A. Kosinski, D. Caballero -About 15 years ago, education researchers conducted a systematic literature review (SLR) on change strategies for improving undergraduate STEM education instruction. Analyzing 191 articles from 1995 to 2008, the researchers identified four broad categories of change strategies through a comprehensive interdisciplinary literature review: (1) disseminating curriculum and pedagogy, (2) developing reflective teachers, (3) enacting policy, and (4) developing a shared vision. With recent developments in STEM education practices, it is imperative to conduct a follow-up SLR comparing the effects of change strategies and associated student success. Similarly, with the influx of scientific articles published in recent decades, it is time consuming to conduct comprehensive SLRs without the assistance of machine learning (ML) analysis techniques. Working with qualitative researchers, we investigate the impact and ability of using ML to assist in the analysis pipeline through implementing Computational Grounded Theory. - -#### Using Resource Theory to Understand How Students Think About Indexing -##### Folks involved: T. Finzell (lead), D. Silvia, D. Caballero -Students struggle with how to loop through lists in Python, often mixing and matching their strategies between looping by value and looping by index. At the heart of this issue is the concept of indexing, which can be a challenging abstraction for students. My work uses Resource Theory, a cognitive framework based on DiSessa’s Knowledge in Pieces, to identify concepts and procedures that students activate when solving problems involving indexing. - -#### Students’ Approach to Problem-Solving Computational Tasks with Functions -##### Folks involved: R. Frisbie (lead), K. Sachithanand, E. Tobias, D. Caballero, D. Silvia -Students with a variety of prior knowledge and experience with respect to computation engage in our interdisciplinary introductory computation courses. We strive to create a curriculum that brings together students’ disciplines and experiences with computer science concepts, data analysis, and computational modeling. This project encompasses two different research avenues. (1) Qualitative interviews with students centered on computational tasks involving functions and (2) Exploration of the impact of research findings integrated into introductory curricula. The data generated consist of student interviews where they describe their thought processes aloud while engaging in tasks presented in a Jupyter notebook. In particular, I compare the characteristics of the pathways that students take to arrive at a solution to a particular task. - -#### Self-efficacy in interdisciplinary computing -##### Folks involved: P. Hamerski (lead), P. Tourangeau, D. Silvia, D. Caballero +Title: Past and Present Research Efforts +Slug: projects + +## Current Projects + +### Exploring the Impact of Unsupervised Clustering Methods in Systematic Literature Reviews +#### Folks Involved: E. Bolger, D. Kinsman, A. Kosinski, D. Caballero +About 15 years ago, education researchers conducted a systematic literature review (SLR) on change strategies for improving undergraduate STEM education instruction. Analyzing 191 articles from 1995 to 2008, the researchers identified four broad categories of change strategies through a comprehensive interdisciplinary literature review: (1) disseminating curriculum and pedagogy, (2) developing reflective teachers, (3) enacting policy, and (4) developing a shared vision. With recent developments in STEM education practices, it is imperative to conduct a follow-up SLR comparing the effects of change strategies and associated student success. Similarly, with the influx of scientific articles published in recent decades, it is time consuming to conduct comprehensive SLRs without the assistance of machine learning (ML) analysis techniques. Working with qualitative researchers, we investigate the impact and ability of using ML to assist in the analysis pipeline through implementing Computational Grounded Theory. + +### Using Resource Theory to Understand How Students Think About Indexing +#### Folks involved: T. Finzell (lead), D. Silvia, D. Caballero +Students struggle with how to loop through lists in Python, often mixing and matching their strategies between looping by value and looping by index. At the heart of this issue is the concept of indexing, which can be a challenging abstraction for students. My work uses Resource Theory, a cognitive framework based on DiSessa's Knowledge in Pieces, to identify concepts and procedures that students activate when solving problems involving indexing. + +### Students' Approach to Problem-Solving Computational Tasks with Functions +#### Folks involved: R. Frisbie (lead), K. Sachithanand, E. Tobias, D. Caballero, D. Silvia +Students with a variety of prior knowledge and experience with respect to computation engage in our interdisciplinary introductory computation courses. We strive to create a curriculum that brings together students' disciplines and experiences with computer science concepts, data analysis, and computational modeling. This project encompasses two different research avenues. (1) Qualitative interviews with students centered on computational tasks involving functions and (2) Exploration of the impact of research findings integrated into introductory curricula. The data generated consist of student interviews where they describe their thought processes aloud while engaging in tasks presented in a Jupyter notebook. In particular, I compare the characteristics of the pathways that students take to arrive at a solution to a particular task. + +### Self-efficacy in interdisciplinary computing +#### Folks involved: P. Hamerski (lead), P. Tourangeau, D. Silvia, D. Caballero This project focuses on characterizing self-efficacy for interdisciplinary computing, from the perspectives of students in an introductory CMSE course. We have carried out data generation by conducting semi-structured research interviews. We are working on data analysis, which entails theory-driven and data-driven coding for self-efficacy, developing a codebook, and shaping findings around how students described their course experiences and how those descriptions align with self-efficacy. -#### Characterizing Community Interactions Among Faculty Using Network Analysis -##### Folks involved: E. Bolger, M. Nwobi, D. Caballero -{% include figure.html image="/assets/img/projects/CompareDegreeTies.png" position="right" width="400px" %} +### Characterizing Community Interactions Among Faculty Using Network Analysis +#### Folks involved: E. Bolger, M. Nwobi, D. Caballero + +Comparing degree ties network visualization + Using Social Network Analysis (SNA), we analyze the interactions of physics instructors over Slack involved with the Partnership for Integration of Computation into Undergraduate Physics (PICUP) – a faculty learning community. We analyze these relationships with traditional SNA metrics, such as reciprocity. However, to statistically quantify the values of these metrics in our networks, we need to create our own sample by generating random networks similar to the original. In this project, we compare the degree distributions of the random networks from various generation techniques. The choice of random generation method will allow us to make statistical claims about the nature of the interactions between the physics instructors and provide insight on how the virtual environment supports faculty in integrating computing into their classrooms. diff --git a/pubs.md b/content/pages/pubs.md similarity index 99% rename from pubs.md rename to content/pages/pubs.md index 2208eca..89588ef 100644 --- a/pubs.md +++ b/content/pages/pubs.md @@ -1,7 +1,6 @@ ---- -layout: page -title: CERL Publications ---- +Title: CERL Publications +Slug: pubs + ## 2025 Bolger, E., Nwobi, M., & Caballero, M. D. (2025). Characterizing Faculty @@ -211,4 +210,3 @@ Caballero, M. D., & Merner, L. (2018). Prevalence and nature of computational instruction in undergraduate physics programs across the United States. *Physical Review Physics Education Research*, *14*(2), 020129. - diff --git a/content/posts/welcome.md b/content/posts/welcome.md new file mode 100644 index 0000000..754227a --- /dev/null +++ b/content/posts/welcome.md @@ -0,0 +1,9 @@ +Title: Welcome to the New CERL Website +Date: 2026-05-06 +Author: Devin Silvia +Slug: welcome-to-the-new-cerl-website +Summary: We've redesigned the CERL website and added a News & Perspectives space for sharing lab updates and longer-form writing from group members. + +We've redesigned the CERL website and are excited to introduce **News & Perspectives** — a space where we'll share lab updates, highlight recent work, and post longer-form writing from group members about research, teaching, and computing education. + +Keep an eye here for announcements about new publications, conference presentations, and opportunities to get involved with CERL. diff --git a/index.md b/index.md deleted file mode 100644 index f5ef763..0000000 --- a/index.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: Computing Education Research Lab @ MSU -layout: page -aside: True -#feature_image: "https://picsum.photos/1300/400?image=989" -feature_image: "/assets/img/foggy_michigan.jpg" #image found here: https://images.app.goo.gl/Z6X1KbgBkZsMsbou6 -#feature_text: | - # Welcome! ---- - -The Computing Education Research Lab (CERL) at [Michigan State University](https://msu.edu) is an interdisciplinary collaboration that studies how students learn to do computational work and their attitudes about doing that work. In particular, we explore how students learn to integrate computing into their education outside of traditional computer science courses. - -Our research group includes faculty, postdocs, and students from the [Department of Computational Mathematics, Science and Engineering](https://cmse.msu.edu) and the [Department of Physics and Astronomy](https://pa.msu.edu). diff --git a/pelicanconf.py b/pelicanconf.py new file mode 100644 index 0000000..3e2c0dc --- /dev/null +++ b/pelicanconf.py @@ -0,0 +1,71 @@ +AUTHOR = "CERL" +SITENAME = "CERL@MSU" +SITEURL = "" +SITELOGO = "/assets/img/logo.png" + +SITE_DESCRIPTION = """ +We're working to demystify how college students learn computing in the modern era. +

+Interested in joining us?
+Send an email to dsilvia@msu.edu. +""" + +# Theme choice: "msu" or "cerl" +COLOR_SCHEME = "cerl" + +PATH = "content" +PAGE_PATHS = ["pages"] +ARTICLE_PATHS = ["posts"] +ARTICLE_URL = "news/{date:%Y}/{slug}/" +ARTICLE_SAVE_AS = "news/{date:%Y}/{slug}/index.html" + +DIRECT_TEMPLATES = ["news"] +NEWS_SAVE_AS = "news/index.html" + +STATIC_PATHS = ["assets"] + +TIMEZONE = "America/Detroit" +DEFAULT_LANG = "en" + +THEME = "themes" + +MENUITEMS = [ + ("Home", "/"), + ("News & Perspectives", "/news/"), + ("People", "/people/"), + ("Projects", "/projects/"), + ("Curriculum Development", "/curriculumdev/"), + ("Outreach", "/outreach/"), + ("Publications", "/pubs/"), +] + +PAGE_URL = "{slug}/" +PAGE_SAVE_AS = "{slug}/index.html" + +# Disable blog/feed features +FEED_ALL_ATOM = None +CATEGORY_FEED_ATOM = None +TRANSLATION_FEED_ATOM = None +AUTHOR_FEED_ATOM = None +AUTHOR_FEED_RSS = None +DEFAULT_PAGINATION = False + +# Suppress unused output +ARCHIVES_SAVE_AS = "" +AUTHORS_SAVE_AS = "" +AUTHOR_SAVE_AS = "" +CATEGORIES_SAVE_AS = "" +CATEGORY_SAVE_AS = "" +TAGS_SAVE_AS = "" +TAG_SAVE_AS = "" +INDEX_SAVE_AS = "" + +PLUGINS = ["pelican.plugins.sitemap"] + +SITEMAP = { + "format": "xml", + "priorities": {"articles": 0.6, "indexes": 0.6, "pages": 0.8}, + "changefreqs": {"articles": "monthly", "indexes": "weekly", "pages": "monthly"}, +} + +TYPOGRIFY = True diff --git a/publishconf.py b/publishconf.py new file mode 100644 index 0000000..5f69c62 --- /dev/null +++ b/publishconf.py @@ -0,0 +1,9 @@ +import sys +from pathlib import Path + +sys.path.insert(0, str(Path(__file__).parent)) +from pelicanconf import * # noqa: F401, F403 + +SITEURL = "https://msucerl.org" +RELATIVE_URLS = False +DELETE_OUTPUT_DIRECTORY = True diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..77fd5b4 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,15 @@ +[project] +name = "cerl-website" +version = "0.1.0" +requires-python = ">=3.11" +dependencies = [ + "pelican[markdown]>=4.10", + "pelican-sitemap>=1.1", + "typogrify>=2.0", + "pypandoc-binary>=1.13", +] + +[dependency-groups] +dev = [ + "livereload>=2.6", +] diff --git a/templates/apa.csl b/templates/apa.csl new file mode 100644 index 0000000..84632ab --- /dev/null +++ b/templates/apa.csl @@ -0,0 +1,2273 @@ + + diff --git a/templates/pubs-template.md b/templates/pubs-template.md index bb9397f..cf9d858 100644 --- a/templates/pubs-template.md +++ b/templates/pubs-template.md @@ -1,9 +1,5 @@ --- title: "pubs" -date: 2025-05-16 -hidemeta: true -bibliography: ../assets/bib/group_publications.bib -csl: 'http://www.zotero.org/styles/apa' nocite: '@*' --- diff --git a/templates/yaml-metadata.template b/templates/yaml-metadata.template deleted file mode 100644 index 1265717..0000000 --- a/templates/yaml-metadata.template +++ /dev/null @@ -1,3 +0,0 @@ -$metadata$ - -$body$ \ No newline at end of file diff --git a/themes/static/css/style.css b/themes/static/css/style.css new file mode 100644 index 0000000..3d369ef --- /dev/null +++ b/themes/static/css/style.css @@ -0,0 +1,323 @@ +/* ── Reset & base ─────────────────────────────────────────── */ +*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } + +:root { + --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; + --max-width: 1100px; + --header-height: 60px; +} + +html { font-size: 18px; scroll-behavior: smooth; } + +/* ── Skip link ────────────────────────────────────────────── */ +.skip-link { + position: absolute; + top: -100%; + left: 0; + background: var(--color-header-bg); + color: var(--color-header-text); + padding: 0.5rem 1rem; + z-index: 200; + text-decoration: none; + font-size: 0.95rem; +} +.skip-link:focus { top: 0; } + +@media (prefers-reduced-motion: reduce) { + html { scroll-behavior: auto; } + *, *::before, *::after { transition: none !important; } +} + +body { + font-family: var(--font-sans); + color: var(--color-text); + background: var(--color-body-bg); + line-height: 1.7; + display: flex; + flex-direction: column; + min-height: 100vh; +} + +/* ── Header ───────────────────────────────────────────────── */ +.site-header { + background: var(--color-header-bg); + height: var(--header-height); + position: sticky; + top: 0; + z-index: 100; + box-shadow: 0 2px 6px rgba(0,0,0,0.25); +} + +.header-inner { + max-width: var(--max-width); + margin: 0 auto; + padding: 0 1.5rem; + height: 100%; + display: flex; + align-items: center; + justify-content: space-between; +} + +.site-brand img { display: block; } +.site-brand .site-name { + color: var(--color-header-text); + font-size: 1.2rem; + font-weight: 700; + text-decoration: none; +} +.site-brand { text-decoration: none; } + +.site-nav ul { + list-style: none; + display: flex; + gap: 0.25rem; +} + +.site-nav a { + color: var(--color-header-text); + text-decoration: none; + font-size: 0.95rem; + padding: 0.4rem 0.75rem; + border-radius: 4px; + transition: background 0.15s; +} + +.site-nav a:hover { + background: rgba(255,255,255,0.15); +} + +.site-nav a:focus-visible { + outline: 2px solid var(--color-header-text); + outline-offset: 2px; + text-decoration: underline; +} + +.site-nav a.active { + background: var(--color-nav-active); +} + +a:focus-visible, +button:focus-visible { + outline: 2px solid var(--color-accent); + outline-offset: 2px; +} + +/* ── Page layout ──────────────────────────────────────────── */ +.page-wrap { + flex: 1; + max-width: var(--max-width); + margin: 0 auto; + padding: 2.5rem 1.5rem; + width: 100%; +} + +.page-wrap.with-aside { + display: grid; + grid-template-columns: 1fr 280px; + gap: 3rem; + align-items: start; +} + +/* ── Page content ─────────────────────────────────────────── */ +.page-content { + min-width: 0; +} + +.typeset .page-title { + font-size: 1.75rem; + font-weight: 700; + color: var(--color-heading); + margin-top: 0; + margin-bottom: 1.5rem; + padding-bottom: 0.5rem; + border-bottom: 3px solid var(--color-heading-border); +} + +/* ── Aside ────────────────────────────────────────────────── */ +.page-aside { + position: sticky; + top: calc(var(--header-height) + 1.5rem); +} + +.aside-section { + background: var(--color-aside-bg); + border: 1px solid var(--color-border); + border-left: 4px solid var(--color-aside-border); + border-radius: 6px; + padding: 1.25rem; +} + +.aside-section h3 { + font-size: 1.1rem; + font-weight: 700; + margin-bottom: 0.75rem; + color: var(--color-heading); +} + +.aside-logo { + display: block; + width: 100%; + max-width: 180px; + margin: 0 auto 1rem; +} + +.aside-section p { + font-size: 1rem; + color: var(--color-text-light); + line-height: 1.6; +} + +.aside-section a { + color: var(--color-aside-link); +} + +/* ── Typography (typeset) ─────────────────────────────────── */ +.typeset h1, .typeset h2, .typeset h3, +.typeset h4, .typeset h5, .typeset h6 { + font-weight: 700; + line-height: 1.3; + margin: 1.5rem 0 0.75rem; + color: var(--color-heading); +} + +.typeset h2 { font-size: 1.5rem; border-bottom: 2px solid var(--color-heading-border); padding-bottom: 0.35rem; } +.typeset h3 { font-size: 1.2rem; border-bottom: 1px solid var(--color-border); padding-bottom: 0.25rem; } +.typeset h4 { font-size: 1.05rem; } +.typeset h5 { font-size: 0.95rem; color: var(--color-text-light); font-weight: 600; } + +.typeset p { margin-bottom: 1rem; } + +.typeset a { color: var(--color-accent); text-decoration: underline; } +.typeset a:hover { color: var(--color-accent-hover); } + +.typeset ul, .typeset ol { + margin: 0.75rem 0 1rem 1.5rem; +} + +.typeset li { margin-bottom: 0.35rem; } + +.typeset em { font-style: italic; } +.typeset strong { font-weight: 700; } + +.typeset hr { + border: none; + border-top: 1px solid var(--color-border); + margin: 2rem 0; +} + +.typeset blockquote { + border-left: 3px solid var(--color-blockquote); + padding-left: 1rem; + color: var(--color-text-light); + margin: 1rem 0; +} + +/* ── People / figure floats ───────────────────────────────── */ +.typeset img[style*="float:left"], +.typeset img[style*="float: left"] { + margin: 0.25rem 1.25rem 1rem 0; +} + +.typeset img[style*="float:right"], +.typeset img[style*="float: right"] { + margin: 0.25rem 0 1rem 1.25rem; +} + +/* Person blocks: clear floats after each h2/h3/h4 section */ +.typeset h2, .typeset h3, .typeset h4 { clear: both; } + +/* ── Footer ───────────────────────────────────────────────── */ +.site-footer { + background: var(--color-footer-bg); + border-top: 3px solid var(--color-footer-border); + padding: 1.5rem; + text-align: center; + font-size: 1rem; + color: var(--color-text-light); +} + +.footer-inner { + display: flex; + flex-direction: column; + align-items: center; + gap: 0.75rem; +} + +.footer-logo img { display: block; } + +/* ── Responsive ───────────────────────────────────────────── */ +@media (max-width: 768px) { + .site-nav ul { gap: 0; flex-wrap: wrap; } + .site-nav a { font-size: 0.875rem; padding: 0.3rem 0.5rem; } + + .page-wrap.with-aside { + grid-template-columns: 1fr; + } + + .page-aside { + position: static; + } + +} + +/* ── News list ────────────────────────────────────────────── */ +.news-list { + list-style: none; + margin: 0; + padding: 0; +} + +.news-item { + padding: 1.5rem 0; + border-bottom: 1px solid var(--color-border); +} + +.news-item:first-child { padding-top: 0; } + +.news-item-title { + display: block; + font-size: 1.2rem; + font-weight: 700; + color: var(--color-accent); + text-decoration: underline; + margin-bottom: 0.25rem; +} + +.news-item-title:hover { + color: var(--color-accent-hover); +} + +.news-item-meta { + font-size: 0.875rem; + color: var(--color-text-light); + margin-bottom: 0.5rem; +} + +.news-item-summary { margin: 0 0 0.5rem; } + +.news-item-more { + font-size: 0.875rem; + font-weight: 600; + color: var(--color-accent); + text-decoration: none; +} + +.news-item-more:hover { + color: var(--color-accent-hover); + text-decoration: underline; +} + +/* ── Article ──────────────────────────────────────────────── */ +.article-meta { + font-size: 0.875rem; + color: var(--color-text-light); + margin-bottom: 1.5rem; + padding-bottom: 1rem; + border-bottom: 1px solid var(--color-border); +} + +.article-back { + margin-top: 2rem; + padding-top: 1rem; + border-top: 1px solid var(--color-border); +} diff --git a/themes/static/css/theme-cerl.css b/themes/static/css/theme-cerl.css new file mode 100644 index 0000000..1139e3b --- /dev/null +++ b/themes/static/css/theme-cerl.css @@ -0,0 +1,39 @@ +/* ── CERL color scheme (teal, grey, black) ────────────────── */ +:root { + --color-header-bg: #0d2b36; + --color-header-text: #f0f0f0; + --color-nav-active: #1e6070; + --color-aside-link: #1e5f6e; + --color-heading: #0d2b36; + --color-heading-border: #2e7a8c; + --color-accent: #2e7a8c; + --color-accent-hover: #0d2b36; + --color-body-bg: #ffffff; + --color-text: #1a1a1a; + --color-text-light: #555555; + --color-border: #ccd6d8; + --color-aside-bg: #edf4f6; + --color-aside-border: #2e7a8c; + --color-footer-bg: #f0f3f4; + --color-footer-border: #0d2b36; + --color-blockquote: #3d9aac; +} + +@media (prefers-color-scheme: dark) { + :root { + --color-heading: #9acfda; + --color-heading-border: #2e7a8c; + --color-accent: #4db8cc; + --color-accent-hover: #7dcfdd; + --color-aside-link: #4db8cc; + --color-body-bg: #0d1b22; + --color-text: #e2ecee; + --color-text-light: #8faab2; + --color-border: #1e404d; + --color-aside-bg: #111f27; + --color-aside-border: #2e7a8c; + --color-footer-bg: #0a1419; + --color-footer-border: #1e404d; + --color-blockquote: #4db8cc; + } +} diff --git a/themes/static/css/theme-msu.css b/themes/static/css/theme-msu.css new file mode 100644 index 0000000..fea757c --- /dev/null +++ b/themes/static/css/theme-msu.css @@ -0,0 +1,39 @@ +/* ── MSU brand color scheme ───────────────────────────────── */ +:root { + --color-header-bg: #18453b; + --color-header-text: #f0f0f0; + --color-nav-active: #006810; + --color-aside-link: #006810; + --color-heading: #18453b; + --color-heading-border: #18453b; + --color-accent: #008208; + --color-accent-hover: #18453b; + --color-body-bg: #ffffff; + --color-text: #1a1a1a; + --color-text-light: #555555; + --color-border: #d6e4d6; + --color-aside-bg: #eaf3ec; + --color-aside-border: #18453b; + --color-footer-bg: #f0f4f0; + --color-footer-border: #18453b; + --color-blockquote: #0b9a6d; +} + +@media (prefers-color-scheme: dark) { + :root { + --color-heading: #7ec48e; + --color-heading-border: #2d7a4f; + --color-accent: #3dc45a; + --color-accent-hover: #65d47a; + --color-aside-link: #3dc45a; + --color-body-bg: #0a1a12; + --color-text: #e2ede5; + --color-text-light: #8aaa90; + --color-border: #1a3828; + --color-aside-bg: #0f2018; + --color-aside-border: #2d7a4f; + --color-footer-bg: #08130e; + --color-footer-border: #1a3828; + --color-blockquote: #3dc45a; + } +} diff --git a/themes/templates/article.html b/themes/templates/article.html new file mode 100644 index 0000000..e8fa5d0 --- /dev/null +++ b/themes/templates/article.html @@ -0,0 +1,17 @@ +{% extends "base.html" %} + +{% block title %}{{ article.title }} | {{ SITENAME }}{% endblock %} + +{% block body %} +
+
+

{{ article.title }}

+ + {{ article.content }} +
+

← News & Perspectives

+
+{% endblock %} diff --git a/themes/templates/base.html b/themes/templates/base.html new file mode 100644 index 0000000..b6b538d --- /dev/null +++ b/themes/templates/base.html @@ -0,0 +1,64 @@ + + + + + + {% block title %}{{ SITENAME }}{% endblock %} + + + {% if SITEURL %} + {% if page is defined %} + + {% elif article is defined %} + + {% elif output_file is defined %} + + {% endif %} + {% endif %} + + + + + + {% block feature %}{% endblock %} + +
+ {% block body %}{% endblock %} +
+ +
+ +
+ + diff --git a/themes/templates/index.html b/themes/templates/index.html new file mode 100644 index 0000000..1b1a2b2 --- /dev/null +++ b/themes/templates/index.html @@ -0,0 +1,39 @@ +{% extends "base.html" %} + +{% block title %}{{ SITENAME }}{% endblock %} + +{% block feature %} +{# + Feature hero banner — disabled but preserved for potential re-use. + To re-enable: + 1. Restore .feature-hero and .feature-overlay CSS rules in style.css + (a full-width banner with a darkening overlay, ~300px tall) + 2. Add FEATURE_IMAGE = "/assets/img/YOUR_IMAGE.jpg" to pelicanconf.py + 3. Uncomment the block below + +
+
+
+#} +{% endblock %} + +{% block layout_class %}with-aside{% endblock %} + +{% block body %} +
+

{{ page.title }}

+ {{ page.content }} +
+ +{% endblock %} diff --git a/themes/templates/news.html b/themes/templates/news.html new file mode 100644 index 0000000..061757b --- /dev/null +++ b/themes/templates/news.html @@ -0,0 +1,26 @@ +{% extends "base.html" %} + +{% block title %}News & Perspectives | {{ SITENAME }}{% endblock %} + +{% block body %} +
+

News & Perspectives

+ {% if articles %} +
    + {% for article in articles %} +
  • + {{ article.title }} +
    + + {% if article.author %} · {{ article.author }}{% endif %} +
    + {% if article.summary %}
    {{ article.summary }}
    {% endif %} + +
  • + {% endfor %} +
+ {% else %} +

No posts yet — check back soon.

+ {% endif %} +
+{% endblock %} diff --git a/themes/templates/page.html b/themes/templates/page.html new file mode 100644 index 0000000..580b8af --- /dev/null +++ b/themes/templates/page.html @@ -0,0 +1,10 @@ +{% extends "base.html" %} + +{% block title %}{{ page.title }} | {{ SITENAME }}{% endblock %} + +{% block body %} +
+

{{ page.title }}

+ {{ page.content }} +
+{% endblock %} diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000..ff84fa7 --- /dev/null +++ b/uv.lock @@ -0,0 +1,467 @@ +version = 1 +revision = 3 +requires-python = ">=3.11" + +[[package]] +name = "anyio" +version = "4.13.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "idna" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/19/14/2c5dd9f512b66549ae92767a9c7b330ae88e1932ca57876909410251fe13/anyio-4.13.0.tar.gz", hash = "sha256:334b70e641fd2221c1505b3890c69882fe4a2df910cba14d97019b90b24439dc", size = 231622, upload-time = "2026-03-24T12:59:09.671Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/da/42/e921fccf5015463e32a3cf6ee7f980a6ed0f395ceeaa45060b61d86486c2/anyio-4.13.0-py3-none-any.whl", hash = "sha256:08b310f9e24a9594186fd75b4f73f4a4152069e3853f1ed8bfbf58369f4ad708", size = 114353, upload-time = "2026-03-24T12:59:08.246Z" }, +] + +[[package]] +name = "blinker" +version = "1.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/21/28/9b3f50ce0e048515135495f198351908d99540d69bfdc8c1d15b73dc55ce/blinker-1.9.0.tar.gz", hash = "sha256:b4ce2265a7abece45e7cc896e98dbebe6cead56bcf805a3d23136d145f5445bf", size = 22460, upload-time = "2024-11-08T17:25:47.436Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl", hash = "sha256:ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc", size = 8458, upload-time = "2024-11-08T17:25:46.184Z" }, +] + +[[package]] +name = "cerl-website" +version = "0.1.0" +source = { virtual = "." } +dependencies = [ + { name = "pelican", extra = ["markdown"] }, + { name = "pelican-sitemap" }, + { name = "pypandoc-binary" }, + { name = "typogrify" }, +] + +[package.dev-dependencies] +dev = [ + { name = "livereload" }, +] + +[package.metadata] +requires-dist = [ + { name = "pelican", extras = ["markdown"], specifier = ">=4.10" }, + { name = "pelican-sitemap", specifier = ">=1.1" }, + { name = "pypandoc-binary", specifier = ">=1.13" }, + { name = "typogrify", specifier = ">=2.0" }, +] + +[package.metadata.requires-dev] +dev = [{ name = "livereload", specifier = ">=2.6" }] + +[[package]] +name = "docutils" +version = "0.22.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ae/b6/03bb70946330e88ffec97aefd3ea75ba575cb2e762061e0e62a213befee8/docutils-0.22.4.tar.gz", hash = "sha256:4db53b1fde9abecbb74d91230d32ab626d94f6badfc575d6db9194a49df29968", size = 2291750, upload-time = "2025-12-18T19:00:26.443Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/02/10/5da547df7a391dcde17f59520a231527b8571e6f46fc8efb02ccb370ab12/docutils-0.22.4-py3-none-any.whl", hash = "sha256:d0013f540772d1420576855455d050a2180186c91c15779301ac2ccb3eeb68de", size = 633196, upload-time = "2025-12-18T19:00:18.077Z" }, +] + +[[package]] +name = "feedgenerator" +version = "2.2.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "tzdata", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b0/d2/f05e9f4628cb0df988de66f8a97dd52877490e6ebf8e7b41cd341bf2ad6b/feedgenerator-2.2.1.tar.gz", hash = "sha256:0eaa955f1f0bcb5b87ac195af740f06ff9fff4a40ed30b8a7c6bbebb264d4dd1", size = 20872, upload-time = "2025-08-17T19:36:53.48Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b9/08/6f74bef4663fb137fa10b493facce85bee8c055b67fbd9a7695d88e3d1a3/feedgenerator-2.2.1-py3-none-any.whl", hash = "sha256:0d8bb321e49dd43c916b659e137c1eab1b1c053dd4535a03ef8d47e5f3358ba5", size = 18495, upload-time = "2025-08-17T19:36:52.036Z" }, +] + +[[package]] +name = "idna" +version = "3.13" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ce/cc/762dfb036166873f0059f3b7de4565e1b5bc3d6f28a414c13da27e442f99/idna-3.13.tar.gz", hash = "sha256:585ea8fe5d69b9181ec1afba340451fba6ba764af97026f92a91d4eef164a242", size = 194210, upload-time = "2026-04-22T16:42:42.314Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5d/13/ad7d7ca3808a898b4612b6fe93cde56b53f3034dcde235acb1f0e1df24c6/idna-3.13-py3-none-any.whl", hash = "sha256:892ea0cde124a99ce773decba204c5552b69c3c67ffd5f232eb7696135bc8bb3", size = 68629, upload-time = "2026-04-22T16:42:40.909Z" }, +] + +[[package]] +name = "jinja2" +version = "3.1.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, +] + +[[package]] +name = "livereload" +version = "2.7.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "tornado" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/43/6e/f2748665839812a9bbe5c75d3f983edbf3ab05fa5cd2f7c2f36fffdf65bd/livereload-2.7.1.tar.gz", hash = "sha256:3d9bf7c05673df06e32bea23b494b8d36ca6d10f7d5c3c8a6989608c09c986a9", size = 22255, upload-time = "2024-12-18T13:42:01.461Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e4/3e/de54dc7f199e85e6ca37e2e5dae2ec3bce2151e9e28f8eb9076d71e83d56/livereload-2.7.1-py3-none-any.whl", hash = "sha256:5201740078c1b9433f4b2ba22cd2729a39b9d0ec0a2cc6b4d3df257df5ad0564", size = 22657, upload-time = "2024-12-18T13:41:56.35Z" }, +] + +[[package]] +name = "markdown" +version = "3.10.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2b/f4/69fa6ed85ae003c2378ffa8f6d2e3234662abd02c10d216c0ba96081a238/markdown-3.10.2.tar.gz", hash = "sha256:994d51325d25ad8aa7ce4ebaec003febcce822c3f8c911e3b17c52f7f589f950", size = 368805, upload-time = "2026-02-09T14:57:26.942Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/de/1f/77fa3081e4f66ca3576c896ae5d31c3002ac6607f9747d2e3aa49227e464/markdown-3.10.2-py3-none-any.whl", hash = "sha256:e91464b71ae3ee7afd3017d9f358ef0baf158fd9a298db92f1d4761133824c36", size = 108180, upload-time = "2026-02-09T14:57:25.787Z" }, +] + +[[package]] +name = "markdown-it-py" +version = "4.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "mdurl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5b/f5/4ec618ed16cc4f8fb3b701563655a69816155e79e24a17b651541804721d/markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3", size = 73070, upload-time = "2025-08-11T12:57:52.854Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147", size = 87321, upload-time = "2025-08-11T12:57:51.923Z" }, +] + +[[package]] +name = "markupsafe" +version = "3.0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7e/99/7690b6d4034fffd95959cbe0c02de8deb3098cc577c67bb6a24fe5d7caa7/markupsafe-3.0.3.tar.gz", hash = "sha256:722695808f4b6457b320fdc131280796bdceb04ab50fe1795cd540799ebe1698", size = 80313, upload-time = "2025-09-27T18:37:40.426Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/08/db/fefacb2136439fc8dd20e797950e749aa1f4997ed584c62cfb8ef7c2be0e/markupsafe-3.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1cc7ea17a6824959616c525620e387f6dd30fec8cb44f649e31712db02123dad", size = 11631, upload-time = "2025-09-27T18:36:18.185Z" }, + { url = "https://files.pythonhosted.org/packages/e1/2e/5898933336b61975ce9dc04decbc0a7f2fee78c30353c5efba7f2d6ff27a/markupsafe-3.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bd4cd07944443f5a265608cc6aab442e4f74dff8088b0dfc8238647b8f6ae9a", size = 12058, upload-time = "2025-09-27T18:36:19.444Z" }, + { url = "https://files.pythonhosted.org/packages/1d/09/adf2df3699d87d1d8184038df46a9c80d78c0148492323f4693df54e17bb/markupsafe-3.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b5420a1d9450023228968e7e6a9ce57f65d148ab56d2313fcd589eee96a7a50", size = 24287, upload-time = "2025-09-27T18:36:20.768Z" }, + { url = "https://files.pythonhosted.org/packages/30/ac/0273f6fcb5f42e314c6d8cd99effae6a5354604d461b8d392b5ec9530a54/markupsafe-3.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0bf2a864d67e76e5c9a34dc26ec616a66b9888e25e7b9460e1c76d3293bd9dbf", size = 22940, upload-time = "2025-09-27T18:36:22.249Z" }, + { url = "https://files.pythonhosted.org/packages/19/ae/31c1be199ef767124c042c6c3e904da327a2f7f0cd63a0337e1eca2967a8/markupsafe-3.0.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc51efed119bc9cfdf792cdeaa4d67e8f6fcccab66ed4bfdd6bde3e59bfcbb2f", size = 21887, upload-time = "2025-09-27T18:36:23.535Z" }, + { url = "https://files.pythonhosted.org/packages/b2/76/7edcab99d5349a4532a459e1fe64f0b0467a3365056ae550d3bcf3f79e1e/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:068f375c472b3e7acbe2d5318dea141359e6900156b5b2ba06a30b169086b91a", size = 23692, upload-time = "2025-09-27T18:36:24.823Z" }, + { url = "https://files.pythonhosted.org/packages/a4/28/6e74cdd26d7514849143d69f0bf2399f929c37dc2b31e6829fd2045b2765/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:7be7b61bb172e1ed687f1754f8e7484f1c8019780f6f6b0786e76bb01c2ae115", size = 21471, upload-time = "2025-09-27T18:36:25.95Z" }, + { url = "https://files.pythonhosted.org/packages/62/7e/a145f36a5c2945673e590850a6f8014318d5577ed7e5920a4b3448e0865d/markupsafe-3.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f9e130248f4462aaa8e2552d547f36ddadbeaa573879158d721bbd33dfe4743a", size = 22923, upload-time = "2025-09-27T18:36:27.109Z" }, + { url = "https://files.pythonhosted.org/packages/0f/62/d9c46a7f5c9adbeeeda52f5b8d802e1094e9717705a645efc71b0913a0a8/markupsafe-3.0.3-cp311-cp311-win32.whl", hash = "sha256:0db14f5dafddbb6d9208827849fad01f1a2609380add406671a26386cdf15a19", size = 14572, upload-time = "2025-09-27T18:36:28.045Z" }, + { url = "https://files.pythonhosted.org/packages/83/8a/4414c03d3f891739326e1783338e48fb49781cc915b2e0ee052aa490d586/markupsafe-3.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:de8a88e63464af587c950061a5e6a67d3632e36df62b986892331d4620a35c01", size = 15077, upload-time = "2025-09-27T18:36:29.025Z" }, + { url = "https://files.pythonhosted.org/packages/35/73/893072b42e6862f319b5207adc9ae06070f095b358655f077f69a35601f0/markupsafe-3.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:3b562dd9e9ea93f13d53989d23a7e775fdfd1066c33494ff43f5418bc8c58a5c", size = 13876, upload-time = "2025-09-27T18:36:29.954Z" }, + { url = "https://files.pythonhosted.org/packages/5a/72/147da192e38635ada20e0a2e1a51cf8823d2119ce8883f7053879c2199b5/markupsafe-3.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d53197da72cc091b024dd97249dfc7794d6a56530370992a5e1a08983ad9230e", size = 11615, upload-time = "2025-09-27T18:36:30.854Z" }, + { url = "https://files.pythonhosted.org/packages/9a/81/7e4e08678a1f98521201c3079f77db69fb552acd56067661f8c2f534a718/markupsafe-3.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1872df69a4de6aead3491198eaf13810b565bdbeec3ae2dc8780f14458ec73ce", size = 12020, upload-time = "2025-09-27T18:36:31.971Z" }, + { url = "https://files.pythonhosted.org/packages/1e/2c/799f4742efc39633a1b54a92eec4082e4f815314869865d876824c257c1e/markupsafe-3.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3a7e8ae81ae39e62a41ec302f972ba6ae23a5c5396c8e60113e9066ef893da0d", size = 24332, upload-time = "2025-09-27T18:36:32.813Z" }, + { url = "https://files.pythonhosted.org/packages/3c/2e/8d0c2ab90a8c1d9a24f0399058ab8519a3279d1bd4289511d74e909f060e/markupsafe-3.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6dd0be5b5b189d31db7cda48b91d7e0a9795f31430b7f271219ab30f1d3ac9d", size = 22947, upload-time = "2025-09-27T18:36:33.86Z" }, + { url = "https://files.pythonhosted.org/packages/2c/54/887f3092a85238093a0b2154bd629c89444f395618842e8b0c41783898ea/markupsafe-3.0.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:94c6f0bb423f739146aec64595853541634bde58b2135f27f61c1ffd1cd4d16a", size = 21962, upload-time = "2025-09-27T18:36:35.099Z" }, + { url = "https://files.pythonhosted.org/packages/c9/2f/336b8c7b6f4a4d95e91119dc8521402461b74a485558d8f238a68312f11c/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:be8813b57049a7dc738189df53d69395eba14fb99345e0a5994914a3864c8a4b", size = 23760, upload-time = "2025-09-27T18:36:36.001Z" }, + { url = "https://files.pythonhosted.org/packages/32/43/67935f2b7e4982ffb50a4d169b724d74b62a3964bc1a9a527f5ac4f1ee2b/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:83891d0e9fb81a825d9a6d61e3f07550ca70a076484292a70fde82c4b807286f", size = 21529, upload-time = "2025-09-27T18:36:36.906Z" }, + { url = "https://files.pythonhosted.org/packages/89/e0/4486f11e51bbba8b0c041098859e869e304d1c261e59244baa3d295d47b7/markupsafe-3.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:77f0643abe7495da77fb436f50f8dab76dbc6e5fd25d39589a0f1fe6548bfa2b", size = 23015, upload-time = "2025-09-27T18:36:37.868Z" }, + { url = "https://files.pythonhosted.org/packages/2f/e1/78ee7a023dac597a5825441ebd17170785a9dab23de95d2c7508ade94e0e/markupsafe-3.0.3-cp312-cp312-win32.whl", hash = "sha256:d88b440e37a16e651bda4c7c2b930eb586fd15ca7406cb39e211fcff3bf3017d", size = 14540, upload-time = "2025-09-27T18:36:38.761Z" }, + { url = "https://files.pythonhosted.org/packages/aa/5b/bec5aa9bbbb2c946ca2733ef9c4ca91c91b6a24580193e891b5f7dbe8e1e/markupsafe-3.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:26a5784ded40c9e318cfc2bdb30fe164bdb8665ded9cd64d500a34fb42067b1c", size = 15105, upload-time = "2025-09-27T18:36:39.701Z" }, + { url = "https://files.pythonhosted.org/packages/e5/f1/216fc1bbfd74011693a4fd837e7026152e89c4bcf3e77b6692fba9923123/markupsafe-3.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:35add3b638a5d900e807944a078b51922212fb3dedb01633a8defc4b01a3c85f", size = 13906, upload-time = "2025-09-27T18:36:40.689Z" }, + { url = "https://files.pythonhosted.org/packages/38/2f/907b9c7bbba283e68f20259574b13d005c121a0fa4c175f9bed27c4597ff/markupsafe-3.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e1cf1972137e83c5d4c136c43ced9ac51d0e124706ee1c8aa8532c1287fa8795", size = 11622, upload-time = "2025-09-27T18:36:41.777Z" }, + { url = "https://files.pythonhosted.org/packages/9c/d9/5f7756922cdd676869eca1c4e3c0cd0df60ed30199ffd775e319089cb3ed/markupsafe-3.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:116bb52f642a37c115f517494ea5feb03889e04df47eeff5b130b1808ce7c219", size = 12029, upload-time = "2025-09-27T18:36:43.257Z" }, + { url = "https://files.pythonhosted.org/packages/00/07/575a68c754943058c78f30db02ee03a64b3c638586fba6a6dd56830b30a3/markupsafe-3.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:133a43e73a802c5562be9bbcd03d090aa5a1fe899db609c29e8c8d815c5f6de6", size = 24374, upload-time = "2025-09-27T18:36:44.508Z" }, + { url = "https://files.pythonhosted.org/packages/a9/21/9b05698b46f218fc0e118e1f8168395c65c8a2c750ae2bab54fc4bd4e0e8/markupsafe-3.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfcd093f13f0f0b7fdd0f198b90053bf7b2f02a3927a30e63f3ccc9df56b676", size = 22980, upload-time = "2025-09-27T18:36:45.385Z" }, + { url = "https://files.pythonhosted.org/packages/7f/71/544260864f893f18b6827315b988c146b559391e6e7e8f7252839b1b846a/markupsafe-3.0.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:509fa21c6deb7a7a273d629cf5ec029bc209d1a51178615ddf718f5918992ab9", size = 21990, upload-time = "2025-09-27T18:36:46.916Z" }, + { url = "https://files.pythonhosted.org/packages/c2/28/b50fc2f74d1ad761af2f5dcce7492648b983d00a65b8c0e0cb457c82ebbe/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4afe79fb3de0b7097d81da19090f4df4f8d3a2b3adaa8764138aac2e44f3af1", size = 23784, upload-time = "2025-09-27T18:36:47.884Z" }, + { url = "https://files.pythonhosted.org/packages/ed/76/104b2aa106a208da8b17a2fb72e033a5a9d7073c68f7e508b94916ed47a9/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:795e7751525cae078558e679d646ae45574b47ed6e7771863fcc079a6171a0fc", size = 21588, upload-time = "2025-09-27T18:36:48.82Z" }, + { url = "https://files.pythonhosted.org/packages/b5/99/16a5eb2d140087ebd97180d95249b00a03aa87e29cc224056274f2e45fd6/markupsafe-3.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8485f406a96febb5140bfeca44a73e3ce5116b2501ac54fe953e488fb1d03b12", size = 23041, upload-time = "2025-09-27T18:36:49.797Z" }, + { url = "https://files.pythonhosted.org/packages/19/bc/e7140ed90c5d61d77cea142eed9f9c303f4c4806f60a1044c13e3f1471d0/markupsafe-3.0.3-cp313-cp313-win32.whl", hash = "sha256:bdd37121970bfd8be76c5fb069c7751683bdf373db1ed6c010162b2a130248ed", size = 14543, upload-time = "2025-09-27T18:36:51.584Z" }, + { url = "https://files.pythonhosted.org/packages/05/73/c4abe620b841b6b791f2edc248f556900667a5a1cf023a6646967ae98335/markupsafe-3.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:9a1abfdc021a164803f4d485104931fb8f8c1efd55bc6b748d2f5774e78b62c5", size = 15113, upload-time = "2025-09-27T18:36:52.537Z" }, + { url = "https://files.pythonhosted.org/packages/f0/3a/fa34a0f7cfef23cf9500d68cb7c32dd64ffd58a12b09225fb03dd37d5b80/markupsafe-3.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:7e68f88e5b8799aa49c85cd116c932a1ac15caaa3f5db09087854d218359e485", size = 13911, upload-time = "2025-09-27T18:36:53.513Z" }, + { url = "https://files.pythonhosted.org/packages/e4/d7/e05cd7efe43a88a17a37b3ae96e79a19e846f3f456fe79c57ca61356ef01/markupsafe-3.0.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:218551f6df4868a8d527e3062d0fb968682fe92054e89978594c28e642c43a73", size = 11658, upload-time = "2025-09-27T18:36:54.819Z" }, + { url = "https://files.pythonhosted.org/packages/99/9e/e412117548182ce2148bdeacdda3bb494260c0b0184360fe0d56389b523b/markupsafe-3.0.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3524b778fe5cfb3452a09d31e7b5adefeea8c5be1d43c4f810ba09f2ceb29d37", size = 12066, upload-time = "2025-09-27T18:36:55.714Z" }, + { url = "https://files.pythonhosted.org/packages/bc/e6/fa0ffcda717ef64a5108eaa7b4f5ed28d56122c9a6d70ab8b72f9f715c80/markupsafe-3.0.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4e885a3d1efa2eadc93c894a21770e4bc67899e3543680313b09f139e149ab19", size = 25639, upload-time = "2025-09-27T18:36:56.908Z" }, + { url = "https://files.pythonhosted.org/packages/96/ec/2102e881fe9d25fc16cb4b25d5f5cde50970967ffa5dddafdb771237062d/markupsafe-3.0.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8709b08f4a89aa7586de0aadc8da56180242ee0ada3999749b183aa23df95025", size = 23569, upload-time = "2025-09-27T18:36:57.913Z" }, + { url = "https://files.pythonhosted.org/packages/4b/30/6f2fce1f1f205fc9323255b216ca8a235b15860c34b6798f810f05828e32/markupsafe-3.0.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b8512a91625c9b3da6f127803b166b629725e68af71f8184ae7e7d54686a56d6", size = 23284, upload-time = "2025-09-27T18:36:58.833Z" }, + { url = "https://files.pythonhosted.org/packages/58/47/4a0ccea4ab9f5dcb6f79c0236d954acb382202721e704223a8aafa38b5c8/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9b79b7a16f7fedff2495d684f2b59b0457c3b493778c9eed31111be64d58279f", size = 24801, upload-time = "2025-09-27T18:36:59.739Z" }, + { url = "https://files.pythonhosted.org/packages/6a/70/3780e9b72180b6fecb83a4814d84c3bf4b4ae4bf0b19c27196104149734c/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:12c63dfb4a98206f045aa9563db46507995f7ef6d83b2f68eda65c307c6829eb", size = 22769, upload-time = "2025-09-27T18:37:00.719Z" }, + { url = "https://files.pythonhosted.org/packages/98/c5/c03c7f4125180fc215220c035beac6b9cb684bc7a067c84fc69414d315f5/markupsafe-3.0.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:8f71bc33915be5186016f675cd83a1e08523649b0e33efdb898db577ef5bb009", size = 23642, upload-time = "2025-09-27T18:37:01.673Z" }, + { url = "https://files.pythonhosted.org/packages/80/d6/2d1b89f6ca4bff1036499b1e29a1d02d282259f3681540e16563f27ebc23/markupsafe-3.0.3-cp313-cp313t-win32.whl", hash = "sha256:69c0b73548bc525c8cb9a251cddf1931d1db4d2258e9599c28c07ef3580ef354", size = 14612, upload-time = "2025-09-27T18:37:02.639Z" }, + { url = "https://files.pythonhosted.org/packages/2b/98/e48a4bfba0a0ffcf9925fe2d69240bfaa19c6f7507b8cd09c70684a53c1e/markupsafe-3.0.3-cp313-cp313t-win_amd64.whl", hash = "sha256:1b4b79e8ebf6b55351f0d91fe80f893b4743f104bff22e90697db1590e47a218", size = 15200, upload-time = "2025-09-27T18:37:03.582Z" }, + { url = "https://files.pythonhosted.org/packages/0e/72/e3cc540f351f316e9ed0f092757459afbc595824ca724cbc5a5d4263713f/markupsafe-3.0.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ad2cf8aa28b8c020ab2fc8287b0f823d0a7d8630784c31e9ee5edea20f406287", size = 13973, upload-time = "2025-09-27T18:37:04.929Z" }, + { url = "https://files.pythonhosted.org/packages/33/8a/8e42d4838cd89b7dde187011e97fe6c3af66d8c044997d2183fbd6d31352/markupsafe-3.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:eaa9599de571d72e2daf60164784109f19978b327a3910d3e9de8c97b5b70cfe", size = 11619, upload-time = "2025-09-27T18:37:06.342Z" }, + { url = "https://files.pythonhosted.org/packages/b5/64/7660f8a4a8e53c924d0fa05dc3a55c9cee10bbd82b11c5afb27d44b096ce/markupsafe-3.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c47a551199eb8eb2121d4f0f15ae0f923d31350ab9280078d1e5f12b249e0026", size = 12029, upload-time = "2025-09-27T18:37:07.213Z" }, + { url = "https://files.pythonhosted.org/packages/da/ef/e648bfd021127bef5fa12e1720ffed0c6cbb8310c8d9bea7266337ff06de/markupsafe-3.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f34c41761022dd093b4b6896d4810782ffbabe30f2d443ff5f083e0cbbb8c737", size = 24408, upload-time = "2025-09-27T18:37:09.572Z" }, + { url = "https://files.pythonhosted.org/packages/41/3c/a36c2450754618e62008bf7435ccb0f88053e07592e6028a34776213d877/markupsafe-3.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:457a69a9577064c05a97c41f4e65148652db078a3a509039e64d3467b9e7ef97", size = 23005, upload-time = "2025-09-27T18:37:10.58Z" }, + { url = "https://files.pythonhosted.org/packages/bc/20/b7fdf89a8456b099837cd1dc21974632a02a999ec9bf7ca3e490aacd98e7/markupsafe-3.0.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e8afc3f2ccfa24215f8cb28dcf43f0113ac3c37c2f0f0806d8c70e4228c5cf4d", size = 22048, upload-time = "2025-09-27T18:37:11.547Z" }, + { url = "https://files.pythonhosted.org/packages/9a/a7/591f592afdc734f47db08a75793a55d7fbcc6902a723ae4cfbab61010cc5/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ec15a59cf5af7be74194f7ab02d0f59a62bdcf1a537677ce67a2537c9b87fcda", size = 23821, upload-time = "2025-09-27T18:37:12.48Z" }, + { url = "https://files.pythonhosted.org/packages/7d/33/45b24e4f44195b26521bc6f1a82197118f74df348556594bd2262bda1038/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:0eb9ff8191e8498cca014656ae6b8d61f39da5f95b488805da4bb029cccbfbaf", size = 21606, upload-time = "2025-09-27T18:37:13.485Z" }, + { url = "https://files.pythonhosted.org/packages/ff/0e/53dfaca23a69fbfbbf17a4b64072090e70717344c52eaaaa9c5ddff1e5f0/markupsafe-3.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2713baf880df847f2bece4230d4d094280f4e67b1e813eec43b4c0e144a34ffe", size = 23043, upload-time = "2025-09-27T18:37:14.408Z" }, + { url = "https://files.pythonhosted.org/packages/46/11/f333a06fc16236d5238bfe74daccbca41459dcd8d1fa952e8fbd5dccfb70/markupsafe-3.0.3-cp314-cp314-win32.whl", hash = "sha256:729586769a26dbceff69f7a7dbbf59ab6572b99d94576a5592625d5b411576b9", size = 14747, upload-time = "2025-09-27T18:37:15.36Z" }, + { url = "https://files.pythonhosted.org/packages/28/52/182836104b33b444e400b14f797212f720cbc9ed6ba34c800639d154e821/markupsafe-3.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:bdc919ead48f234740ad807933cdf545180bfbe9342c2bb451556db2ed958581", size = 15341, upload-time = "2025-09-27T18:37:16.496Z" }, + { url = "https://files.pythonhosted.org/packages/6f/18/acf23e91bd94fd7b3031558b1f013adfa21a8e407a3fdb32745538730382/markupsafe-3.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:5a7d5dc5140555cf21a6fefbdbf8723f06fcd2f63ef108f2854de715e4422cb4", size = 14073, upload-time = "2025-09-27T18:37:17.476Z" }, + { url = "https://files.pythonhosted.org/packages/3c/f0/57689aa4076e1b43b15fdfa646b04653969d50cf30c32a102762be2485da/markupsafe-3.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1353ef0c1b138e1907ae78e2f6c63ff67501122006b0f9abad68fda5f4ffc6ab", size = 11661, upload-time = "2025-09-27T18:37:18.453Z" }, + { url = "https://files.pythonhosted.org/packages/89/c3/2e67a7ca217c6912985ec766c6393b636fb0c2344443ff9d91404dc4c79f/markupsafe-3.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1085e7fbddd3be5f89cc898938f42c0b3c711fdcb37d75221de2666af647c175", size = 12069, upload-time = "2025-09-27T18:37:19.332Z" }, + { url = "https://files.pythonhosted.org/packages/f0/00/be561dce4e6ca66b15276e184ce4b8aec61fe83662cce2f7d72bd3249d28/markupsafe-3.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1b52b4fb9df4eb9ae465f8d0c228a00624de2334f216f178a995ccdcf82c4634", size = 25670, upload-time = "2025-09-27T18:37:20.245Z" }, + { url = "https://files.pythonhosted.org/packages/50/09/c419f6f5a92e5fadde27efd190eca90f05e1261b10dbd8cbcb39cd8ea1dc/markupsafe-3.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed51ac40f757d41b7c48425901843666a6677e3e8eb0abcff09e4ba6e664f50", size = 23598, upload-time = "2025-09-27T18:37:21.177Z" }, + { url = "https://files.pythonhosted.org/packages/22/44/a0681611106e0b2921b3033fc19bc53323e0b50bc70cffdd19f7d679bb66/markupsafe-3.0.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f190daf01f13c72eac4efd5c430a8de82489d9cff23c364c3ea822545032993e", size = 23261, upload-time = "2025-09-27T18:37:22.167Z" }, + { url = "https://files.pythonhosted.org/packages/5f/57/1b0b3f100259dc9fffe780cfb60d4be71375510e435efec3d116b6436d43/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e56b7d45a839a697b5eb268c82a71bd8c7f6c94d6fd50c3d577fa39a9f1409f5", size = 24835, upload-time = "2025-09-27T18:37:23.296Z" }, + { url = "https://files.pythonhosted.org/packages/26/6a/4bf6d0c97c4920f1597cc14dd720705eca0bf7c787aebc6bb4d1bead5388/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f3e98bb3798ead92273dc0e5fd0f31ade220f59a266ffd8a4f6065e0a3ce0523", size = 22733, upload-time = "2025-09-27T18:37:24.237Z" }, + { url = "https://files.pythonhosted.org/packages/14/c7/ca723101509b518797fedc2fdf79ba57f886b4aca8a7d31857ba3ee8281f/markupsafe-3.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5678211cb9333a6468fb8d8be0305520aa073f50d17f089b5b4b477ea6e67fdc", size = 23672, upload-time = "2025-09-27T18:37:25.271Z" }, + { url = "https://files.pythonhosted.org/packages/fb/df/5bd7a48c256faecd1d36edc13133e51397e41b73bb77e1a69deab746ebac/markupsafe-3.0.3-cp314-cp314t-win32.whl", hash = "sha256:915c04ba3851909ce68ccc2b8e2cd691618c4dc4c4232fb7982bca3f41fd8c3d", size = 14819, upload-time = "2025-09-27T18:37:26.285Z" }, + { url = "https://files.pythonhosted.org/packages/1a/8a/0402ba61a2f16038b48b39bccca271134be00c5c9f0f623208399333c448/markupsafe-3.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4faffd047e07c38848ce017e8725090413cd80cbc23d86e55c587bf979e579c9", size = 15426, upload-time = "2025-09-27T18:37:27.316Z" }, + { url = "https://files.pythonhosted.org/packages/70/bc/6f1c2f612465f5fa89b95bead1f44dcb607670fd42891d8fdcd5d039f4f4/markupsafe-3.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:32001d6a8fc98c8cb5c947787c5d08b0a50663d139f1305bac5885d98d9b40fa", size = 14146, upload-time = "2025-09-27T18:37:28.327Z" }, +] + +[[package]] +name = "mdurl" +version = "0.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, +] + +[[package]] +name = "ordered-set" +version = "4.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4c/ca/bfac8bc689799bcca4157e0e0ced07e70ce125193fc2e166d2e685b7e2fe/ordered-set-4.1.0.tar.gz", hash = "sha256:694a8e44c87657c59292ede72891eb91d34131f6531463aab3009191c77364a8", size = 12826, upload-time = "2022-01-26T14:38:56.6Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/33/55/af02708f230eb77084a299d7b08175cff006dea4f2721074b92cdb0296c0/ordered_set-4.1.0-py3-none-any.whl", hash = "sha256:046e1132c71fcf3330438a539928932caf51ddbc582496833e23de611de14562", size = 7634, upload-time = "2022-01-26T14:38:48.677Z" }, +] + +[[package]] +name = "pelican" +version = "4.12.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "blinker" }, + { name = "docutils" }, + { name = "feedgenerator" }, + { name = "jinja2" }, + { name = "ordered-set" }, + { name = "pygments" }, + { name = "python-dateutil" }, + { name = "rich" }, + { name = "tzdata", marker = "sys_platform == 'win32'" }, + { name = "unidecode" }, + { name = "watchfiles" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c4/8d/da26b77f0d9827d341bdedea357ccb5670717e3a9b4142e3e44c7f34db44/pelican-4.12.0.tar.gz", hash = "sha256:3983b5d2dc84c7bdf967154359077a2b78c0bbd2f7dcc55292133a7779609458", size = 1252907, upload-time = "2026-04-20T15:30:17.322Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6e/55/4adcce41a45f8f77e69d7e84ea447819dae1a78b4b9762a104599e5ec811/pelican-4.12.0-py3-none-any.whl", hash = "sha256:3697230f56cfcca9e98d3ac9ac26f655bb20cad807f7eacf156601e241f69ad8", size = 1358275, upload-time = "2026-04-20T15:30:15.383Z" }, +] + +[package.optional-dependencies] +markdown = [ + { name = "markdown" }, +] + +[[package]] +name = "pelican-sitemap" +version = "1.2.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pelican" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5c/c1/d9e1d539decfba947d711bcb37427ad15914557a728418bd928d56e58a32/pelican_sitemap-1.2.2.tar.gz", hash = "sha256:93f72d035dd0ec2f5cee38b2766bbd7f6a54bf186635ae1261a6deac422dcfb7", size = 8013, upload-time = "2025-10-12T15:24:36.727Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/68/c2/d2f98364b49a40bac9f315f29d8c22322b47bc4ebdec6a8e3a4f657ebc24/pelican_sitemap-1.2.2-py3-none-any.whl", hash = "sha256:09ba150dd1b54ef855f18e7ec920160d7118e932e0dac1c6e8bf3a41e938e682", size = 8046, upload-time = "2025-10-12T15:24:35.678Z" }, +] + +[[package]] +name = "pygments" +version = "2.19.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, +] + +[[package]] +name = "pypandoc-binary" +version = "1.17" +source = { registry = "https://pypi.org/simple" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/80/85/681a54111f0948821a5cf87ce30a88bb0a3f6848af5112c912abac4a2b77/pypandoc_binary-1.17-py3-none-macosx_10_9_x86_64.whl", hash = "sha256:734726dc618ef276343e272e1a6b4567e59c2ef9ef41d5533042deac3b0531f1", size = 25553945, upload-time = "2026-03-14T22:38:47.91Z" }, + { url = "https://files.pythonhosted.org/packages/15/58/8fd107c68522957868c1e785fbea7595608df118e440e424d189668294df/pypandoc_binary-1.17-py3-none-macosx_11_0_arm64.whl", hash = "sha256:fcfd28f347ed998dda28823fc6bc24f9310e7fdf3ddceaf925bf0563a100ab5b", size = 25553944, upload-time = "2026-03-14T22:38:50.74Z" }, + { url = "https://files.pythonhosted.org/packages/f4/27/ac1078239aae14b94c51975b7f46ad8e099e47d7ae26c175a5486b1c0099/pypandoc_binary-1.17-py3-none-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d6b620b21c9374e3e48aabd518492bf0776b148442ee28816f6aaf52da3d4387", size = 34460960, upload-time = "2026-03-14T22:38:53.391Z" }, + { url = "https://files.pythonhosted.org/packages/8d/7f/1e5612b52900ebe590862dabeadf546f739b27527dcd8bfd632f8adac1be/pypandoc_binary-1.17-py3-none-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9ada156cb980cd54fd6534231788e668c00dbb591cbd24f0be0bd86812eb8788", size = 36867598, upload-time = "2026-03-14T22:38:56.351Z" }, + { url = "https://files.pythonhosted.org/packages/3b/31/a5a867159c4080e5d368f4a53540a727501a2f31affc297dc8e0fced96a7/pypandoc_binary-1.17-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:2f439dcd211183bb3460253ca4511101df6e1acf4a01f45f5617e1fa2ad24279", size = 36867584, upload-time = "2026-03-14T22:38:59.087Z" }, + { url = "https://files.pythonhosted.org/packages/0d/2d/6a51cd4e54bdf132c19416801077c34bd40ba182e85d843360d36ae03a2d/pypandoc_binary-1.17-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:f6e6d3e4cfafbe23189a08db3d41f8def260bacd6e7e382bceadab7ba1f17da6", size = 34460949, upload-time = "2026-03-14T22:39:01.71Z" }, + { url = "https://files.pythonhosted.org/packages/c6/b9/f47b77ba75ed5d47ec85fcc2ecfbf7f78e3a73347f3a09836634d930de98/pypandoc_binary-1.17-py3-none-win_amd64.whl", hash = "sha256:76fae066cd2d7e78fb97f0ec8e9e36f437b07187b689b0b415ca18216f8f898a", size = 40891661, upload-time = "2026-03-14T22:39:04.782Z" }, +] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, +] + +[[package]] +name = "rich" +version = "15.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown-it-py" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c0/8f/0722ca900cc807c13a6a0c696dacf35430f72e0ec571c4275d2371fca3e9/rich-15.0.0.tar.gz", hash = "sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36", size = 230680, upload-time = "2026-04-12T08:24:00.75Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/82/3b/64d4899d73f91ba49a8c18a8ff3f0ea8f1c1d75481760df8c68ef5235bf5/rich-15.0.0-py3-none-any.whl", hash = "sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb", size = 310654, upload-time = "2026-04-12T08:24:02.83Z" }, +] + +[[package]] +name = "six" +version = "1.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, +] + +[[package]] +name = "smartypants" +version = "2.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6c/8f/a033f78196d9467b402d100ec40b95166d43fa2642693f23f771473d8195/smartypants-2.0.2.tar.gz", hash = "sha256:39d64ce1d7cc6964b698297bdf391bc12c3251b7f608e6e55d857cd7c5f800c6", size = 16392, upload-time = "2025-06-17T07:59:48.122Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/39/2c/f12558bff677defbfc64bf32441daec245df608dd2d9a12168f1d766ad75/smartypants-2.0.2-py2.py3-none-any.whl", hash = "sha256:9471578606e8ee0740065bf8771f55fec8c83313cb98c5d1c1864ddd389d0f3a", size = 10168, upload-time = "2025-06-17T07:59:46.765Z" }, +] + +[[package]] +name = "tornado" +version = "6.5.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f8/f1/3173dfa4a18db4a9b03e5d55325559dab51ee653763bb8745a75af491286/tornado-6.5.5.tar.gz", hash = "sha256:192b8f3ea91bd7f1f50c06955416ed76c6b72f96779b962f07f911b91e8d30e9", size = 516006, upload-time = "2026-03-10T21:31:02.067Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/59/8c/77f5097695f4dd8255ecbd08b2a1ed8ba8b953d337804dd7080f199e12bf/tornado-6.5.5-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:487dc9cc380e29f58c7ab88f9e27cdeef04b2140862e5076a66fb6bb68bb1bfa", size = 445983, upload-time = "2026-03-10T21:30:44.28Z" }, + { url = "https://files.pythonhosted.org/packages/ab/5e/7625b76cd10f98f1516c36ce0346de62061156352353ef2da44e5c21523c/tornado-6.5.5-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:65a7f1d46d4bb41df1ac99f5fcb685fb25c7e61613742d5108b010975a9a6521", size = 444246, upload-time = "2026-03-10T21:30:46.571Z" }, + { url = "https://files.pythonhosted.org/packages/b2/04/7b5705d5b3c0fab088f434f9c83edac1573830ca49ccf29fb83bf7178eec/tornado-6.5.5-cp39-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:e74c92e8e65086b338fd56333fb9a68b9f6f2fe7ad532645a290a464bcf46be5", size = 447229, upload-time = "2026-03-10T21:30:48.273Z" }, + { url = "https://files.pythonhosted.org/packages/34/01/74e034a30ef59afb4097ef8659515e96a39d910b712a89af76f5e4e1f93c/tornado-6.5.5-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:435319e9e340276428bbdb4e7fa732c2d399386d1de5686cb331ec8eee754f07", size = 448192, upload-time = "2026-03-10T21:30:51.22Z" }, + { url = "https://files.pythonhosted.org/packages/be/00/fe9e02c5a96429fce1a1d15a517f5d8444f9c412e0bb9eadfbe3b0fc55bf/tornado-6.5.5-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:3f54aa540bdbfee7b9eb268ead60e7d199de5021facd276819c193c0fb28ea4e", size = 448039, upload-time = "2026-03-10T21:30:53.52Z" }, + { url = "https://files.pythonhosted.org/packages/82/9e/656ee4cec0398b1d18d0f1eb6372c41c6b889722641d84948351ae19556d/tornado-6.5.5-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:36abed1754faeb80fbd6e64db2758091e1320f6bba74a4cf8c09cd18ccce8aca", size = 447445, upload-time = "2026-03-10T21:30:55.541Z" }, + { url = "https://files.pythonhosted.org/packages/5a/76/4921c00511f88af86a33de770d64141170f1cfd9c00311aea689949e274e/tornado-6.5.5-cp39-abi3-win32.whl", hash = "sha256:dd3eafaaeec1c7f2f8fdcd5f964e8907ad788fe8a5a32c4426fbbdda621223b7", size = 448582, upload-time = "2026-03-10T21:30:57.142Z" }, + { url = "https://files.pythonhosted.org/packages/2c/23/f6c6112a04d28eed765e374435fb1a9198f73e1ec4b4024184f21faeb1ad/tornado-6.5.5-cp39-abi3-win_amd64.whl", hash = "sha256:6443a794ba961a9f619b1ae926a2e900ac20c34483eea67be4ed8f1e58d3ef7b", size = 448990, upload-time = "2026-03-10T21:30:58.857Z" }, + { url = "https://files.pythonhosted.org/packages/b7/c8/876602cbc96469911f0939f703453c1157b0c826ecb05bdd32e023397d4e/tornado-6.5.5-cp39-abi3-win_arm64.whl", hash = "sha256:2c9a876e094109333f888539ddb2de4361743e5d21eece20688e3e351e4990a6", size = 448016, upload-time = "2026-03-10T21:31:00.43Z" }, +] + +[[package]] +name = "typing-extensions" +version = "4.15.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, +] + +[[package]] +name = "typogrify" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "smartypants" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/93/8c/b73fe0050bbf67c172b7c6d0c74c356939de0e891e669667f20381c099a8/typogrify-2.1.0.tar.gz", hash = "sha256:f0aa004e98032a6e6be4c9da65e7eb7150e36ca3bf508adbcda82b4d003e61ee", size = 28622, upload-time = "2025-01-12T16:38:12.431Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ab/7f/3221bc6bd429a78e37b96aac309a66512af35360b69c67d20bb5e4ef4e5b/typogrify-2.1.0-py3-none-any.whl", hash = "sha256:fdfd2bf8ad3df7296074187e89a890b68b116263bd4e0f4aefe768291b0d854e", size = 12411, upload-time = "2025-01-12T16:38:11.112Z" }, +] + +[[package]] +name = "tzdata" +version = "2026.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ba/19/1b9b0e29f30c6d35cb345486df41110984ea67ae69dddbc0e8a100999493/tzdata-2026.2.tar.gz", hash = "sha256:9173fde7d80d9018e02a662e168e5a2d04f87c41ea174b139fbef642eda62d10", size = 198254, upload-time = "2026-04-24T15:22:08.651Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/e4/dccd7f47c4b64213ac01ef921a1337ee6e30e8c6466046018326977efd95/tzdata-2026.2-py2.py3-none-any.whl", hash = "sha256:bbe9af844f658da81a5f95019480da3a89415801f6cc966806612cc7169bffe7", size = 349321, upload-time = "2026-04-24T15:22:05.876Z" }, +] + +[[package]] +name = "unidecode" +version = "1.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/94/7d/a8a765761bbc0c836e397a2e48d498305a865b70a8600fd7a942e85dcf63/Unidecode-1.4.0.tar.gz", hash = "sha256:ce35985008338b676573023acc382d62c264f307c8f7963733405add37ea2b23", size = 200149, upload-time = "2025-04-24T08:45:03.798Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8f/b7/559f59d57d18b44c6d1250d2eeaa676e028b9c527431f5d0736478a73ba1/Unidecode-1.4.0-py3-none-any.whl", hash = "sha256:c3c7606c27503ad8d501270406e345ddb480a7b5f38827eafe4fa82a137f0021", size = 235837, upload-time = "2025-04-24T08:45:01.609Z" }, +] + +[[package]] +name = "watchfiles" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c2/c9/8869df9b2a2d6c59d79220a4db37679e74f807c559ffe5265e08b227a210/watchfiles-1.1.1.tar.gz", hash = "sha256:a173cb5c16c4f40ab19cecf48a534c409f7ea983ab8fed0741304a1c0a31b3f2", size = 94440, upload-time = "2025-10-14T15:06:21.08Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1f/f8/2c5f479fb531ce2f0564eda479faecf253d886b1ab3630a39b7bf7362d46/watchfiles-1.1.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:f57b396167a2565a4e8b5e56a5a1c537571733992b226f4f1197d79e94cf0ae5", size = 406529, upload-time = "2025-10-14T15:04:32.899Z" }, + { url = "https://files.pythonhosted.org/packages/fe/cd/f515660b1f32f65df671ddf6f85bfaca621aee177712874dc30a97397977/watchfiles-1.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:421e29339983e1bebc281fab40d812742268ad057db4aee8c4d2bce0af43b741", size = 394384, upload-time = "2025-10-14T15:04:33.761Z" }, + { url = "https://files.pythonhosted.org/packages/7b/c3/28b7dc99733eab43fca2d10f55c86e03bd6ab11ca31b802abac26b23d161/watchfiles-1.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6e43d39a741e972bab5d8100b5cdacf69db64e34eb19b6e9af162bccf63c5cc6", size = 448789, upload-time = "2025-10-14T15:04:34.679Z" }, + { url = "https://files.pythonhosted.org/packages/4a/24/33e71113b320030011c8e4316ccca04194bf0cbbaeee207f00cbc7d6b9f5/watchfiles-1.1.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f537afb3276d12814082a2e9b242bdcf416c2e8fd9f799a737990a1dbe906e5b", size = 460521, upload-time = "2025-10-14T15:04:35.963Z" }, + { url = "https://files.pythonhosted.org/packages/f4/c3/3c9a55f255aa57b91579ae9e98c88704955fa9dac3e5614fb378291155df/watchfiles-1.1.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b2cd9e04277e756a2e2d2543d65d1e2166d6fd4c9b183f8808634fda23f17b14", size = 488722, upload-time = "2025-10-14T15:04:37.091Z" }, + { url = "https://files.pythonhosted.org/packages/49/36/506447b73eb46c120169dc1717fe2eff07c234bb3232a7200b5f5bd816e9/watchfiles-1.1.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5f3f58818dc0b07f7d9aa7fe9eb1037aecb9700e63e1f6acfed13e9fef648f5d", size = 596088, upload-time = "2025-10-14T15:04:38.39Z" }, + { url = "https://files.pythonhosted.org/packages/82/ab/5f39e752a9838ec4d52e9b87c1e80f1ee3ccdbe92e183c15b6577ab9de16/watchfiles-1.1.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9bb9f66367023ae783551042d31b1d7fd422e8289eedd91f26754a66f44d5cff", size = 472923, upload-time = "2025-10-14T15:04:39.666Z" }, + { url = "https://files.pythonhosted.org/packages/af/b9/a419292f05e302dea372fa7e6fda5178a92998411f8581b9830d28fb9edb/watchfiles-1.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aebfd0861a83e6c3d1110b78ad54704486555246e542be3e2bb94195eabb2606", size = 456080, upload-time = "2025-10-14T15:04:40.643Z" }, + { url = "https://files.pythonhosted.org/packages/b0/c3/d5932fd62bde1a30c36e10c409dc5d54506726f08cb3e1d8d0ba5e2bc8db/watchfiles-1.1.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5fac835b4ab3c6487b5dbad78c4b3724e26bcc468e886f8ba8cc4306f68f6701", size = 629432, upload-time = "2025-10-14T15:04:41.789Z" }, + { url = "https://files.pythonhosted.org/packages/f7/77/16bddd9779fafb795f1a94319dc965209c5641db5bf1edbbccace6d1b3c0/watchfiles-1.1.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:399600947b170270e80134ac854e21b3ccdefa11a9529a3decc1327088180f10", size = 623046, upload-time = "2025-10-14T15:04:42.718Z" }, + { url = "https://files.pythonhosted.org/packages/46/ef/f2ecb9a0f342b4bfad13a2787155c6ee7ce792140eac63a34676a2feeef2/watchfiles-1.1.1-cp311-cp311-win32.whl", hash = "sha256:de6da501c883f58ad50db3a32ad397b09ad29865b5f26f64c24d3e3281685849", size = 271473, upload-time = "2025-10-14T15:04:43.624Z" }, + { url = "https://files.pythonhosted.org/packages/94/bc/f42d71125f19731ea435c3948cad148d31a64fccde3867e5ba4edee901f9/watchfiles-1.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:35c53bd62a0b885bf653ebf6b700d1bf05debb78ad9292cf2a942b23513dc4c4", size = 287598, upload-time = "2025-10-14T15:04:44.516Z" }, + { url = "https://files.pythonhosted.org/packages/57/c9/a30f897351f95bbbfb6abcadafbaca711ce1162f4db95fc908c98a9165f3/watchfiles-1.1.1-cp311-cp311-win_arm64.whl", hash = "sha256:57ca5281a8b5e27593cb7d82c2ac927ad88a96ed406aa446f6344e4328208e9e", size = 277210, upload-time = "2025-10-14T15:04:45.883Z" }, + { url = "https://files.pythonhosted.org/packages/74/d5/f039e7e3c639d9b1d09b07ea412a6806d38123f0508e5f9b48a87b0a76cc/watchfiles-1.1.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:8c89f9f2f740a6b7dcc753140dd5e1ab9215966f7a3530d0c0705c83b401bd7d", size = 404745, upload-time = "2025-10-14T15:04:46.731Z" }, + { url = "https://files.pythonhosted.org/packages/a5/96/a881a13aa1349827490dab2d363c8039527060cfcc2c92cc6d13d1b1049e/watchfiles-1.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bd404be08018c37350f0d6e34676bd1e2889990117a2b90070b3007f172d0610", size = 391769, upload-time = "2025-10-14T15:04:48.003Z" }, + { url = "https://files.pythonhosted.org/packages/4b/5b/d3b460364aeb8da471c1989238ea0e56bec24b6042a68046adf3d9ddb01c/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8526e8f916bb5b9a0a777c8317c23ce65de259422bba5b31325a6fa6029d33af", size = 449374, upload-time = "2025-10-14T15:04:49.179Z" }, + { url = "https://files.pythonhosted.org/packages/b9/44/5769cb62d4ed055cb17417c0a109a92f007114a4e07f30812a73a4efdb11/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2edc3553362b1c38d9f06242416a5d8e9fe235c204a4072e988ce2e5bb1f69f6", size = 459485, upload-time = "2025-10-14T15:04:50.155Z" }, + { url = "https://files.pythonhosted.org/packages/19/0c/286b6301ded2eccd4ffd0041a1b726afda999926cf720aab63adb68a1e36/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:30f7da3fb3f2844259cba4720c3fc7138eb0f7b659c38f3bfa65084c7fc7abce", size = 488813, upload-time = "2025-10-14T15:04:51.059Z" }, + { url = "https://files.pythonhosted.org/packages/c7/2b/8530ed41112dd4a22f4dcfdb5ccf6a1baad1ff6eed8dc5a5f09e7e8c41c7/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f8979280bdafff686ba5e4d8f97840f929a87ed9cdf133cbbd42f7766774d2aa", size = 594816, upload-time = "2025-10-14T15:04:52.031Z" }, + { url = "https://files.pythonhosted.org/packages/ce/d2/f5f9fb49489f184f18470d4f99f4e862a4b3e9ac2865688eb2099e3d837a/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dcc5c24523771db3a294c77d94771abcfcb82a0e0ee8efd910c37c59ec1b31bb", size = 475186, upload-time = "2025-10-14T15:04:53.064Z" }, + { url = "https://files.pythonhosted.org/packages/cf/68/5707da262a119fb06fbe214d82dd1fe4a6f4af32d2d14de368d0349eb52a/watchfiles-1.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1db5d7ae38ff20153d542460752ff397fcf5c96090c1230803713cf3147a6803", size = 456812, upload-time = "2025-10-14T15:04:55.174Z" }, + { url = "https://files.pythonhosted.org/packages/66/ab/3cbb8756323e8f9b6f9acb9ef4ec26d42b2109bce830cc1f3468df20511d/watchfiles-1.1.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:28475ddbde92df1874b6c5c8aaeb24ad5be47a11f87cde5a28ef3835932e3e94", size = 630196, upload-time = "2025-10-14T15:04:56.22Z" }, + { url = "https://files.pythonhosted.org/packages/78/46/7152ec29b8335f80167928944a94955015a345440f524d2dfe63fc2f437b/watchfiles-1.1.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:36193ed342f5b9842edd3532729a2ad55c4160ffcfa3700e0d54be496b70dd43", size = 622657, upload-time = "2025-10-14T15:04:57.521Z" }, + { url = "https://files.pythonhosted.org/packages/0a/bf/95895e78dd75efe9a7f31733607f384b42eb5feb54bd2eb6ed57cc2e94f4/watchfiles-1.1.1-cp312-cp312-win32.whl", hash = "sha256:859e43a1951717cc8de7f4c77674a6d389b106361585951d9e69572823f311d9", size = 272042, upload-time = "2025-10-14T15:04:59.046Z" }, + { url = "https://files.pythonhosted.org/packages/87/0a/90eb755f568de2688cb220171c4191df932232c20946966c27a59c400850/watchfiles-1.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:91d4c9a823a8c987cce8fa2690923b069966dabb196dd8d137ea2cede885fde9", size = 288410, upload-time = "2025-10-14T15:05:00.081Z" }, + { url = "https://files.pythonhosted.org/packages/36/76/f322701530586922fbd6723c4f91ace21364924822a8772c549483abed13/watchfiles-1.1.1-cp312-cp312-win_arm64.whl", hash = "sha256:a625815d4a2bdca61953dbba5a39d60164451ef34c88d751f6c368c3ea73d404", size = 278209, upload-time = "2025-10-14T15:05:01.168Z" }, + { url = "https://files.pythonhosted.org/packages/bb/f4/f750b29225fe77139f7ae5de89d4949f5a99f934c65a1f1c0b248f26f747/watchfiles-1.1.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:130e4876309e8686a5e37dba7d5e9bc77e6ed908266996ca26572437a5271e18", size = 404321, upload-time = "2025-10-14T15:05:02.063Z" }, + { url = "https://files.pythonhosted.org/packages/2b/f9/f07a295cde762644aa4c4bb0f88921d2d141af45e735b965fb2e87858328/watchfiles-1.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5f3bde70f157f84ece3765b42b4a52c6ac1a50334903c6eaf765362f6ccca88a", size = 391783, upload-time = "2025-10-14T15:05:03.052Z" }, + { url = "https://files.pythonhosted.org/packages/bc/11/fc2502457e0bea39a5c958d86d2cb69e407a4d00b85735ca724bfa6e0d1a/watchfiles-1.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:14e0b1fe858430fc0251737ef3824c54027bedb8c37c38114488b8e131cf8219", size = 449279, upload-time = "2025-10-14T15:05:04.004Z" }, + { url = "https://files.pythonhosted.org/packages/e3/1f/d66bc15ea0b728df3ed96a539c777acfcad0eb78555ad9efcaa1274688f0/watchfiles-1.1.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f27db948078f3823a6bb3b465180db8ebecf26dd5dae6f6180bd87383b6b4428", size = 459405, upload-time = "2025-10-14T15:05:04.942Z" }, + { url = "https://files.pythonhosted.org/packages/be/90/9f4a65c0aec3ccf032703e6db02d89a157462fbb2cf20dd415128251cac0/watchfiles-1.1.1-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:059098c3a429f62fc98e8ec62b982230ef2c8df68c79e826e37b895bc359a9c0", size = 488976, upload-time = "2025-10-14T15:05:05.905Z" }, + { url = "https://files.pythonhosted.org/packages/37/57/ee347af605d867f712be7029bb94c8c071732a4b44792e3176fa3c612d39/watchfiles-1.1.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bfb5862016acc9b869bb57284e6cb35fdf8e22fe59f7548858e2f971d045f150", size = 595506, upload-time = "2025-10-14T15:05:06.906Z" }, + { url = "https://files.pythonhosted.org/packages/a8/78/cc5ab0b86c122047f75e8fc471c67a04dee395daf847d3e59381996c8707/watchfiles-1.1.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:319b27255aacd9923b8a276bb14d21a5f7ff82564c744235fc5eae58d95422ae", size = 474936, upload-time = "2025-10-14T15:05:07.906Z" }, + { url = "https://files.pythonhosted.org/packages/62/da/def65b170a3815af7bd40a3e7010bf6ab53089ef1b75d05dd5385b87cf08/watchfiles-1.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c755367e51db90e75b19454b680903631d41f9e3607fbd941d296a020c2d752d", size = 456147, upload-time = "2025-10-14T15:05:09.138Z" }, + { url = "https://files.pythonhosted.org/packages/57/99/da6573ba71166e82d288d4df0839128004c67d2778d3b566c138695f5c0b/watchfiles-1.1.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c22c776292a23bfc7237a98f791b9ad3144b02116ff10d820829ce62dff46d0b", size = 630007, upload-time = "2025-10-14T15:05:10.117Z" }, + { url = "https://files.pythonhosted.org/packages/a8/51/7439c4dd39511368849eb1e53279cd3454b4a4dbace80bab88feeb83c6b5/watchfiles-1.1.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:3a476189be23c3686bc2f4321dd501cb329c0a0469e77b7b534ee10129ae6374", size = 622280, upload-time = "2025-10-14T15:05:11.146Z" }, + { url = "https://files.pythonhosted.org/packages/95/9c/8ed97d4bba5db6fdcdb2b298d3898f2dd5c20f6b73aee04eabe56c59677e/watchfiles-1.1.1-cp313-cp313-win32.whl", hash = "sha256:bf0a91bfb5574a2f7fc223cf95eeea79abfefa404bf1ea5e339c0c1560ae99a0", size = 272056, upload-time = "2025-10-14T15:05:12.156Z" }, + { url = "https://files.pythonhosted.org/packages/1f/f3/c14e28429f744a260d8ceae18bf58c1d5fa56b50d006a7a9f80e1882cb0d/watchfiles-1.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:52e06553899e11e8074503c8e716d574adeeb7e68913115c4b3653c53f9bae42", size = 288162, upload-time = "2025-10-14T15:05:13.208Z" }, + { url = "https://files.pythonhosted.org/packages/dc/61/fe0e56c40d5cd29523e398d31153218718c5786b5e636d9ae8ae79453d27/watchfiles-1.1.1-cp313-cp313-win_arm64.whl", hash = "sha256:ac3cc5759570cd02662b15fbcd9d917f7ecd47efe0d6b40474eafd246f91ea18", size = 277909, upload-time = "2025-10-14T15:05:14.49Z" }, + { url = "https://files.pythonhosted.org/packages/79/42/e0a7d749626f1e28c7108a99fb9bf524b501bbbeb9b261ceecde644d5a07/watchfiles-1.1.1-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:563b116874a9a7ce6f96f87cd0b94f7faf92d08d0021e837796f0a14318ef8da", size = 403389, upload-time = "2025-10-14T15:05:15.777Z" }, + { url = "https://files.pythonhosted.org/packages/15/49/08732f90ce0fbbc13913f9f215c689cfc9ced345fb1bcd8829a50007cc8d/watchfiles-1.1.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3ad9fe1dae4ab4212d8c91e80b832425e24f421703b5a42ef2e4a1e215aff051", size = 389964, upload-time = "2025-10-14T15:05:16.85Z" }, + { url = "https://files.pythonhosted.org/packages/27/0d/7c315d4bd5f2538910491a0393c56bf70d333d51bc5b34bee8e68e8cea19/watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce70f96a46b894b36eba678f153f052967a0d06d5b5a19b336ab0dbbd029f73e", size = 448114, upload-time = "2025-10-14T15:05:17.876Z" }, + { url = "https://files.pythonhosted.org/packages/c3/24/9e096de47a4d11bc4df41e9d1e61776393eac4cb6eb11b3e23315b78b2cc/watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cb467c999c2eff23a6417e58d75e5828716f42ed8289fe6b77a7e5a91036ca70", size = 460264, upload-time = "2025-10-14T15:05:18.962Z" }, + { url = "https://files.pythonhosted.org/packages/cc/0f/e8dea6375f1d3ba5fcb0b3583e2b493e77379834c74fd5a22d66d85d6540/watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:836398932192dae4146c8f6f737d74baeac8b70ce14831a239bdb1ca882fc261", size = 487877, upload-time = "2025-10-14T15:05:20.094Z" }, + { url = "https://files.pythonhosted.org/packages/ac/5b/df24cfc6424a12deb41503b64d42fbea6b8cb357ec62ca84a5a3476f654a/watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:743185e7372b7bc7c389e1badcc606931a827112fbbd37f14c537320fca08620", size = 595176, upload-time = "2025-10-14T15:05:21.134Z" }, + { url = "https://files.pythonhosted.org/packages/8f/b5/853b6757f7347de4e9b37e8cc3289283fb983cba1ab4d2d7144694871d9c/watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:afaeff7696e0ad9f02cbb8f56365ff4686ab205fcf9c4c5b6fdfaaa16549dd04", size = 473577, upload-time = "2025-10-14T15:05:22.306Z" }, + { url = "https://files.pythonhosted.org/packages/e1/f7/0a4467be0a56e80447c8529c9fce5b38eab4f513cb3d9bf82e7392a5696b/watchfiles-1.1.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f7eb7da0eb23aa2ba036d4f616d46906013a68caf61b7fdbe42fc8b25132e77", size = 455425, upload-time = "2025-10-14T15:05:23.348Z" }, + { url = "https://files.pythonhosted.org/packages/8e/e0/82583485ea00137ddf69bc84a2db88bd92ab4a6e3c405e5fb878ead8d0e7/watchfiles-1.1.1-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:831a62658609f0e5c64178211c942ace999517f5770fe9436be4c2faeba0c0ef", size = 628826, upload-time = "2025-10-14T15:05:24.398Z" }, + { url = "https://files.pythonhosted.org/packages/28/9a/a785356fccf9fae84c0cc90570f11702ae9571036fb25932f1242c82191c/watchfiles-1.1.1-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:f9a2ae5c91cecc9edd47e041a930490c31c3afb1f5e6d71de3dc671bfaca02bf", size = 622208, upload-time = "2025-10-14T15:05:25.45Z" }, + { url = "https://files.pythonhosted.org/packages/c3/f4/0872229324ef69b2c3edec35e84bd57a1289e7d3fe74588048ed8947a323/watchfiles-1.1.1-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:d1715143123baeeaeadec0528bb7441103979a1d5f6fd0e1f915383fea7ea6d5", size = 404315, upload-time = "2025-10-14T15:05:26.501Z" }, + { url = "https://files.pythonhosted.org/packages/7b/22/16d5331eaed1cb107b873f6ae1b69e9ced582fcf0c59a50cd84f403b1c32/watchfiles-1.1.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:39574d6370c4579d7f5d0ad940ce5b20db0e4117444e39b6d8f99db5676c52fd", size = 390869, upload-time = "2025-10-14T15:05:27.649Z" }, + { url = "https://files.pythonhosted.org/packages/b2/7e/5643bfff5acb6539b18483128fdc0ef2cccc94a5b8fbda130c823e8ed636/watchfiles-1.1.1-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7365b92c2e69ee952902e8f70f3ba6360d0d596d9299d55d7d386df84b6941fb", size = 449919, upload-time = "2025-10-14T15:05:28.701Z" }, + { url = "https://files.pythonhosted.org/packages/51/2e/c410993ba5025a9f9357c376f48976ef0e1b1aefb73b97a5ae01a5972755/watchfiles-1.1.1-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bfff9740c69c0e4ed32416f013f3c45e2ae42ccedd1167ef2d805c000b6c71a5", size = 460845, upload-time = "2025-10-14T15:05:30.064Z" }, + { url = "https://files.pythonhosted.org/packages/8e/a4/2df3b404469122e8680f0fcd06079317e48db58a2da2950fb45020947734/watchfiles-1.1.1-cp314-cp314-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b27cf2eb1dda37b2089e3907d8ea92922b673c0c427886d4edc6b94d8dfe5db3", size = 489027, upload-time = "2025-10-14T15:05:31.064Z" }, + { url = "https://files.pythonhosted.org/packages/ea/84/4587ba5b1f267167ee715b7f66e6382cca6938e0a4b870adad93e44747e6/watchfiles-1.1.1-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:526e86aced14a65a5b0ec50827c745597c782ff46b571dbfe46192ab9e0b3c33", size = 595615, upload-time = "2025-10-14T15:05:32.074Z" }, + { url = "https://files.pythonhosted.org/packages/6a/0f/c6988c91d06e93cd0bb3d4a808bcf32375ca1904609835c3031799e3ecae/watchfiles-1.1.1-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04e78dd0b6352db95507fd8cb46f39d185cf8c74e4cf1e4fbad1d3df96faf510", size = 474836, upload-time = "2025-10-14T15:05:33.209Z" }, + { url = "https://files.pythonhosted.org/packages/b4/36/ded8aebea91919485b7bbabbd14f5f359326cb5ec218cd67074d1e426d74/watchfiles-1.1.1-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c85794a4cfa094714fb9c08d4a218375b2b95b8ed1666e8677c349906246c05", size = 455099, upload-time = "2025-10-14T15:05:34.189Z" }, + { url = "https://files.pythonhosted.org/packages/98/e0/8c9bdba88af756a2fce230dd365fab2baf927ba42cd47521ee7498fd5211/watchfiles-1.1.1-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:74d5012b7630714b66be7b7b7a78855ef7ad58e8650c73afc4c076a1f480a8d6", size = 630626, upload-time = "2025-10-14T15:05:35.216Z" }, + { url = "https://files.pythonhosted.org/packages/2a/84/a95db05354bf2d19e438520d92a8ca475e578c647f78f53197f5a2f17aaf/watchfiles-1.1.1-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:8fbe85cb3201c7d380d3d0b90e63d520f15d6afe217165d7f98c9c649654db81", size = 622519, upload-time = "2025-10-14T15:05:36.259Z" }, + { url = "https://files.pythonhosted.org/packages/1d/ce/d8acdc8de545de995c339be67711e474c77d643555a9bb74a9334252bd55/watchfiles-1.1.1-cp314-cp314-win32.whl", hash = "sha256:3fa0b59c92278b5a7800d3ee7733da9d096d4aabcfabb9a928918bd276ef9b9b", size = 272078, upload-time = "2025-10-14T15:05:37.63Z" }, + { url = "https://files.pythonhosted.org/packages/c4/c9/a74487f72d0451524be827e8edec251da0cc1fcf111646a511ae752e1a3d/watchfiles-1.1.1-cp314-cp314-win_amd64.whl", hash = "sha256:c2047d0b6cea13b3316bdbafbfa0c4228ae593d995030fda39089d36e64fc03a", size = 287664, upload-time = "2025-10-14T15:05:38.95Z" }, + { url = "https://files.pythonhosted.org/packages/df/b8/8ac000702cdd496cdce998c6f4ee0ca1f15977bba51bdf07d872ebdfc34c/watchfiles-1.1.1-cp314-cp314-win_arm64.whl", hash = "sha256:842178b126593addc05acf6fce960d28bc5fae7afbaa2c6c1b3a7b9460e5be02", size = 277154, upload-time = "2025-10-14T15:05:39.954Z" }, + { url = "https://files.pythonhosted.org/packages/47/a8/e3af2184707c29f0f14b1963c0aace6529f9d1b8582d5b99f31bbf42f59e/watchfiles-1.1.1-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:88863fbbc1a7312972f1c511f202eb30866370ebb8493aef2812b9ff28156a21", size = 403820, upload-time = "2025-10-14T15:05:40.932Z" }, + { url = "https://files.pythonhosted.org/packages/c0/ec/e47e307c2f4bd75f9f9e8afbe3876679b18e1bcec449beca132a1c5ffb2d/watchfiles-1.1.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:55c7475190662e202c08c6c0f4d9e345a29367438cf8e8037f3155e10a88d5a5", size = 390510, upload-time = "2025-10-14T15:05:41.945Z" }, + { url = "https://files.pythonhosted.org/packages/d5/a0/ad235642118090f66e7b2f18fd5c42082418404a79205cdfca50b6309c13/watchfiles-1.1.1-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f53fa183d53a1d7a8852277c92b967ae99c2d4dcee2bfacff8868e6e30b15f7", size = 448408, upload-time = "2025-10-14T15:05:43.385Z" }, + { url = "https://files.pythonhosted.org/packages/df/85/97fa10fd5ff3332ae17e7e40e20784e419e28521549780869f1413742e9d/watchfiles-1.1.1-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6aae418a8b323732fa89721d86f39ec8f092fc2af67f4217a2b07fd3e93c6101", size = 458968, upload-time = "2025-10-14T15:05:44.404Z" }, + { url = "https://files.pythonhosted.org/packages/47/c2/9059c2e8966ea5ce678166617a7f75ecba6164375f3b288e50a40dc6d489/watchfiles-1.1.1-cp314-cp314t-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f096076119da54a6080e8920cbdaac3dbee667eb91dcc5e5b78840b87415bd44", size = 488096, upload-time = "2025-10-14T15:05:45.398Z" }, + { url = "https://files.pythonhosted.org/packages/94/44/d90a9ec8ac309bc26db808a13e7bfc0e4e78b6fc051078a554e132e80160/watchfiles-1.1.1-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:00485f441d183717038ed2e887a7c868154f216877653121068107b227a2f64c", size = 596040, upload-time = "2025-10-14T15:05:46.502Z" }, + { url = "https://files.pythonhosted.org/packages/95/68/4e3479b20ca305cfc561db3ed207a8a1c745ee32bf24f2026a129d0ddb6e/watchfiles-1.1.1-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a55f3e9e493158d7bfdb60a1165035f1cf7d320914e7b7ea83fe22c6023b58fc", size = 473847, upload-time = "2025-10-14T15:05:47.484Z" }, + { url = "https://files.pythonhosted.org/packages/4f/55/2af26693fd15165c4ff7857e38330e1b61ab8c37d15dc79118cdba115b7a/watchfiles-1.1.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c91ed27800188c2ae96d16e3149f199d62f86c7af5f5f4d2c61a3ed8cd3666c", size = 455072, upload-time = "2025-10-14T15:05:48.928Z" }, + { url = "https://files.pythonhosted.org/packages/66/1d/d0d200b10c9311ec25d2273f8aad8c3ef7cc7ea11808022501811208a750/watchfiles-1.1.1-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:311ff15a0bae3714ffb603e6ba6dbfba4065ab60865d15a6ec544133bdb21099", size = 629104, upload-time = "2025-10-14T15:05:49.908Z" }, + { url = "https://files.pythonhosted.org/packages/e3/bd/fa9bb053192491b3867ba07d2343d9f2252e00811567d30ae8d0f78136fe/watchfiles-1.1.1-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:a916a2932da8f8ab582f242c065f5c81bed3462849ca79ee357dd9551b0e9b01", size = 622112, upload-time = "2025-10-14T15:05:50.941Z" }, + { url = "https://files.pythonhosted.org/packages/d3/8e/e500f8b0b77be4ff753ac94dc06b33d8f0d839377fee1b78e8c8d8f031bf/watchfiles-1.1.1-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:db476ab59b6765134de1d4fe96a1a9c96ddf091683599be0f26147ea1b2e4b88", size = 408250, upload-time = "2025-10-14T15:06:10.264Z" }, + { url = "https://files.pythonhosted.org/packages/bd/95/615e72cd27b85b61eec764a5ca51bd94d40b5adea5ff47567d9ebc4d275a/watchfiles-1.1.1-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:89eef07eee5e9d1fda06e38822ad167a044153457e6fd997f8a858ab7564a336", size = 396117, upload-time = "2025-10-14T15:06:11.28Z" }, + { url = "https://files.pythonhosted.org/packages/c9/81/e7fe958ce8a7fb5c73cc9fb07f5aeaf755e6aa72498c57d760af760c91f8/watchfiles-1.1.1-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce19e06cbda693e9e7686358af9cd6f5d61312ab8b00488bc36f5aabbaf77e24", size = 450493, upload-time = "2025-10-14T15:06:12.321Z" }, + { url = "https://files.pythonhosted.org/packages/6e/d4/ed38dd3b1767193de971e694aa544356e63353c33a85d948166b5ff58b9e/watchfiles-1.1.1-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3e6f39af2eab0118338902798b5aa6664f46ff66bc0280de76fca67a7f262a49", size = 457546, upload-time = "2025-10-14T15:06:13.372Z" }, +]