summaryrefslogtreecommitdiff
path: root/website
diff options
context:
space:
mode:
Diffstat (limited to 'website')
-rw-r--r--website/.gitignore7
-rw-r--r--website/config.toml41
-rw-r--r--website/content/_index.md21
-rw-r--r--website/content/community-exercises/index.md73
-rw-r--r--website/content/setup/index.md78
-rw-r--r--website/content/usage/index.md55
-rw-r--r--website/input.css54
-rw-r--r--website/justfile5
-rw-r--r--website/package.json5
-rw-r--r--website/static/images/happy_ferris.svg33
-rw-r--r--website/static/images/panic.svg70
-rw-r--r--website/static/images/rust_logo.svg61
-rw-r--r--website/templates/404.html14
-rw-r--r--website/templates/anchor-link.html2
-rw-r--r--website/templates/base.html92
-rw-r--r--website/templates/index.html9
-rw-r--r--website/templates/page.html39
-rw-r--r--website/templates/shortcodes/details.html9
18 files changed, 668 insertions, 0 deletions
diff --git a/website/.gitignore b/website/.gitignore
new file mode 100644
index 0000000..648e077
--- /dev/null
+++ b/website/.gitignore
@@ -0,0 +1,7 @@
+/node_modules/
+/package-lock.json
+
+/public/
+
+/static/main.css
+/static/processed_images/
diff --git a/website/config.toml b/website/config.toml
new file mode 100644
index 0000000..0c01dc7
--- /dev/null
+++ b/website/config.toml
@@ -0,0 +1,41 @@
+base_url = "https://rustlings.rust-lang.org"
+title = "Rustlings"
+description = "Small exercises to get you used to reading and writing Rust code!"
+
+compile_sass = false
+build_search_index = false
+
+[markdown]
+highlight_code = true
+highlight_theme = "dracula"
+
+insert_anchor_links = "heading"
+
+[extra]
+logo_path = "images/happy_ferris.svg"
+
+[[extra.menu_items]]
+name = "Rustlings"
+url = "@/_index.md"
+[[extra.menu_items]]
+name = "Setup"
+url = "@/setup/index.md"
+[[extra.menu_items]]
+name = "Usage"
+url = "@/usage/index.md"
+[[extra.menu_items]]
+name = "Community Exercises"
+url = "@/community-exercises/index.md"
+[[extra.menu_items]]
+name = "Q&A"
+url = "https://github.com/rust-lang/rustlings/discussions/categories/q-a?discussions_q="
+
+[[extra.footer_items]]
+name = "Repository"
+url = "https://github.com/rust-lang/rustlings"
+[[extra.footer_items]]
+name = "Changelog"
+url = "https://github.com/rust-lang/rustlings/blob/main/CHANGELOG.md"
+[[extra.footer_items]]
+name = "MIT License"
+url = "https://github.com/rust-lang/rustlings/blob/main/LICENSE"
diff --git a/website/content/_index.md b/website/content/_index.md
new file mode 100644
index 0000000..4bb4483
--- /dev/null
+++ b/website/content/_index.md
@@ -0,0 +1,21 @@
++++
++++
+
+Small exercises to get you used to reading and writing [Rust](https://www.rust-lang.org) code - _Recommended in parallel to reading [the official Rust book](https://doc.rust-lang.org/book) πŸ“šοΈ_
+
+<script src="https://asciinema.org/a/719805.js" id="asciicast-719805" async="true"></script>
+
+## Quick start
+
+```bash
+# Installation
+cargo install rustlings
+# Initialization
+rustlings init
+# Moving into new directory
+cd rustlings
+# Starting Rustlings
+rustlings
+```
+
+Visit the [**setup**](@/setup/index.md) page for more details 🧰
diff --git a/website/content/community-exercises/index.md b/website/content/community-exercises/index.md
new file mode 100644
index 0000000..0f713d7
--- /dev/null
+++ b/website/content/community-exercises/index.md
@@ -0,0 +1,73 @@
++++
+title = "Community Exercises"
++++
+
+## List of Community Exercises
+
+- πŸ‡―πŸ‡΅ [Japanese Rustlings](https://github.com/sotanengel/rustlings-jp):A Japanese translation of the Rustlings exercises.
+- πŸ‡¨πŸ‡³ [Simplified Chinese Rustlings](https://github.com/SandmeyerX/rustlings-zh-cn): A simplified Chinese translation of the Rustlings exercises.
+
+> You can use the same `rustlings` program that you installed with `cargo install rustlings` to run community exercises.
+
+## Creating Community Exercises
+
+Rustling's support for community exercises allows you to create your own exercises to focus on some specific topic.
+You could also offer a translation of the original Rustlings exercises as community exercises.
+
+### Getting Started
+
+To create community exercises, install Rustlings and run `rustlings dev new PROJECT_NAME`.
+This command will, similar to `cargo new PROJECT_NAME`, create the template directory `PROJECT_NAME` with all what you need to get started.
+
+_Read the comments_ in the generated `info.toml` file to understand its format.
+It allows you to set a custom welcome and final message and specify the metadata of every exercise.
+
+### Creating an Exercise
+
+Here is an example of the metadata of one exercise:
+
+```toml
+[[exercises]]
+name = "intro1"
+hint = """
+To finish this exercise, you need to …
+These links might help you …"""
+```
+
+After entering this in `info.toml`, create the file `intro1.rs` in the `exercises/` directory.
+The exercise needs to contain a `main` function, but it can be empty.
+Adding tests is recommended.
+Look at the official Rustlings exercises for inspiration.
+
+You can optionally add a solution file `intro1.rs` to the `solutions/` directory.
+
+Now, run `rustlings dev check`.
+It will tell you about any issues with your exercises.
+For example, it will tell you to run `rustlings dev update` to update the `Cargo.toml` file to include the new exercise `intro1`.
+
+`rustlings dev check` will also run your solutions (if you have any) to make sure that they run successfully.
+
+That's it!
+You finished your first exercise πŸŽ‰
+
+### Cargo.toml
+
+Except of the `bin` list, you can modify the `Cargo.toml` file as you want.
+
+> The `bin` list is automatically updated by running `rustlings dev update`
+
+- You can add dependencies in the `[dependencies]` table.
+- You might want to [configure some lints](https://doc.rust-lang.org/cargo/reference/manifest.html#the-lints-section) for all exercises. You can do so in the `[lints.rust]` and `[lints.clippy]` tables.
+
+### Publishing
+
+Now, add more exercises and publish them as a Git repository.
+
+Users just have to clone that repository and run `rustlings` in it to start working on your exercises (just like the official ones).
+
+One difference to the official exercises is that the solution files will not be hidden until the user finishes an exercise.
+But you can trust your users to not open the solution too early πŸ˜‰
+
+### Sharing
+
+After publishing your community exercises, open an issue or a pull request in the [official Rustlings repository](https://github.com/rust-lang/rustlings) to add your project to the [list of community exercises](#list-of-community-exercises) πŸ˜ƒ
diff --git a/website/content/setup/index.md b/website/content/setup/index.md
new file mode 100644
index 0000000..54551ad
--- /dev/null
+++ b/website/content/setup/index.md
@@ -0,0 +1,78 @@
++++
+title = "Setup"
++++
+
+<!-- toc -->
+
+## Installing Rust
+
+Before installing Rustlings, you must have the **latest version of Rust** installed.
+Visit [www.rust-lang.org/tools/install](https://www.rust-lang.org/tools/install) for further instructions.
+This will also install _Cargo_, Rust's package/project manager.
+
+> 🐧 If you are on **Linux**, make sure you have `gcc` installed (_for a linker_).
+>
+> Debian: `sudo apt install gcc`\
+> Fedora: `sudo dnf install gcc`
+
+> 🍎 If you are on **MacOS**, make sure you have _Xcode and its developer tools_ installed: `xcode-select --install`
+
+## Installing Rustlings
+
+The following command will download and compile Rustlings:
+
+```bash
+cargo install rustlings
+```
+
+{% details(summary="If the installation fails…") %}
+
+- Make sure you have the latest Rust version by running `rustup update`
+- Try adding the `--locked` flag: `cargo install rustlings --locked`
+- Otherwise, please [report the issue](https://github.com/rust-lang/rustlings/issues/new)
+
+{% end %}
+
+## Initialization
+
+After installing Rustlings, run the following command to initialize the `rustlings/` directory:
+
+```bash
+rustlings init
+```
+
+{% details(summary="If the command <code>rustlings</code> can't be found…") %}
+
+You are probably using Linux and installed Rust using your package manager.
+
+Cargo installs binaries to the directory `~/.cargo/bin`.
+Sadly, package managers often don't add `~/.cargo/bin` to your `PATH` environment variable.
+
+- Either add `~/.cargo/bin` manually to `PATH`
+- Or uninstall Rust from the package manager and [install it using the official way with `rustup`](https://www.rust-lang.org/tools/install)
+
+{% end %}
+
+Now, go into the newly initialized directory and launch Rustlings for further instructions on getting started with the exercises:
+
+```bash
+cd rustlings/
+rustlings
+```
+
+## Working environment
+
+### Editor
+
+Our general recommendation is [VS Code](https://code.visualstudio.com/) with the [rust-analyzer plugin](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer).
+But any editor that supports [rust-analyzer](https://rust-analyzer.github.io/) should be enough for working on the exercises.
+
+### Terminal
+
+While working with Rustlings, please use a modern terminal for the best user experience.
+The default terminal on Linux and Mac should be sufficient.
+On Windows, we recommend the [Windows Terminal](https://aka.ms/terminal).
+
+## Usage
+
+After being done with the setup, visit the [**usage**](@/usage/index.md) page for some info about using Rustlings πŸš€
diff --git a/website/content/usage/index.md b/website/content/usage/index.md
new file mode 100644
index 0000000..88dabf4
--- /dev/null
+++ b/website/content/usage/index.md
@@ -0,0 +1,55 @@
++++
+title = "Usage"
++++
+
+<!-- toc -->
+
+## Doing exercises
+
+The exercises are sorted by topic and can be found in the subdirectory `exercises/<topic>`.
+For every topic, there is an additional `README.md` file with some resources to get you started on the topic.
+We highly recommend that you have a look at them before you start πŸ“šοΈ
+
+Most exercises contain an error that keeps them from compiling, and it's up to you to fix it!
+Some exercises contain tests that need to pass for the exercise to be done βœ…
+
+Search for `TODO` and `todo!()` to find out what you need to change.
+Ask for hints by entering `h` in the _watch mode_ πŸ’‘
+
+## Watch Mode
+
+After the [initialization](@/setup/index.md#initialization), Rustlings can be launched by simply running the command `rustlings`.
+
+This will start the _watch mode_ which walks you through the exercises in a predefined order (what we think is best for newcomers).
+It will rerun the current exercise automatically every time you change the exercise's file in the `exercises/` directory.
+
+{% details(summary="If detecting file changes in the <code>exercises/</code> directory fails…") %}
+
+You can add the **`--manual-run`** flag (`rustlings --manual-run`) to manually rerun the current exercise by entering `r` in the watch mode.
+
+Please [report the issue](https://github.com/rust-lang/rustlings/issues/new) with some information about your operating system and whether you run Rustlings in a container or a virtual machine (e.g. WSL).
+
+{% end %}
+
+## Exercise List
+
+In the [watch mode](#watch-mode) (after launching `rustlings`), you can enter `l` to open the interactive exercise list.
+
+The list allows you to…
+
+- See the status of all exercises (done or pending)
+- `c`: Continue at another exercise (temporarily skip some exercises or go back to a previous one)
+- `r`: Reset status and file of the selected exercise (you need to _reload/reopen_ its file in your editor afterwards)
+
+See the footer of the list for all possible keys.
+
+## Questions?
+
+If you need any help while doing the exercises and the builtin hints aren't helpful, feel free to ask in the [_Q&A_ discussions](https://github.com/rust-lang/rustlings/discussions/categories/q-a?discussions_q=) if your question isn't answered there πŸ’‘
+
+## Continuing On
+
+Once you've completed Rustlings, put your new knowledge to good use!
+Continue practicing your Rust skills by building your own projects, contributing to Rustlings, or finding other open-source projects to contribute to.
+
+> If you want to create your own Rustlings exercises, visit the [**community exercises**](@/community-exercises/index.md) page πŸ—οΈ
diff --git a/website/input.css b/website/input.css
new file mode 100644
index 0000000..af0675d
--- /dev/null
+++ b/website/input.css
@@ -0,0 +1,54 @@
+@import 'tailwindcss';
+
+@layer base {
+ h1 {
+ @apply text-4xl mt-3 mb-3 font-bold;
+ }
+ h2 {
+ @apply text-3xl mt-4 mb-1.5 font-bold;
+ }
+ h3 {
+ @apply text-2xl mt-5 mb-1.5 font-bold;
+ }
+ h4 {
+ @apply text-xl mt-6 mb-1.5 font-bold;
+ }
+ p {
+ @apply mb-2;
+ }
+ a {
+ @apply text-[#FFC832] underline hover:decoration-orange-400 transition duration-300;
+ }
+ ul {
+ @apply mt-2 mb-3 ml-1 list-disc list-inside marker:text-sky-600;
+ }
+ ol {
+ @apply mt-2 mb-3 ml-1 list-decimal list-inside marker:text-sky-500;
+ }
+ li {
+ @apply my-0.5;
+ }
+ code {
+ @apply bg-white/10 px-1 pb-px pt-1 rounded-md;
+ }
+ pre code {
+ @apply bg-inherit p-0 text-inherit;
+ }
+ hr {
+ @apply my-5 rounded-full;
+ }
+ img {
+ @apply md:w-3/4 lg:w-3/5;
+ }
+ blockquote {
+ @apply px-3 pt-2 pb-0.5 mb-4 mt-2 border-s-4 border-white/80 bg-white/7 rounded-sm;
+ }
+
+ pre {
+ @apply px-2 pt-2 pb-px overflow-x-auto text-sm sm:text-base rounded-sm mt-2 mb-4 after:content-[attr(data-lang)] after:text-[8px] after:opacity-40 selection:bg-white/15;
+ }
+ pre code mark {
+ @apply pb-0.5 pt-1 pr-px text-inherit rounded-xs;
+ }
+}
+
diff --git a/website/justfile b/website/justfile
new file mode 100644
index 0000000..7efc3ef
--- /dev/null
+++ b/website/justfile
@@ -0,0 +1,5 @@
+zola:
+ zola serve --open
+
+tailwind:
+ npx @tailwindcss/cli -w -i input.css -o static/main.css
diff --git a/website/package.json b/website/package.json
new file mode 100644
index 0000000..38dd27e
--- /dev/null
+++ b/website/package.json
@@ -0,0 +1,5 @@
+{
+ "dependencies": {
+ "@tailwindcss/cli": "^4.1"
+ }
+}
diff --git a/website/static/images/happy_ferris.svg b/website/static/images/happy_ferris.svg
new file mode 100644
index 0000000..c7f240d
--- /dev/null
+++ b/website/static/images/happy_ferris.svg
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg width="100%" height="100%" viewBox="0 0 1200 800" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;">
+ <g id="Layer-1" serif:id="Layer 1">
+ <g transform="matrix(1,0,0,1,1009.4,506.362)">
+ <path d="M0,-7.203L-12.072,-32.209C-12.009,-33.156 -11.961,-34.107 -11.961,-35.062C-11.961,-63.408 -41.439,-89.533 -91.03,-110.451L-91.03,-93.058C-95.866,-94.977 -100.901,-96.845 -106.147,-98.651L-106.147,-106.759C-177.021,-132.319 -282.53,-148.537 -400.388,-148.537C-503.361,-148.537 -596.917,-136.157 -666.179,-115.983L-666.179,-87.737L-666.181,-87.737L-666.181,-121.925C-737.141,-99.375 -781.135,-68.048 -781.135,-33.41C-781.135,-27.95 -780.034,-22.572 -777.918,-17.297L-785.146,-4.43C-785.146,-4.43 -790.938,3.082 -780.74,18.932C-771.746,32.909 -726.692,87.617 -702.913,116.267C-692.699,130.954 -685.772,140.001 -685.167,139.126C-684.212,137.74 -691.518,110.165 -711.802,78.703C-721.268,61.808 -732.57,39.42 -739.356,22.884C-720.414,34.874 -609.126,90.913 -382.124,90.685C-150.13,90.453 -47.009,17.834 -35.691,7.948C-39.646,23.837 -53.159,55.981 -63.936,78.586C-81.642,110.917 -88.056,139.064 -87.232,140.456C-86.708,141.334 -80.667,132.015 -71.756,116.913C-51.025,87.37 -11.739,30.974 -3.889,16.608C5.007,0.323 0,-7.203 0,-7.203" style="fill:rgb(165,43,0);fill-rule:nonzero;"/>
+ </g>
+ <g transform="matrix(1,0,0,1,1079.49,294.885)">
+ <path d="M0,204.135L-79.343,145.689C-80.088,143.089 -80.833,140.488 -81.603,137.908L-55.541,100.154C-52.881,96.314 -52.345,91.322 -54.072,86.943C-55.803,82.585 -59.587,79.461 -64.062,78.696L-108.128,71.217C-109.837,67.732 -111.626,64.301 -113.422,60.898L-94.907,18.51C-93.004,14.193 -93.402,9.175 -95.929,5.256C-98.446,1.319 -102.715,-0.981 -107.267,-0.802L-151.991,0.823C-154.306,-2.193 -156.658,-5.18 -159.058,-8.114L-148.78,-53.546C-147.738,-58.158 -149.054,-62.989 -152.267,-66.34C-155.462,-69.679 -160.105,-71.062 -164.52,-69.979L-208.082,-59.27C-210.902,-61.763 -213.77,-64.223 -216.67,-66.635L-215.103,-113.276C-214.935,-117.997 -217.136,-122.484 -220.915,-125.105C-224.692,-127.741 -229.485,-128.137 -233.616,-126.179L-274.254,-106.858C-277.527,-108.736 -280.819,-110.595 -284.146,-112.395L-291.327,-158.356C-292.056,-163.012 -295.051,-166.968 -299.246,-168.774C-303.431,-170.591 -308.222,-170.002 -311.894,-167.238L-348.126,-140.053C-351.695,-141.238 -355.279,-142.373 -358.905,-143.46L-374.522,-187.045C-376.11,-191.488 -379.772,-194.751 -384.238,-195.669C-388.688,-196.578 -393.266,-195.037 -396.352,-191.589L-426.851,-157.47C-430.536,-157.893 -434.228,-158.28 -437.927,-158.601L-461.476,-198.277C-463.86,-202.295 -468.073,-204.741 -472.615,-204.741C-477.144,-204.741 -481.365,-202.295 -483.733,-198.277L-507.288,-158.601C-510.989,-158.28 -514.696,-157.893 -518.376,-157.47L-548.875,-191.589C-551.965,-195.037 -556.559,-196.578 -560.997,-195.669C-565.457,-194.739 -569.125,-191.488 -570.704,-187.045L-586.333,-143.46C-589.954,-142.373 -593.538,-141.23 -597.113,-140.053L-633.333,-167.238C-637.016,-170.012 -641.811,-170.599 -646.001,-168.774C-650.182,-166.968 -653.189,-163.012 -653.914,-158.356L-661.1,-112.395C-664.422,-110.595 -667.714,-108.746 -670.995,-106.858L-711.629,-126.179C-715.756,-128.145 -720.574,-127.741 -724.333,-125.105C-728.106,-122.484 -730.313,-117.997 -730.143,-113.276L-728.581,-66.635C-731.475,-64.223 -734.337,-61.763 -737.172,-59.27L-780.726,-69.979C-785.149,-71.053 -789.788,-69.679 -792.991,-66.34C-796.212,-62.989 -797.517,-58.158 -796.482,-53.546L-786.225,-8.114C-788.603,-5.169 -790.958,-2.193 -793.267,0.823L-837.991,-0.802C-842.504,-0.937 -846.812,1.319 -849.334,5.256C-851.861,9.175 -852.244,14.193 -850.363,18.51L-831.835,60.898C-833.634,64.301 -835.421,67.732 -837.144,71.217L-881.207,78.696C-885.686,79.45 -889.459,82.572 -891.201,86.943C-892.929,91.322 -892.368,96.314 -889.727,100.154L-863.661,137.908C-863.862,138.575 -864.048,139.247 -864.248,139.916L-937.944,218.201C-937.944,218.201 -949.24,227.052 -932.797,247.855C-918.297,266.206 -843.846,338.951 -804.526,377.06C-787.92,396.408 -776.542,408.389 -775.354,407.353C-773.478,405.708 -783.326,370.506 -816.036,329.204C-841.252,292.148 -873.977,235.155 -866.303,228.586C-866.303,228.586 -857.574,217.505 -840.061,209.529C-839.42,210.041 -840.723,209.022 -840.061,209.529C-840.061,209.529 -470.466,380.02 -127.632,212.413C-88.468,205.388 -64.759,226.368 -64.759,226.368C-56.583,231.108 -77.755,289.712 -95.166,328.505C-118.845,372.555 -122.317,406.927 -120.31,408.119C-119.042,408.876 -110.427,395.766 -98.138,374.902C-67.814,332.649 -10.492,252.1 0,232.534C11.895,210.352 0,204.135 0,204.135" style="fill:rgb(247,76,0);fill-rule:nonzero;"/>
+ </g>
+ <g transform="matrix(1,0,0,1,917.896,244.679)">
+ <path d="M0,232.466C0,232.466 53.179,230 123.032,159.004L132.93,137.025C132.93,137.025 24.513,29.177 193.048,-45.266C193.048,-45.266 178.293,-21.154 182.622,72.006C182.622,72.006 233.437,54.357 248.336,-27.934C248.336,-27.934 322.456,69.79 167.834,161.443C167.834,161.443 95.294,277.732 -6.971,266.593L0,232.466Z" style="fill:rgb(247,76,0);fill-rule:nonzero;"/>
+ </g>
+ <g transform="matrix(1,0,0,1,676.997,488.361)">
+ <path d="M0,-78.192C0,-78.192 36.935,-118.635 73.871,-78.192C73.871,-78.192 102.893,-24.265 73.871,2.695C73.871,2.695 26.384,40.443 0,2.695C0,2.695 -31.658,-26.964 0,-78.192" style="fill-rule:nonzero;"/>
+ </g>
+ <g transform="matrix(1,0,0,1,719.761,425.169)">
+ <path d="M0,0.004C0,15.75 -9.282,28.518 -20.732,28.518C-32.18,28.518 -41.462,15.75 -41.462,0.004C-41.462,-15.746 -32.18,-28.514 -20.732,-28.514C-9.282,-28.514 0,-15.746 0,0.004" style="fill:white;fill-rule:nonzero;"/>
+ </g>
+ <g transform="matrix(1,0,0,1,512.148,482.736)">
+ <path d="M0,-83.609C0,-83.609 63.355,-111.661 80.648,-49.047C80.648,-49.047 98.762,23.933 28.618,28.052C28.618,28.052 -60.826,10.824 0,-83.609" style="fill-rule:nonzero;"/>
+ </g>
+ <g transform="matrix(1,0,0,1,543.968,426.204)">
+ <path d="M0,0.002C0,16.241 -9.572,29.411 -21.381,29.411C-33.185,29.411 -42.76,16.241 -42.76,0.002C-42.76,-16.242 -33.185,-29.409 -21.381,-29.409C-9.572,-29.409 0,-16.242 0,0.002" style="fill:white;fill-rule:nonzero;"/>
+ </g>
+ <g transform="matrix(1,0,0,1,593.317,576.574)">
+ <path d="M0,-40.271L80.796,-46.755C80.796,-46.755 78.058,-33.749 67.517,-23.986C67.517,-23.986 39.727,6.484 7.844,-26.519C7.844,-26.519 2.627,-32.148 0,-40.271" style="fill-rule:nonzero;"/>
+ </g>
+ <g transform="matrix(1,0,0,1,269.796,270.778)">
+ <path d="M0,190.741C-0.667,190.741 -1.321,190.79 -1.973,190.842C-28.207,184.871 -101.946,165.657 -121.437,134.479C-121.437,134.479 -22.21,21.607 -177.297,-50.54L-159.24,74.338C-159.24,74.338 -207.049,42.389 -217.366,-27.008C-217.366,-27.008 -333.789,57.486 -165.982,138.466C-165.982,138.466 -150.762,195.653 -4.633,241.281L-4.526,240.846C-3.055,241.118 -1.549,241.281 0,241.281C13.808,241.281 25.003,229.969 25.003,216.01C25.003,202.054 13.808,190.741 0,190.741" style="fill:rgb(247,76,0);fill-rule:nonzero;"/>
+ </g>
+ </g>
+</svg>
diff --git a/website/static/images/panic.svg b/website/static/images/panic.svg
new file mode 100644
index 0000000..be55f5e
--- /dev/null
+++ b/website/static/images/panic.svg
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="1434.979px" height="947px" viewBox="0 0 1434.979 947" enable-background="new 0 0 1434.979 947" xml:space="preserve">
+<!--<rect fill="#FFFFFF" width="1434.979" height="947"/>-->
+<path fill="#8F1F1D" d="M712.827,368.579c-131.633,0-251.228,15.825-339.77,41.615v220.298
+ c88.542,25.79,208.137,41.614,339.77,41.614c150.657,0,285.535-20.729,376.134-53.402V421.986
+ C998.361,389.311,863.483,368.579,712.827,368.579"/>
+<path fill="#8F1F1D" d="M1094.847,567.972c-3.856-10.663-4.629-24.154-1.36-37.162c5.85-23.289,22.421-36.198,37.013-28.833
+ c3.618,1.827,6.773,4.73,9.387,8.418c0.239-0.001,0.479,0,0.715,0.016c0,0,44.552,53.106,3.313,116.003
+ c-0.896,3.569-76.534,91.718-94.043,94.524C1038.411,722.773,1064.762,630.939,1094.847,567.972"/>
+<path fill="#8F1F1D" d="M363.903,557.551c5.3-9.631,7.158-22.788,4.217-36.426c-5.266-24.416-23.91-41.109-41.642-37.285
+ c-4.398,0.948-8.325,3.072-11.666,6.099c-0.282-0.059-0.564-0.113-0.845-0.153c0,0-56.292,41.952-12.057,113.924
+ c0.805,3.741,83.851,108.838,104.311,115.764C419.612,724.004,394.974,626.947,363.903,557.551"/>
+<path fill="#E23A26" d="M284.891,563.596l0.007,0.015C285.083,563.755,285.255,563.887,284.891,563.596"/>
+<path fill="#E33B26" d="M1180.543,488.433c-0.88-3.064-1.756-6.126-2.662-9.162l30.683-44.451c3.13-4.522,3.771-10.398,1.73-15.555
+ c-2.04-5.13-6.49-8.81-11.76-9.71l-51.887-8.805c-2.008-4.102-4.115-8.142-6.229-12.15l21.797-49.903
+ c2.243-5.087,1.769-10.995-1.203-15.608c-2.961-4.636-7.99-7.344-13.349-7.133l-52.656,1.913c-2.727-3.55-5.496-7.068-8.322-10.521
+ l12.102-53.49c1.225-5.433-0.322-11.118-4.104-15.064c-3.762-3.932-9.229-5.559-14.426-4.283l-51.289,12.608
+ c-3.321-2.935-6.699-5.833-10.114-8.673l1.849-54.914c0.197-5.559-2.394-10.842-6.845-13.925
+ c-4.445-3.104-10.093-3.573-14.955-1.266l-47.848,22.747c-3.854-2.21-7.728-4.4-11.644-6.517l-8.455-54.115
+ c-0.857-5.483-4.386-10.139-9.326-12.266c-4.923-2.137-10.568-1.447-14.891,1.808l-42.659,32.007
+ c-4.2-1.395-8.419-2.732-12.692-4.011l-18.386-51.316c-1.87-5.229-6.182-9.071-11.438-10.151c-5.238-1.072-10.63,0.742-14.263,4.802
+ l-35.907,40.171c-4.342-0.5-8.685-0.956-13.043-1.331l-27.723-46.713c-2.811-4.732-7.771-7.612-13.116-7.612
+ c-5.334,0-10.304,2.88-13.09,7.612l-27.733,46.713c-4.358,0.375-8.722,0.831-13.056,1.331l-35.91-40.171
+ c-3.636-4.06-9.047-5.874-14.268-4.802c-5.255,1.092-9.573,4.922-11.433,10.151l-18.402,51.316
+ c-4.26,1.279-8.481,2.627-12.691,4.011l-42.644-32.007c-4.336-3.266-9.98-3.955-14.916-1.808c-4.919,2.127-8.461,6.783-9.313,12.266
+ l-8.461,54.115c-3.914,2.117-7.789,4.294-11.653,6.517L436.1,168.34c-4.858-2.316-10.529-1.838-14.954,1.266
+ c-4.445,3.083-7.042,8.366-6.84,13.925l1.835,54.914c-3.405,2.84-6.774,5.738-10.112,8.673L354.75,234.51
+ c-5.211-1.265-10.67,0.351-14.441,4.283c-3.795,3.946-5.332,9.631-4.113,15.064l12.079,53.49c-2.802,3.467-5.575,6.971-8.293,10.521
+ l-52.655-1.913c-5.314-0.157-10.386,2.497-13.356,7.133c-2.974,4.613-3.425,10.521-1.211,15.608l21.814,49.903
+ c-2.119,4.008-4.224,8.048-6.249,12.15l-51.882,8.805c-5.271,0.888-9.715,4.566-11.765,9.71c-2.037,5.157-1.375,11.033,1.735,15.555
+ l30.69,44.451c-0.236,0.784-0.455,1.576-0.69,2.364l-16.863,17.911l45.341,64.05c0,0,435.152,200.731,838.797,3.396
+ C1169.796,558.719,1180.543,488.433,1180.543,488.433"/>
+<path d="M795.716,446.557c0,0,48.162-52.734,96.324,0c0,0,37.844,70.318,0,105.473c0,0-61.922,49.223-96.324,0
+ C795.716,552.029,754.434,513.354,795.716,446.557"/>
+<path fill="#FFFFFF" d="M855.154,481.097c0,19.782-11.66,35.82-26.041,35.82c-14.379,0-26.04-16.038-26.04-35.82
+ c0-19.782,11.661-35.821,26.04-35.821C843.494,445.275,855.154,461.315,855.154,481.097"/>
+<path d="M578.401,430.129c0,0,84.436-37.385,107.481,46.059c0,0,24.141,97.261-69.339,102.751
+ C616.543,578.939,497.34,555.98,578.401,430.129"/>
+<rect x="187.424" y="75.529" fill="none" width="1060" height="782"/>
+<path fill="#FFFFFF" d="M627.514,481.096c0,20.579-12.13,37.27-27.095,37.27c-14.959,0-27.092-16.69-27.092-37.27
+ c0-20.583,12.133-37.27,27.092-37.27C615.384,443.826,627.514,460.513,627.514,481.096"/>
+<path fill="#E33B26" d="M299.026,574.745c10.967-12.463,37.611-27.557,35.57-46.282c-3.653-33.526-31.456-57.999-62.099-54.658
+ c-7.599,0.827-14.658,3.292-20.923,7.035c-0.463-0.106-0.925-0.211-1.388-0.294c0,0-103.632,50.873-44.564,152.657
+ c0.557,5.137,117.847,155.668,150.787,167.131C377.968,807.836,336.498,671.694,299.026,574.745"/>
+<path fill="#E33B26" d="M1140.973,570.202c-12.692-10.7-46.162-20.418-46.92-39.238c-1.355-33.697,22.512-62.021,53.312-63.26
+ c7.638-0.308,14.983,1.083,21.734,3.857c0.442-0.174,0.884-0.347,1.329-0.497c0,0,110.025,34.951,66.695,144.366
+ c0.21,5.163-93.468,171.416-124.345,187.635C1092.57,813.681,1118.285,671.635,1140.973,570.202"/>
+<rect x="187.484" y="75.843" fill="none" width="1059.75" height="781.686"/>
+<rect x="187.424" y="75.529" fill="none" width="1060" height="782"/>
+<g>
+ <path fill="#E33B26" d="M283.144,565.511c0,0-137.214-4.942-161.62-140.761l57.596-25.427c0,0-13.912,96.957,106.615,110.022
+ L283.144,565.511"/>
+ <path fill="#E33B26" d="M127.552,333.083c0,0-24.965-49.774-65.807-113.261C18.721,241.035-2.671,299.05,13.482,357.484
+ c17.846,64.558,74.749,105.16,127.097,90.69s80.318-78.535,62.471-143.092c-7.909-28.618-23.501-52.519-42.963-69.011
+ C150.611,287.113,127.552,333.083,127.552,333.083"/>
+</g>
+<rect x="187.484" y="75.843" fill="none" width="1059.75" height="781.686"/>
+<g>
+ <path fill="#E33B26" d="M1148.012,565.511c0,0,137.214-4.942,161.62-140.761l-57.596-25.428c0,0,13.912,96.957-106.615,110.022
+ L1148.012,565.511"/>
+ <path fill="#E33B26" d="M1303.604,333.083c0,0,24.966-49.774,65.808-113.261c43.023,21.212,64.416,79.228,48.262,137.662
+ c-17.846,64.558-74.748,105.16-127.096,90.689c-52.348-14.47-80.318-78.534-62.472-143.091
+ c7.909-28.618,23.501-52.519,42.964-69.011C1280.544,287.113,1303.604,333.083,1303.604,333.083"/>
+</g>
+<path d="M807.895,626.942c-7.131-58.735-72.193-61.431-72.193-61.431c-50.936,11.227-59.183,47.369-57.392,75.104L807.895,626.942z"
+ />
+</svg>
diff --git a/website/static/images/rust_logo.svg b/website/static/images/rust_logo.svg
new file mode 100644
index 0000000..3b42cfe
--- /dev/null
+++ b/website/static/images/rust_logo.svg
@@ -0,0 +1,61 @@
+<svg version="1.1" height="106" width="106" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+<g id="logo" transform="translate(53, 53)">
+ <path id="r" transform="translate(0.5, 0.5)" fill="white" stroke="white" stroke-width="1" stroke-linejoin="round" d="
+ M -9,-15 H 4 C 12,-15 12,-7 4,-7 H -9 Z
+ M -40,22 H 0 V 11 H -9 V 3 H 1 C 12,3 6,22 15,22 H 40
+ V 3 H 34 V 5 C 34,13 25,12 24,7 C 23,2 19,-2 18,-2 C 33,-10 24,-26 12,-26 H -35
+ V -15 H -25 V 11 H -40 Z" />
+ <g id="gear" mask="url(#holes)">
+ <circle r="43" fill="none" stroke="white" stroke-width="9" />
+ <g id="cogs">
+ <polygon id="cog" stroke="white" stroke-width="3" stroke-linejoin="round" points="46,3 51,0 46,-3" />
+ <use xlink:href="#cog" transform="rotate(11.25)" />
+ <use xlink:href="#cog" transform="rotate(22.50)" />
+ <use xlink:href="#cog" transform="rotate(33.75)" />
+ <use xlink:href="#cog" transform="rotate(45.00)" />
+ <use xlink:href="#cog" transform="rotate(56.25)" />
+ <use xlink:href="#cog" transform="rotate(67.50)" />
+ <use xlink:href="#cog" transform="rotate(78.75)" />
+ <use xlink:href="#cog" transform="rotate(90.00)" />
+ <use xlink:href="#cog" transform="rotate(101.25)" />
+ <use xlink:href="#cog" transform="rotate(112.50)" />
+ <use xlink:href="#cog" transform="rotate(123.75)" />
+ <use xlink:href="#cog" transform="rotate(135.00)" />
+ <use xlink:href="#cog" transform="rotate(146.25)" />
+ <use xlink:href="#cog" transform="rotate(157.50)" />
+ <use xlink:href="#cog" transform="rotate(168.75)" />
+ <use xlink:href="#cog" transform="rotate(180.00)" />
+ <use xlink:href="#cog" transform="rotate(191.25)" />
+ <use xlink:href="#cog" transform="rotate(202.50)" />
+ <use xlink:href="#cog" transform="rotate(213.75)" />
+ <use xlink:href="#cog" transform="rotate(225.00)" />
+ <use xlink:href="#cog" transform="rotate(236.25)" />
+ <use xlink:href="#cog" transform="rotate(247.50)" />
+ <use xlink:href="#cog" transform="rotate(258.75)" />
+ <use xlink:href="#cog" transform="rotate(270.00)" />
+ <use xlink:href="#cog" transform="rotate(281.25)" />
+ <use xlink:href="#cog" transform="rotate(292.50)" />
+ <use xlink:href="#cog" transform="rotate(303.75)" />
+ <use xlink:href="#cog" transform="rotate(315.00)" />
+ <use xlink:href="#cog" transform="rotate(326.25)" />
+ <use xlink:href="#cog" transform="rotate(337.50)" />
+ <use xlink:href="#cog" transform="rotate(348.75)" />
+ </g>
+ <g id="mounts">
+ <polygon id="mount" stroke="white" stroke-width="6" stroke-linejoin="round" points="-7,-42 0,-35 7,-42" />
+ <use xlink:href="#mount" transform="rotate(72)" />
+ <use xlink:href="#mount" transform="rotate(144)" />
+ <use xlink:href="#mount" transform="rotate(216)" />
+ <use xlink:href="#mount" transform="rotate(288)" />
+ </g>
+ </g>
+ <mask id="holes">
+ <rect x="-60" y="-60" width="120" height="120" fill="white"/>
+ <circle id="hole" cy="-40" r="3" />
+ <use xlink:href="#hole" transform="rotate(72)" />
+ <use xlink:href="#hole" transform="rotate(144)" />
+ <use xlink:href="#hole" transform="rotate(216)" />
+ <use xlink:href="#hole" transform="rotate(288)" />
+ </mask>
+</g>
+</svg>
diff --git a/website/templates/404.html b/website/templates/404.html
new file mode 100644
index 0000000..eb9d469
--- /dev/null
+++ b/website/templates/404.html
@@ -0,0 +1,14 @@
+{% extends "base.html" %}
+
+{% block content %}
+ <div class="flex flex-col mx-auto text-center">
+ <h1>DON'T PANIC!</h1>
+ <h2>404: Page not found!</h2>
+
+ <img class="mx-auto max-h-[50vh]"
+ src="{{ get_url(path='images/panic.svg') | safe }}"
+ alt="">
+
+ <a class="text-2xl font-bold" href="{{ get_url(path='@/_index.md') }}">Back to homepage</a>
+ </div>
+{% endblock %}
diff --git a/website/templates/anchor-link.html b/website/templates/anchor-link.html
new file mode 100644
index 0000000..c8644d9
--- /dev/null
+++ b/website/templates/anchor-link.html
@@ -0,0 +1,2 @@
+<a class="text-white no-underline transition-none hover:underline"
+ href="#{{ id }}"></a>
diff --git a/website/templates/base.html b/website/templates/base.html
new file mode 100644
index 0000000..1a55aeb
--- /dev/null
+++ b/website/templates/base.html
@@ -0,0 +1,92 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+
+ {%- set timestamp = now(timestamp=true) -%}
+
+ {%- if page.title -%}
+ {% set_global title = page.title %}
+ {%- elif section.title -%}
+ {% set_global title = section.title %}
+ {%- else -%}
+ {% set_global title = config.title %}
+ {%- endif -%}
+
+ {%- if page.description -%}
+ {% set_global description = page.description %}
+ {%- elif section.description -%}
+ {% set_global description = section.description %}
+ {%- else -%}
+ {% set_global description = config.description %}
+ {%- endif -%}
+
+ {%- if page.permalink -%}
+ {% set_global permalink = page.permalink %}
+ {%- elif section.permalink -%}
+ {% set_global permalink = section.permalink %}
+ {%- endif %}
+
+ <title>{%- block title -%}{{- title -}}{%- endblock -%}</title>
+
+ <meta name="description"
+ content="{%- block description -%}{{- description -}}{%- endblock -%}">
+
+ <link rel="icon"
+ type="image/x-icon"
+ href="{{ get_url(path=config.extra.logo_path) | safe }}?v={{ timestamp }}">
+
+ <link href="{{ get_url(path='main.css') | safe }}?v={{ timestamp }}"
+ rel="stylesheet">
+
+ <meta property="og:title" content="{{ title }}">
+ <meta property="og:description" content="{{ description }}">
+ <meta property="og:image"
+ content="{{ get_url(path=config.extra.logo_path) | safe }}?v={{ timestamp }}">
+ {% if permalink %}<meta property="og:url" content="{{ permalink | safe }}">{% endif %}
+ </head>
+
+ <body class="flex flex-col p-2 mx-auto min-h-screen text-lg text-white break-words lg:px-5 2xl:container bg-[#2A3439]">
+ <header class="flex flex-col gap-x-4 items-center py-2 px-4 mb-1 rounded-sm sm:flex-row sm:rounded-full bg-black/30">
+ <a class="transition duration-500 hover:scale-110"
+ href="{{ get_url(path='@/_index.md') | safe }}"
+ aria-hidden="true">
+ <img class="w-12 h-12"
+ src="{{ get_url(path=config.extra.logo_path) | safe }}"
+ alt="">
+ </a>
+
+ <nav class="flex flex-col gap-x-6 items-center font-bold sm:flex-row">
+ {% for menu_item in config.extra.menu_items %}
+ {%- if menu_item.url is starting_with("@") -%}
+ {% set_global menu_item_url = get_url(path=menu_item.url) %}
+ {%- else -%}
+ {% set_global menu_item_url = menu_item.url %}
+ {%- endif %}
+
+ <a class="p-1 no-underline" href="{{ menu_item_url | safe }}">{{ menu_item.name }}</a>
+ {% endfor %}
+ </nav>
+ </header>
+
+ <main class="leading-relaxed">
+ {% block content %}{% endblock %}
+ </main>
+
+ <footer class="pt-2 pb-1 mt-auto text-sm text-center">
+ <div class="inline-flex gap-x-1.5 items-center mx-auto mt-2">
+ <img class="w-8 h-8"
+ src="{{ get_url(path='images/rust_logo.svg') | safe }}"
+ alt="">
+ <div class="italic">Rustlings is an official Rust project</div>
+ </div>
+
+ <nav class="flex flex-col gap-y-3 justify-around py-3 mt-3 rounded-sm sm:flex-row sm:rounded-full bg-black/30">
+ {% for footer_item in config.extra.footer_items %}
+ <a class="no-underline" href="{{ footer_item.url | safe }}">{{ footer_item.name }}</a>
+ {% endfor %}
+ </nav>
+ </footer>
+ </body>
+</html>
diff --git a/website/templates/index.html b/website/templates/index.html
new file mode 100644
index 0000000..0d2b2e3
--- /dev/null
+++ b/website/templates/index.html
@@ -0,0 +1,9 @@
+{% extends "base.html" %}
+
+{% block content %}
+ <div class="m-3">
+ <h1>Rustlings</h1>
+
+ {{ section.content | safe }}
+ </div>
+{% endblock %}
diff --git a/website/templates/page.html b/website/templates/page.html
new file mode 100644
index 0000000..b2f6c01
--- /dev/null
+++ b/website/templates/page.html
@@ -0,0 +1,39 @@
+{% extends "base.html" %}
+
+{% block content %}
+ <article>
+ <h1>{{ page.title }}</h1>
+
+ <div class="py-0.5 px-4 my-3 rounded-xl border-double border-s-4">
+ <nav>
+ <ul class="ml-0 list-none">
+ {% for parent in page.toc %}
+ {% if parent.level == 2 %}
+ <li>
+ {#- -#}
+ <a href="{{ parent.permalink | safe }}">{{ parent.title }}</a>
+ {#- -#}
+ {% if parent.children %}
+ <ul class="my-0 ml-5 list-none">
+ {% for child in parent.children %}
+ {% if child.level == 3 %}
+ <li>
+ {#- -#}
+ <a class="text-base" href="{{ child.permalink | safe }}">{{ child.title }}</a>
+ {#- -#}
+ </li>
+ {% endif %}
+ {% endfor %}
+ </ul>
+ {% endif %}
+ {#- -#}
+ </li>
+ {% endif %}
+ {% endfor %}
+ </ul>
+ </nav>
+ </div>
+
+ {{ page.content | safe }}
+ </article>
+{% endblock %}
diff --git a/website/templates/shortcodes/details.html b/website/templates/shortcodes/details.html
new file mode 100644
index 0000000..1c07778
--- /dev/null
+++ b/website/templates/shortcodes/details.html
@@ -0,0 +1,9 @@
+<details>
+ <summary>
+ <strong>{{ summary | safe }}</strong> (<em>click to expand</em>)
+ </summary>
+
+ <blockquote class="pt-1 mx-0.5 mt-1 rounded-none border-dashed border-x-3 border-b-3">
+ {{ body | markdown | safe }}
+ </blockquote>
+</details>