mirror of
https://github.com/rust-lang/rustlings.git
synced 2025-06-08 23:46:26 +02:00
Add templates
This commit is contained in:
parent
74ab9924b4
commit
7ec6986965
@ -7,6 +7,12 @@ build_search_index = false
|
|||||||
|
|
||||||
[markdown]
|
[markdown]
|
||||||
highlight_code = true
|
highlight_code = true
|
||||||
|
highlight_theme = "ayu-mirage"
|
||||||
|
|
||||||
|
insert_anchor_links = "heading"
|
||||||
|
|
||||||
|
[extra]
|
||||||
|
logo_path = "images/happy_ferris.svg"
|
||||||
|
|
||||||
[[extra.menu_items]]
|
[[extra.menu_items]]
|
||||||
name = "Home"
|
name = "Home"
|
||||||
|
143
website/content/_index.md
Normal file
143
website/content/_index.md
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
+++
|
||||||
|
+++
|
||||||
|
|
||||||
|
Greetings and welcome to Rustlings.
|
||||||
|
This project contains small exercises to get you used to reading and writing Rust code.
|
||||||
|
This includes reading and responding to compiler messages!
|
||||||
|
|
||||||
|
It is recommended to do the Rustlings exercises in parallel to reading [the official Rust book](https://doc.rust-lang.org/book/), the most comprehensive resource for learning Rust 📚️
|
||||||
|
|
||||||
|
<!-- toc -->
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
### Installing Rust
|
||||||
|
|
||||||
|
Before installing Rustlings, you need to have the **latest version of Rust** installed.
|
||||||
|
Visit [www.rust-lang.org/tools/install](https://www.rust-lang.org/tools/install) for further instructions on installing Rust.
|
||||||
|
This will also install _Cargo_, Rust's package/project manager.
|
||||||
|
|
||||||
|
> 🐧 If you are on Linux, make sure you have installed `gcc` (for a linker).
|
||||||
|
>
|
||||||
|
> Deb: `sudo apt install gcc`
|
||||||
|
>
|
||||||
|
> Dnf: `sudo dnf install gcc`
|
||||||
|
|
||||||
|
> 🍎 If you are on MacOS, make sure you have installed Xcode and its developer tools by running `xcode-select --install`.
|
||||||
|
|
||||||
|
### Installing Rustlings
|
||||||
|
|
||||||
|
The following command will download and compile Rustlings:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cargo install rustlings
|
||||||
|
```
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary><strong>If the installation fails…</strong> (<em>click to expand</em>)</summary>
|
||||||
|
|
||||||
|
- 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)
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
### Initialization
|
||||||
|
|
||||||
|
After installing Rustlings, run the following command to initialize the `rustlings/` directory:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
rustlings init
|
||||||
|
```
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary><strong>If the command <code>rustlings</code> can't be found…</strong> (<em>click to expand</em>)</summary>
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
The solution is to …
|
||||||
|
|
||||||
|
- either add `~/.cargo/bin` manually to `PATH`
|
||||||
|
- or to uninstall Rust from the package manager and install it using the official way with `rustup`: https://www.rust-lang.org/tools/install
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
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).
|
||||||
|
|
||||||
|
## 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](#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><strong>If detecting file changes in the <code>exercises/</code> directory fails…</strong> (<em>click to expand</em>)</summary>
|
||||||
|
|
||||||
|
> 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 virtual machine (e.g. WSL).
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
|
### 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_ category of the discussions](https://github.com/rust-lang/rustlings/discussions/categories/q-a?discussions_q=) if your question wasn't asked yet 💡
|
||||||
|
|
||||||
|
## 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.
|
||||||
|
|
||||||
|
## Uninstalling Rustlings
|
||||||
|
|
||||||
|
If you want to remove Rustlings from your system, run the following command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cargo uninstall rustlings
|
||||||
|
```
|
66
website/content/custom-exercises/index.md
Normal file
66
website/content/custom-exercises/index.md
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
+++
|
||||||
|
title = "Custom Exercises"
|
||||||
|
+++
|
||||||
|
|
||||||
|
Custom exercises are a set of exercises maintained by the community.
|
||||||
|
You can use the same `rustlings` program that you installed with `cargo install rustlings` to run them:
|
||||||
|
|
||||||
|
- 🇯🇵 [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.
|
||||||
|
|
||||||
|
Do you want to create your own set of Rustlings exercises to focus on some specific topic?
|
||||||
|
Or do you want to translate the original Rustlings exercises?
|
||||||
|
|
||||||
|
<!-- toc -->
|
||||||
|
|
||||||
|
The support of Rustlings for custom exercises allows you to create your own set of Rustlings exercises to focus on some specific topic.
|
||||||
|
You could also offer a translation of the original Rustlings exercises as custom exercises.
|
||||||
|
|
||||||
|
## Getting started
|
||||||
|
|
||||||
|
To create custom exercises, install Rustlings and run `rustlings dev new PROJECT_NAME`.
|
||||||
|
This command will, similar to `cargo new PROJECT_NAME`, create a template directory called `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.
|
||||||
|
|
||||||
|
## Create an exercise
|
||||||
|
|
||||||
|
Here is an example of the metadata of one file:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[[exercises]]
|
||||||
|
name = "intro1"
|
||||||
|
hint = """
|
||||||
|
To finish this exercise, you need to …
|
||||||
|
This link 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 🎉
|
||||||
|
|
||||||
|
## Publish
|
||||||
|
|
||||||
|
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 set of 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 the users to not look at the solution too early 😉
|
||||||
|
|
||||||
|
## Share
|
||||||
|
|
||||||
|
After publishing your set of exercises, open an issue or a pull request in the official Rustlings repository to link to your project in the README 😃
|
@ -2,22 +2,22 @@
|
|||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
h1 {
|
h1 {
|
||||||
@apply text-4xl mt-3 mb-3 text-gray-50 font-bold;
|
@apply text-4xl mt-3 mb-3 font-bold;
|
||||||
}
|
}
|
||||||
h2 {
|
h2 {
|
||||||
@apply text-3xl mt-4 mb-1.5 text-gray-50 font-bold;
|
@apply text-3xl mt-4 mb-1.5 font-bold;
|
||||||
}
|
}
|
||||||
h3 {
|
h3 {
|
||||||
@apply text-2xl mt-5 mb-1.5 text-gray-50 font-bold;
|
@apply text-2xl mt-5 mb-1.5 font-bold;
|
||||||
}
|
}
|
||||||
h4 {
|
h4 {
|
||||||
@apply text-xl mt-6 mb-1.5 text-gray-50 font-bold;
|
@apply text-xl mt-6 mb-1.5 font-bold;
|
||||||
}
|
}
|
||||||
p {
|
p {
|
||||||
@apply mb-2;
|
@apply mb-2;
|
||||||
}
|
}
|
||||||
a {
|
a {
|
||||||
@apply text-[#F74C00] underline hover:decoration-orange-400 transition duration-300;
|
@apply text-[#FFC832] underline hover:decoration-orange-400 transition duration-300;
|
||||||
}
|
}
|
||||||
ul {
|
ul {
|
||||||
@apply mt-2 mb-3 ml-1 list-disc list-inside marker:text-sky-600;
|
@apply mt-2 mb-3 ml-1 list-disc list-inside marker:text-sky-600;
|
||||||
@ -41,11 +41,11 @@
|
|||||||
@apply max-w-full w-full h-full mx-auto my-5 object-contain md:w-3/4 lg:w-3/5 rounded-sm shadow-sm;
|
@apply max-w-full w-full h-full mx-auto my-5 object-contain md:w-3/4 lg:w-3/5 rounded-sm shadow-sm;
|
||||||
}
|
}
|
||||||
blockquote {
|
blockquote {
|
||||||
@apply p-4 my-3 border-s-4 border-gray-300 bg-gray-800 italic;
|
@apply px-3 pt-2 pb-0.5 my-4 border-s-4 border-white/80 bg-white/7 rounded-sm italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
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-gray-500/75;
|
@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 {
|
pre code mark {
|
||||||
@apply pb-0.5 pt-1 pr-px text-inherit rounded-xs;
|
@apply pb-0.5 pt-1 pr-px text-inherit rounded-xs;
|
||||||
|
@ -2,4 +2,4 @@ zola:
|
|||||||
zola serve --open
|
zola serve --open
|
||||||
|
|
||||||
tailwind:
|
tailwind:
|
||||||
fnm exec --using latest npx @tailwindcss/cli -i input.css -o static/main.css
|
fnm exec --using latest npx @tailwindcss/cli -w -i input.css -o static/main.css
|
||||||
|
16
website/templates/404.html
Normal file
16
website/templates/404.html
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% import "macros.html" as macros %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="flex flex-col mx-auto text-center">
|
||||||
|
<h1>DON'T PANIC!</h1>
|
||||||
|
<h2>404: Page not found!</h2>
|
||||||
|
|
||||||
|
<img class="max-h-[50vh]"
|
||||||
|
src="{{ get_url(path='images/panic.svg') | safe }}"
|
||||||
|
alt="">
|
||||||
|
|
||||||
|
{{ macros::btn(link=get_url(path="/") , content="Back to the homepage") }}
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
2
website/templates/anchor-link.html
Normal file
2
website/templates/anchor-link.html
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
<a class="text-white no-underline transition-none hover:underline"
|
||||||
|
href="#{{ id }}"></a>
|
83
website/templates/base.html
Normal file
83
website/templates/base.html
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
<!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-3 mx-auto min-h-screen text-lg text-white break-words bg-[#2A3439] lg:px-5 2xl:container">
|
||||||
|
<header class="flex gap-x-6 items-center py-2 px-2.5 mb-1 bg-black/30 rounded-full">
|
||||||
|
<a class="transition duration-500 hover:scale-110"
|
||||||
|
href="{{ get_url(path='/') | safe }}"
|
||||||
|
aria-hidden="true">
|
||||||
|
<img class="m-0 w-12 h-12 rounded-full"
|
||||||
|
src="{{ get_url(path=config.extra.logo_path) | safe }}"
|
||||||
|
alt="">
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<nav class="flex gap-x-6 items-center font-bold">
|
||||||
|
{% for menu_item in config.extra.menu_items %}
|
||||||
|
<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-3 mt-auto">
|
||||||
|
<img class="m-0 mx-auto w-20 h-20"
|
||||||
|
src="{{ get_url(path='images/happy_ferris.svg') | safe }}"
|
||||||
|
alt="">
|
||||||
|
|
||||||
|
<nav class="flex flex-col gap-y-3 justify-around py-3 text-center bg-black/30 rounded-sm sm:flex-row sm:rounded-full">
|
||||||
|
{% for footer_item in config.extra.footer_items %}
|
||||||
|
<a class="text-sm no-underline" href="{{ footer_item.url | safe }}">{{ footer_item.name }}</a>
|
||||||
|
{% endfor %}
|
||||||
|
</nav>
|
||||||
|
</footer>
|
||||||
|
</body>
|
||||||
|
</html>
|
11
website/templates/index.html
Normal file
11
website/templates/index.html
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% import "macros.html" as macros %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="m-3">
|
||||||
|
<h1>Rustlings</h1>
|
||||||
|
|
||||||
|
{{ section.content | replace(from="<!-- toc -->", to=macros::toc() ) | safe }}
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
46
website/templates/macros.html
Normal file
46
website/templates/macros.html
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
{% macro toc() %}
|
||||||
|
<p class="p-1 my-4 text-base rounded-sm sm:hidden bg-yellow-200/20">Landscape mode recommended on mobile devices</p>
|
||||||
|
|
||||||
|
{%- if page.toc -%}
|
||||||
|
{% set_global toc = page.toc %}
|
||||||
|
{%- else -%}
|
||||||
|
{% set_global toc = section.toc %}
|
||||||
|
{%- endif -%}
|
||||||
|
|
||||||
|
{% if toc %}
|
||||||
|
<div class="px-4 py-0.5 my-3 border-s-4 rounded-xl border-double">
|
||||||
|
<nav>
|
||||||
|
<ul class="ml-0 list-none">
|
||||||
|
{% for parent in 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>
|
||||||
|
{% endif %}
|
||||||
|
{% endmacro %}
|
||||||
|
|
||||||
|
{% macro btn(link, content) %}
|
||||||
|
<a class="py-1.5 px-3 my-2 no-underline bg-gray-800 rounded-xl transition duration-500 hover:scale-[1.02]"
|
||||||
|
href="{{ link | safe }}">{{ content | safe }}</a>
|
||||||
|
{% endmacro %}
|
11
website/templates/page.html
Normal file
11
website/templates/page.html
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% import "macros.html" as macros %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<article>
|
||||||
|
<h1>{{ page.title }}</h1>
|
||||||
|
|
||||||
|
{{ page.content | replace(from="<!-- toc -->", to=macros::toc() ) | safe }}
|
||||||
|
</article>
|
||||||
|
{% endblock %}
|
Loading…
x
Reference in New Issue
Block a user