hotfix: configurable threadpool size & new website starts
This commit is contained in:
parent
e18e25a571
commit
ab892d7453
|
@ -3940,7 +3940,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "trifid_api_entities"
|
||||
version = "0.1.0"
|
||||
version = "0.1.1"
|
||||
dependencies = [
|
||||
"sea-orm",
|
||||
]
|
||||
|
|
|
@ -78,6 +78,11 @@ url = "your-database-url-here"
|
|||
# SocketAddr. Optional. Default = 0.0.0.0:8080 (all IPs, port 8080)
|
||||
# bind = "0.0.0.0:8080"
|
||||
|
||||
# The number of worker threads to create.
|
||||
# Increase this number if your server is timing out requests.
|
||||
# usize. Optional. Default = 32
|
||||
# workers = 32
|
||||
|
||||
#### [tokens] ####
|
||||
# Configure options related to the various tokens that may be issued by the trifid-api server.
|
||||
[tokens]
|
||||
|
|
|
@ -76,6 +76,8 @@ pub struct TrifidConfigDatabase {
|
|||
pub struct TrifidConfigServer {
|
||||
#[serde(default = "socketaddr_8080")]
|
||||
pub bind: SocketAddr,
|
||||
#[serde(default = "default_workers")]
|
||||
pub workers: usize
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
|
@ -730,3 +732,5 @@ fn none<T>() -> Option<T> {
|
|||
fn is_none<T>(o: &Option<T>) -> bool {
|
||||
o.is_none()
|
||||
}
|
||||
|
||||
fn default_workers() -> usize { 32 }
|
|
@ -88,7 +88,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
|||
errors: vec![api_error],
|
||||
}),
|
||||
)
|
||||
.into()
|
||||
.into()
|
||||
}),
|
||||
)
|
||||
.wrap(RequestIdentifier::with_generator(random_id_no_id))
|
||||
|
@ -121,9 +121,10 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
|||
.service(routes::v1::hosts::get_host_overrides)
|
||||
.service(routes::v1::hosts::update_host_overrides)
|
||||
})
|
||||
.bind(CONFIG.server.bind)?
|
||||
.run()
|
||||
.await?;
|
||||
.workers(CONFIG.server.workers)
|
||||
.bind(CONFIG.server.bind)?
|
||||
.run()
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
book
|
|
@ -0,0 +1,16 @@
|
|||
[book]
|
||||
authors = ["core"]
|
||||
language = "en"
|
||||
multilingual = false
|
||||
src = "src"
|
||||
title = "Trifid Documentation"
|
||||
|
||||
[preprocessor]
|
||||
|
||||
[preprocessor.catppuccin]
|
||||
assets_version = "0.2.1" # DO NOT EDIT: Managed by `mdbook-catppuccin install`
|
||||
|
||||
[output]
|
||||
|
||||
[output.html]
|
||||
additional-css = ["./theme/catppuccin.css", "./theme/catppuccin-highlight.css"]
|
|
@ -0,0 +1,49 @@
|
|||
# Summary
|
||||
|
||||
[Introduction](./index.md)
|
||||
|
||||
# tfclient User's Guide
|
||||
|
||||
- [About tfclient](./tfclient/index.md)
|
||||
- [Platform Support](./tfclient/platform_support.md)
|
||||
- [Why can't tfclient support XXXX?](./tfclient/why_not_this_os.md)
|
||||
- [Testing tfclient on new platforms](./tfclient/untested_os.md)
|
||||
- [Installation](./tfclient/install/index.md)
|
||||
- [Windows](./tfclient/install/windows.md)
|
||||
- [macOS](./tfclient/install/macos.md)
|
||||
- [Linux](./tfclient/install/linux.md)
|
||||
- [NetBSD](./tfclient/install/netbsd.md)
|
||||
- [Usage](./tfclient/usage.md)
|
||||
|
||||
# trifid-api User's Guide
|
||||
|
||||
- [About trifid-api (for users)](./trifid-api/users/index.md)
|
||||
- [Supported Clients/Platforms](./trifid-api/users/supported_clients.md)
|
||||
- [How to configure your client](./trifid-api/users/client_setup.md)
|
||||
- [Why doesn't trifid support mobile devices?](./trifid-api/users/mobile.md)
|
||||
|
||||
# trifid-api Administrator's Guide
|
||||
|
||||
- [About trifid-api](./trifid-api/index.md)
|
||||
- [Installation](./trifid-api/install/index.md)
|
||||
- [Windows](./trifid-api/install/windows.md)
|
||||
- [macOS](./trifid-api/install/macos.md)
|
||||
- [Linux](./trifid-api/install/linux.md)
|
||||
- [Docker](./trifid-api/install/docker.md)
|
||||
- [Setup Guide](./trifid-api/guide/index.md)
|
||||
- [Installing trifid-api](./trifid-api/guide/installing.md)
|
||||
- [Setting up your database](./trifid-api/guide/database.md)
|
||||
- [Installing tfcli](./trifid-api/guide/tfcli.md)
|
||||
- [Configuring trifid-api](./trifid-api/guide/config.md)
|
||||
- [Creating an organization](./trifid-api/guide/firstorg.md)
|
||||
- [Enrolling a lighthouse](./trifid-api/guide/enroll.md)
|
||||
- [Troubleshooting](./trifid-api/troubleshooting.md)
|
||||
- [Config Reference](./trifid-api/config.md)
|
||||
|
||||
# tfcli User's Guide
|
||||
|
||||
- [About tfcli](./tfcli/index.md)
|
||||
- [Installation](./tfcli/install/index.md)
|
||||
- [Windows](./tfcli/install/windows.md)
|
||||
- [macOS](./tfcli/install/macos.md)
|
||||
- [Linux](./tfclient/install/linux.md)
|
|
@ -0,0 +1,19 @@
|
|||
# Introduction
|
||||
|
||||
**trifid** is a complete open-source reimplementation of the [Defined Networking](https://defined.net) management protocol for [Nebula](https://github.com/slackhq/nebula) networks.
|
||||
|
||||
It makes it easy to run a completley self-hosted mesh VPN with very little effort.
|
||||
|
||||
In addition to the API server reimplementation and custom client, we include a command-line tool for interacting with the [Management API](https://docs.defined.net), fully compatible with the upstream API or any custom API server like trifid.
|
||||
|
||||
We also include a Rust library for interacting with keys and certificates in the Nebula PKI. Find it on crates.rs as trifid-pki. This library is an implementation of the Nebula PKI system that is mostly feature-complete, with the exception of non-Curve25519 cryptography, which is currently unsupported.
|
||||
|
||||
This set of pages contains complete documentation on how to use the various parts of the trifid project, with the exception of the library crates, `dnapi-rs` and `trifid-pki`, as those are self-documented Rust libraries with good documentation available through docs.rs.
|
||||
|
||||
If you are looking for documentation on **tfclient**, the trifid implementation of dnclient, see [it's documentation index](./tfclient/index.md).
|
||||
|
||||
If you are a *user* on a trifid-api instance (you are part of an organization on the instance), see [the trifid-api user guide](./trifid-api/users/index.md).
|
||||
|
||||
If you are an administrator on a trifid-api instance or are looking to set one up, see [the trifid-api administrator guide](./trifid-api/index.md).
|
||||
|
||||
If you are looking for documentation on **tfcli**, the management CLI, see [it's documentation index](./tfcli/index.md).
|
|
@ -0,0 +1 @@
|
|||
# About tfcli
|
|
@ -0,0 +1 @@
|
|||
# Installation
|
|
@ -0,0 +1 @@
|
|||
# macOS
|
|
@ -0,0 +1 @@
|
|||
# Windows
|
|
@ -0,0 +1,7 @@
|
|||
# About tfclient
|
||||
|
||||
**tfclient** is an open-source VPN client for the Defined Networking management protocol. It is built around the Nebula mesh vpn originally created by Slack, and now maintained by Defined Networking.
|
||||
|
||||
tfclient is written in Rust, and can run on most platforms. For more information on platform support, see [Platform Support](./platform_support.md).
|
||||
|
||||
To learn how to install or use tfclient, visit the respective pages for [Installation](./install/index.md) or [Usage](./usage.md).
|
|
@ -0,0 +1,5 @@
|
|||
# Installation
|
||||
|
||||
For now, tfclient needs to be compiled from source. Packaged binaries are planned but will come later as the project matures.
|
||||
|
||||
Please refer to the relavent page for your system in the sidebar for instructions on how to compile and install tfclient.
|
|
@ -0,0 +1,97 @@
|
|||
# Linux Installation
|
||||
|
||||
## 1. Set up your compiler toolchain
|
||||
|
||||
In order to compile tfclient, you will need a functional Rust compiler and a functional C compiler suite. You will also need a copy of the `git` command-line tools.
|
||||
|
||||
If you don't have Rust installed, we highly recommend you use `rustup`:
|
||||
|
||||
```
|
||||
curl --proto "=https" --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||
```
|
||||
|
||||
Follow the instructions on-screen.
|
||||
|
||||
Before continuing, ensure you have a Rust compiler:
|
||||
|
||||
```
|
||||
$ cargo -V
|
||||
```
|
||||
|
||||
This command should display `cargo`'s version. If it does not, ensure Rust is installed properly.
|
||||
|
||||
You will also need a functioning Go compiler, with CGo support, and `libclang` installed.
|
||||
|
||||
Ensure you have:
|
||||
- a functioning Rust compiler
|
||||
- a functioning Go compiler, with CGo support
|
||||
- libclang installed
|
||||
|
||||
## 2. Acquire a copy of the tfclient source code
|
||||
|
||||
First, determine the most recent release of tfclient. Visit [the refs page](https://git.e3t.cc/~core/trifid/refs), and find the most recent tfclient release.
|
||||
|
||||
For example, if you see `tfclient-v0.2.3`, the latest version of tfclient is `0.2.3`.
|
||||
|
||||
Next, download the tfclient source code:
|
||||
|
||||
```
|
||||
$ git clone https://git.e3t.cc/~core/trifid --depth 0 -b [desired tfclient version]
|
||||
$ cd tfclient
|
||||
```
|
||||
|
||||
## 3. Compile tfclient
|
||||
|
||||
Finally, compile the tfclient binary with:
|
||||
|
||||
```
|
||||
$ cargo build --release --bin tfclient
|
||||
```
|
||||
|
||||
This can take a very long time depending on your computer specs, and requires an internet connection.
|
||||
|
||||
## 4. Install tfclient system-wide
|
||||
|
||||
Once the build finishes, the resulting binary will be `target/release/tfclient`. Copy this to a location in the system PATH, such as `/bin` or `/usr/bin`.
|
||||
|
||||
## (Optional) 5. Create a system service
|
||||
|
||||
The following section assumes you have installed tfclient to `/usr/bin/tfclient`, and you wish to use the upstream DN API, `https://api.defined.net`. You will need to change these values in the
|
||||
|
||||
This will vary depending on your system. See the below sections for examples.
|
||||
|
||||
### SystemD
|
||||
|
||||
```
|
||||
[Unit]
|
||||
Description=A client for Defined Networking mesh networks
|
||||
Wants=basic.target network.target
|
||||
After=basic.target network.target network-online.target
|
||||
|
||||
[Service]
|
||||
SyslogIdentifier=tfclient
|
||||
ExecStart=/usr/bin/tfclient run --server https://api.defined.net --name tfclient
|
||||
Restart=always
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
Place this file in `/usr/lib/systemd/system/tfclient.service`, and start and enable it with `systemctl enable --now tfclient`.
|
||||
|
||||
### runit
|
||||
|
||||
Create a new folder named `tfclient` in your service directory. For example, on Void Linux, this is `/etc/sv/`.
|
||||
|
||||
Create a new **executable** file named `run` in this directory (Void Linux Example: `/etc/sv/tfclient/run`), with the following contents:
|
||||
|
||||
```
|
||||
#!/bin/bash
|
||||
exec 2>&1 /usr/bin/tfclient --server https://api.defined.net --name tfclient > /var/log/tfclient.log
|
||||
```
|
||||
|
||||
Link the service folder to the runsvdir. For Void Linux, this is `/var/service`:
|
||||
|
||||
```
|
||||
$ ln -s /etc/sv/tfclient /var/service/
|
||||
```
|
|
@ -0,0 +1 @@
|
|||
# macOS
|
|
@ -0,0 +1 @@
|
|||
# NetBSD
|
|
@ -0,0 +1 @@
|
|||
# Windows
|
|
@ -0,0 +1,22 @@
|
|||
# Platform Support
|
||||
|
||||
tfclient is supported on most platforms. tfclient is broken up into two "support tiers":
|
||||
|
||||
- 'Tier 1' platforms have full support, including linking to and managing the nebula binary. No extra work is required on these platforms - just install tfclient and run!
|
||||
- 'Tier 2' platforms cannot link to the nebula-ffi CGo binary due to platform limitations. On these platforms, tfclient must be compiled in Tier 2 mode, and the user is responsible for managing the Nebula binary and ensuring it points to the tfclient-managed config file. Documentation on how to use tfclient on Tier 2 platforms can be found [here](docs/tfclient/tier-2-building.md)
|
||||
|
||||
| Operating System / Architecture | tfclient support tier |
|
||||
|---------------------------------|---------------------------------------|
|
||||
| Windows (all architectures ) | Tier 2 |
|
||||
| Darwin (OSX, macOS) | Tier 2 - [untested](./untested_os.md) |
|
||||
| FreeBSD (amd64) | Tier 1 - [untested](./untested_os.md) |
|
||||
| NetBSD | Tier 2 |
|
||||
| Linux | Tier 1 |
|
||||
|
||||
On platforms marked 'untested', the trifid maintainers were unable to test tfclient on that platform. Help is wanted to test tfclient on as many platforms as possible!
|
||||
|
||||
tfclient should work on most platforms, but the authors of tfclient don't have every device and OS combo in the world.
|
||||
|
||||
If you are willing to run untested software on your machine to contribute to trifid, consider testing tfclient on your device and [reporting your findings back to us](https://lists.e3t.cc/~core/trifid-devel). This is super helpful to us and helps us maintain trifid for more platforms when we have users willing to test the latest versions and report bugs to us. If you are interested, please see [this page](./untested_os.md).
|
||||
|
||||
Unfortunately, [tfclient won't work everywhere](./why_not_this_os.md). See [here](./why_not_this_os.md) for details.
|
|
@ -0,0 +1,13 @@
|
|||
# Help us out - test tfclient on new platforms
|
||||
|
||||
There are [lots](index.md#where-does-trifid-work) of operating systems in which `tfclient` *should* work, but due to a lack of devices, it cannot be tested. If you have a system running one of these devices and want to help out the project, please test tfclient for functionality on your device!
|
||||
|
||||
| **Notice**: While tfclient is almost always perfectly safe, there are always risks to running untested software on production machines. Be careful out there! |
|
||||
|---------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
|
||||
If you aren't able to get tfclient to compile with nebula-ffi, consider trying it as a [Tier 2 platform](docs/tfclient/tier-2-building.md). Documentation on how to do this can be found [here](docs/tfclient/tier-2-building.md).
|
||||
|
||||
Any findings, positive or negative, can be posted straight to [trifid-devel](https://lists.e3t.cc/~core/trifid-devel).
|
||||
|
||||
Thanks! We really appreciate it.
|
||||
|
|
@ -0,0 +1 @@
|
|||
# Usage
|
|
@ -0,0 +1 @@
|
|||
# Why can't tfclient support XXXX?
|
|
@ -0,0 +1 @@
|
|||
# How to configure your client
|
|
@ -0,0 +1 @@
|
|||
# Config Reference
|
|
@ -0,0 +1 @@
|
|||
# Configuring trifid-api
|
|
@ -0,0 +1 @@
|
|||
# Setting up your database
|
|
@ -0,0 +1 @@
|
|||
# Enrolling a lighthouse
|
|
@ -0,0 +1 @@
|
|||
# Creating an organization
|
|
@ -0,0 +1 @@
|
|||
# Setup Guide
|
|
@ -0,0 +1 @@
|
|||
# Installing trifid-api
|
|
@ -0,0 +1 @@
|
|||
# Installing tfcli
|
|
@ -0,0 +1 @@
|
|||
# About trifid-api
|
|
@ -0,0 +1 @@
|
|||
# Docker
|
|
@ -0,0 +1 @@
|
|||
# Installation
|
|
@ -0,0 +1 @@
|
|||
# Linux
|
|
@ -0,0 +1 @@
|
|||
# macOS
|
|
@ -0,0 +1 @@
|
|||
# Windows
|
|
@ -0,0 +1 @@
|
|||
# Supported Clients/Platforms
|
|
@ -0,0 +1 @@
|
|||
# Troubleshooting
|
|
@ -0,0 +1 @@
|
|||
# How to configure your client
|
|
@ -0,0 +1 @@
|
|||
# About trifid-api (for users)
|
|
@ -0,0 +1 @@
|
|||
# Why doesn't trifid support mobile devices?
|
|
@ -0,0 +1 @@
|
|||
# Supported Clients/Platforms
|
|
@ -0,0 +1,607 @@
|
|||
.mocha code .hljs-keyword {
|
||||
color: #cba6f7;
|
||||
}
|
||||
.mocha code .hljs-built_in {
|
||||
color: #f38ba8;
|
||||
}
|
||||
.mocha code .hljs-type {
|
||||
color: #f9e2af;
|
||||
}
|
||||
.mocha code .hljs-literal {
|
||||
color: #fab387;
|
||||
}
|
||||
.mocha code .hljs-number {
|
||||
color: #fab387;
|
||||
}
|
||||
.mocha code .hljs-operator {
|
||||
color: #94e2d5;
|
||||
}
|
||||
.mocha code .hljs-punctuation {
|
||||
color: #bac2de;
|
||||
}
|
||||
.mocha code .hljs-property {
|
||||
color: #94e2d5;
|
||||
}
|
||||
.mocha code .hljs-regexp {
|
||||
color: #f5c2e7;
|
||||
}
|
||||
.mocha code .hljs-string {
|
||||
color: #a6e3a1;
|
||||
}
|
||||
.mocha code .hljs-char.escape_ {
|
||||
color: #a6e3a1;
|
||||
}
|
||||
.mocha code .hljs-subst {
|
||||
color: #a6adc8;
|
||||
}
|
||||
.mocha code .hljs-symbol {
|
||||
color: #f2cdcd;
|
||||
}
|
||||
.mocha code .hljs-variable {
|
||||
color: #cba6f7;
|
||||
}
|
||||
.mocha code .hljs-variable.language_ {
|
||||
color: #cba6f7;
|
||||
}
|
||||
.mocha code .hljs-variable.constant_ {
|
||||
color: #fab387;
|
||||
}
|
||||
.mocha code .hljs-title {
|
||||
color: #89b4fa;
|
||||
}
|
||||
.mocha code .hljs-title.class_ {
|
||||
color: #f9e2af;
|
||||
}
|
||||
.mocha code .hljs-title.function_ {
|
||||
color: #89b4fa;
|
||||
}
|
||||
.mocha code .hljs-params {
|
||||
color: #cdd6f4;
|
||||
}
|
||||
.mocha code .hljs-comment {
|
||||
color: #585b70;
|
||||
}
|
||||
.mocha code .hljs-doctag {
|
||||
color: #f38ba8;
|
||||
}
|
||||
.mocha code .hljs-meta {
|
||||
color: #fab387;
|
||||
}
|
||||
.mocha code .hljs-section {
|
||||
color: #89b4fa;
|
||||
}
|
||||
.mocha code .hljs-tag {
|
||||
color: #a6adc8;
|
||||
}
|
||||
.mocha code .hljs-name {
|
||||
color: #cba6f7;
|
||||
}
|
||||
.mocha code .hljs-attr {
|
||||
color: #89b4fa;
|
||||
}
|
||||
.mocha code .hljs-attribute {
|
||||
color: #a6e3a1;
|
||||
}
|
||||
.mocha code .hljs-bullet {
|
||||
color: #94e2d5;
|
||||
}
|
||||
.mocha code .hljs-code {
|
||||
color: #a6e3a1;
|
||||
}
|
||||
.mocha code .hljs-emphasis {
|
||||
color: #f38ba8;
|
||||
font-style: italic;
|
||||
}
|
||||
.mocha code .hljs-strong {
|
||||
color: #f38ba8;
|
||||
font-weight: bold;
|
||||
}
|
||||
.mocha code .hljs-formula {
|
||||
color: #94e2d5;
|
||||
}
|
||||
.mocha code .hljs-link {
|
||||
color: #74c7ec;
|
||||
font-style: italic;
|
||||
}
|
||||
.mocha code .hljs-quote {
|
||||
color: #a6e3a1;
|
||||
font-style: italic;
|
||||
}
|
||||
.mocha code .hljs-selector-tag {
|
||||
color: #f9e2af;
|
||||
}
|
||||
.mocha code .hljs-selector-id {
|
||||
color: #89b4fa;
|
||||
}
|
||||
.mocha code .hljs-selector-class {
|
||||
color: #94e2d5;
|
||||
}
|
||||
.mocha code .hljs-selector-attr {
|
||||
color: #cba6f7;
|
||||
}
|
||||
.mocha code .hljs-selector-pseudo {
|
||||
color: #94e2d5;
|
||||
}
|
||||
.mocha code .hljs-template-tag {
|
||||
color: #f2cdcd;
|
||||
}
|
||||
.mocha code .hljs-template-variable {
|
||||
color: #f2cdcd;
|
||||
}
|
||||
.mocha code .hljs-diff-addition {
|
||||
color: #a6e3a1;
|
||||
background: rgba(166, 227, 161, 0.15);
|
||||
}
|
||||
.mocha code .hljs-diff-deletion {
|
||||
color: #f38ba8;
|
||||
background: rgba(243, 139, 168, 0.15);
|
||||
}
|
||||
|
||||
.macchiato code .hljs-keyword {
|
||||
color: #c6a0f6;
|
||||
}
|
||||
.macchiato code .hljs-built_in {
|
||||
color: #ed8796;
|
||||
}
|
||||
.macchiato code .hljs-type {
|
||||
color: #eed49f;
|
||||
}
|
||||
.macchiato code .hljs-literal {
|
||||
color: #f5a97f;
|
||||
}
|
||||
.macchiato code .hljs-number {
|
||||
color: #f5a97f;
|
||||
}
|
||||
.macchiato code .hljs-operator {
|
||||
color: #8bd5ca;
|
||||
}
|
||||
.macchiato code .hljs-punctuation {
|
||||
color: #b8c0e0;
|
||||
}
|
||||
.macchiato code .hljs-property {
|
||||
color: #8bd5ca;
|
||||
}
|
||||
.macchiato code .hljs-regexp {
|
||||
color: #f5bde6;
|
||||
}
|
||||
.macchiato code .hljs-string {
|
||||
color: #a6da95;
|
||||
}
|
||||
.macchiato code .hljs-char.escape_ {
|
||||
color: #a6da95;
|
||||
}
|
||||
.macchiato code .hljs-subst {
|
||||
color: #a5adcb;
|
||||
}
|
||||
.macchiato code .hljs-symbol {
|
||||
color: #f0c6c6;
|
||||
}
|
||||
.macchiato code .hljs-variable {
|
||||
color: #c6a0f6;
|
||||
}
|
||||
.macchiato code .hljs-variable.language_ {
|
||||
color: #c6a0f6;
|
||||
}
|
||||
.macchiato code .hljs-variable.constant_ {
|
||||
color: #f5a97f;
|
||||
}
|
||||
.macchiato code .hljs-title {
|
||||
color: #8aadf4;
|
||||
}
|
||||
.macchiato code .hljs-title.class_ {
|
||||
color: #eed49f;
|
||||
}
|
||||
.macchiato code .hljs-title.function_ {
|
||||
color: #8aadf4;
|
||||
}
|
||||
.macchiato code .hljs-params {
|
||||
color: #cad3f5;
|
||||
}
|
||||
.macchiato code .hljs-comment {
|
||||
color: #5b6078;
|
||||
}
|
||||
.macchiato code .hljs-doctag {
|
||||
color: #ed8796;
|
||||
}
|
||||
.macchiato code .hljs-meta {
|
||||
color: #f5a97f;
|
||||
}
|
||||
.macchiato code .hljs-section {
|
||||
color: #8aadf4;
|
||||
}
|
||||
.macchiato code .hljs-tag {
|
||||
color: #a5adcb;
|
||||
}
|
||||
.macchiato code .hljs-name {
|
||||
color: #c6a0f6;
|
||||
}
|
||||
.macchiato code .hljs-attr {
|
||||
color: #8aadf4;
|
||||
}
|
||||
.macchiato code .hljs-attribute {
|
||||
color: #a6da95;
|
||||
}
|
||||
.macchiato code .hljs-bullet {
|
||||
color: #8bd5ca;
|
||||
}
|
||||
.macchiato code .hljs-code {
|
||||
color: #a6da95;
|
||||
}
|
||||
.macchiato code .hljs-emphasis {
|
||||
color: #ed8796;
|
||||
font-style: italic;
|
||||
}
|
||||
.macchiato code .hljs-strong {
|
||||
color: #ed8796;
|
||||
font-weight: bold;
|
||||
}
|
||||
.macchiato code .hljs-formula {
|
||||
color: #8bd5ca;
|
||||
}
|
||||
.macchiato code .hljs-link {
|
||||
color: #7dc4e4;
|
||||
font-style: italic;
|
||||
}
|
||||
.macchiato code .hljs-quote {
|
||||
color: #a6da95;
|
||||
font-style: italic;
|
||||
}
|
||||
.macchiato code .hljs-selector-tag {
|
||||
color: #eed49f;
|
||||
}
|
||||
.macchiato code .hljs-selector-id {
|
||||
color: #8aadf4;
|
||||
}
|
||||
.macchiato code .hljs-selector-class {
|
||||
color: #8bd5ca;
|
||||
}
|
||||
.macchiato code .hljs-selector-attr {
|
||||
color: #c6a0f6;
|
||||
}
|
||||
.macchiato code .hljs-selector-pseudo {
|
||||
color: #8bd5ca;
|
||||
}
|
||||
.macchiato code .hljs-template-tag {
|
||||
color: #f0c6c6;
|
||||
}
|
||||
.macchiato code .hljs-template-variable {
|
||||
color: #f0c6c6;
|
||||
}
|
||||
.macchiato code .hljs-diff-addition {
|
||||
color: #a6da95;
|
||||
background: rgba(166, 218, 149, 0.15);
|
||||
}
|
||||
.macchiato code .hljs-diff-deletion {
|
||||
color: #ed8796;
|
||||
background: rgba(237, 135, 150, 0.15);
|
||||
}
|
||||
|
||||
.frappe code .hljs-keyword {
|
||||
color: #ca9ee6;
|
||||
}
|
||||
.frappe code .hljs-built_in {
|
||||
color: #e78284;
|
||||
}
|
||||
.frappe code .hljs-type {
|
||||
color: #e5c890;
|
||||
}
|
||||
.frappe code .hljs-literal {
|
||||
color: #ef9f76;
|
||||
}
|
||||
.frappe code .hljs-number {
|
||||
color: #ef9f76;
|
||||
}
|
||||
.frappe code .hljs-operator {
|
||||
color: #81c8be;
|
||||
}
|
||||
.frappe code .hljs-punctuation {
|
||||
color: #b5bfe2;
|
||||
}
|
||||
.frappe code .hljs-property {
|
||||
color: #81c8be;
|
||||
}
|
||||
.frappe code .hljs-regexp {
|
||||
color: #f4b8e4;
|
||||
}
|
||||
.frappe code .hljs-string {
|
||||
color: #a6d189;
|
||||
}
|
||||
.frappe code .hljs-char.escape_ {
|
||||
color: #a6d189;
|
||||
}
|
||||
.frappe code .hljs-subst {
|
||||
color: #a5adce;
|
||||
}
|
||||
.frappe code .hljs-symbol {
|
||||
color: #eebebe;
|
||||
}
|
||||
.frappe code .hljs-variable {
|
||||
color: #ca9ee6;
|
||||
}
|
||||
.frappe code .hljs-variable.language_ {
|
||||
color: #ca9ee6;
|
||||
}
|
||||
.frappe code .hljs-variable.constant_ {
|
||||
color: #ef9f76;
|
||||
}
|
||||
.frappe code .hljs-title {
|
||||
color: #8caaee;
|
||||
}
|
||||
.frappe code .hljs-title.class_ {
|
||||
color: #e5c890;
|
||||
}
|
||||
.frappe code .hljs-title.function_ {
|
||||
color: #8caaee;
|
||||
}
|
||||
.frappe code .hljs-params {
|
||||
color: #c6d0f5;
|
||||
}
|
||||
.frappe code .hljs-comment {
|
||||
color: #626880;
|
||||
}
|
||||
.frappe code .hljs-doctag {
|
||||
color: #e78284;
|
||||
}
|
||||
.frappe code .hljs-meta {
|
||||
color: #ef9f76;
|
||||
}
|
||||
.frappe code .hljs-section {
|
||||
color: #8caaee;
|
||||
}
|
||||
.frappe code .hljs-tag {
|
||||
color: #a5adce;
|
||||
}
|
||||
.frappe code .hljs-name {
|
||||
color: #ca9ee6;
|
||||
}
|
||||
.frappe code .hljs-attr {
|
||||
color: #8caaee;
|
||||
}
|
||||
.frappe code .hljs-attribute {
|
||||
color: #a6d189;
|
||||
}
|
||||
.frappe code .hljs-bullet {
|
||||
color: #81c8be;
|
||||
}
|
||||
.frappe code .hljs-code {
|
||||
color: #a6d189;
|
||||
}
|
||||
.frappe code .hljs-emphasis {
|
||||
color: #e78284;
|
||||
font-style: italic;
|
||||
}
|
||||
.frappe code .hljs-strong {
|
||||
color: #e78284;
|
||||
font-weight: bold;
|
||||
}
|
||||
.frappe code .hljs-formula {
|
||||
color: #81c8be;
|
||||
}
|
||||
.frappe code .hljs-link {
|
||||
color: #85c1dc;
|
||||
font-style: italic;
|
||||
}
|
||||
.frappe code .hljs-quote {
|
||||
color: #a6d189;
|
||||
font-style: italic;
|
||||
}
|
||||
.frappe code .hljs-selector-tag {
|
||||
color: #e5c890;
|
||||
}
|
||||
.frappe code .hljs-selector-id {
|
||||
color: #8caaee;
|
||||
}
|
||||
.frappe code .hljs-selector-class {
|
||||
color: #81c8be;
|
||||
}
|
||||
.frappe code .hljs-selector-attr {
|
||||
color: #ca9ee6;
|
||||
}
|
||||
.frappe code .hljs-selector-pseudo {
|
||||
color: #81c8be;
|
||||
}
|
||||
.frappe code .hljs-template-tag {
|
||||
color: #eebebe;
|
||||
}
|
||||
.frappe code .hljs-template-variable {
|
||||
color: #eebebe;
|
||||
}
|
||||
.frappe code .hljs-diff-addition {
|
||||
color: #a6d189;
|
||||
background: rgba(166, 209, 137, 0.15);
|
||||
}
|
||||
.frappe code .hljs-diff-deletion {
|
||||
color: #e78284;
|
||||
background: rgba(231, 130, 132, 0.15);
|
||||
}
|
||||
|
||||
.latte code .hljs-keyword {
|
||||
color: #8839ef;
|
||||
}
|
||||
.latte code .hljs-built_in {
|
||||
color: #d20f39;
|
||||
}
|
||||
.latte code .hljs-type {
|
||||
color: #df8e1d;
|
||||
}
|
||||
.latte code .hljs-literal {
|
||||
color: #fe640b;
|
||||
}
|
||||
.latte code .hljs-number {
|
||||
color: #fe640b;
|
||||
}
|
||||
.latte code .hljs-operator {
|
||||
color: #179299;
|
||||
}
|
||||
.latte code .hljs-punctuation {
|
||||
color: #5c5f77;
|
||||
}
|
||||
.latte code .hljs-property {
|
||||
color: #179299;
|
||||
}
|
||||
.latte code .hljs-regexp {
|
||||
color: #ea76cb;
|
||||
}
|
||||
.latte code .hljs-string {
|
||||
color: #40a02b;
|
||||
}
|
||||
.latte code .hljs-char.escape_ {
|
||||
color: #40a02b;
|
||||
}
|
||||
.latte code .hljs-subst {
|
||||
color: #6c6f85;
|
||||
}
|
||||
.latte code .hljs-symbol {
|
||||
color: #dd7878;
|
||||
}
|
||||
.latte code .hljs-variable {
|
||||
color: #8839ef;
|
||||
}
|
||||
.latte code .hljs-variable.language_ {
|
||||
color: #8839ef;
|
||||
}
|
||||
.latte code .hljs-variable.constant_ {
|
||||
color: #fe640b;
|
||||
}
|
||||
.latte code .hljs-title {
|
||||
color: #1e66f5;
|
||||
}
|
||||
.latte code .hljs-title.class_ {
|
||||
color: #df8e1d;
|
||||
}
|
||||
.latte code .hljs-title.function_ {
|
||||
color: #1e66f5;
|
||||
}
|
||||
.latte code .hljs-params {
|
||||
color: #4c4f69;
|
||||
}
|
||||
.latte code .hljs-comment {
|
||||
color: #acb0be;
|
||||
}
|
||||
.latte code .hljs-doctag {
|
||||
color: #d20f39;
|
||||
}
|
||||
.latte code .hljs-meta {
|
||||
color: #fe640b;
|
||||
}
|
||||
.latte code .hljs-section {
|
||||
color: #1e66f5;
|
||||
}
|
||||
.latte code .hljs-tag {
|
||||
color: #6c6f85;
|
||||
}
|
||||
.latte code .hljs-name {
|
||||
color: #8839ef;
|
||||
}
|
||||
.latte code .hljs-attr {
|
||||
color: #1e66f5;
|
||||
}
|
||||
.latte code .hljs-attribute {
|
||||
color: #40a02b;
|
||||
}
|
||||
.latte code .hljs-bullet {
|
||||
color: #179299;
|
||||
}
|
||||
.latte code .hljs-code {
|
||||
color: #40a02b;
|
||||
}
|
||||
.latte code .hljs-emphasis {
|
||||
color: #d20f39;
|
||||
font-style: italic;
|
||||
}
|
||||
.latte code .hljs-strong {
|
||||
color: #d20f39;
|
||||
font-weight: bold;
|
||||
}
|
||||
.latte code .hljs-formula {
|
||||
color: #179299;
|
||||
}
|
||||
.latte code .hljs-link {
|
||||
color: #209fb5;
|
||||
font-style: italic;
|
||||
}
|
||||
.latte code .hljs-quote {
|
||||
color: #40a02b;
|
||||
font-style: italic;
|
||||
}
|
||||
.latte code .hljs-selector-tag {
|
||||
color: #df8e1d;
|
||||
}
|
||||
.latte code .hljs-selector-id {
|
||||
color: #1e66f5;
|
||||
}
|
||||
.latte code .hljs-selector-class {
|
||||
color: #179299;
|
||||
}
|
||||
.latte code .hljs-selector-attr {
|
||||
color: #8839ef;
|
||||
}
|
||||
.latte code .hljs-selector-pseudo {
|
||||
color: #179299;
|
||||
}
|
||||
.latte code .hljs-template-tag {
|
||||
color: #dd7878;
|
||||
}
|
||||
.latte code .hljs-template-variable {
|
||||
color: #dd7878;
|
||||
}
|
||||
.latte code .hljs-diff-addition {
|
||||
color: #40a02b;
|
||||
background: rgba(64, 160, 43, 0.15);
|
||||
}
|
||||
.latte code .hljs-diff-deletion {
|
||||
color: #d20f39;
|
||||
background: rgba(210, 15, 57, 0.15);
|
||||
}
|
||||
|
||||
.mocha code {
|
||||
color: #a6adc8;
|
||||
background: #181825;
|
||||
}
|
||||
.mocha .ace_gutter {
|
||||
color: #7f849c;
|
||||
background: #181825;
|
||||
}
|
||||
.mocha .ace_gutter-active-line.ace_gutter-cell {
|
||||
color: #f5c2e7;
|
||||
background: #181825;
|
||||
}
|
||||
|
||||
.macchiato code {
|
||||
color: #a5adcb;
|
||||
background: #1e2030;
|
||||
}
|
||||
.macchiato .ace_gutter {
|
||||
color: #8087a2;
|
||||
background: #1e2030;
|
||||
}
|
||||
.macchiato .ace_gutter-active-line.ace_gutter-cell {
|
||||
color: #f5bde6;
|
||||
background: #1e2030;
|
||||
}
|
||||
|
||||
.frappe code {
|
||||
color: #a5adce;
|
||||
background: #292c3c;
|
||||
}
|
||||
.frappe .ace_gutter {
|
||||
color: #838ba7;
|
||||
background: #292c3c;
|
||||
}
|
||||
.frappe .ace_gutter-active-line.ace_gutter-cell {
|
||||
color: #f4b8e4;
|
||||
background: #292c3c;
|
||||
}
|
||||
|
||||
.latte code {
|
||||
color: #6c6f85;
|
||||
background: #e6e9ef;
|
||||
}
|
||||
.latte .ace_gutter {
|
||||
color: #8c8fa1;
|
||||
background: #e6e9ef;
|
||||
}
|
||||
.latte .ace_gutter-active-line.ace_gutter-cell {
|
||||
color: #ea76cb;
|
||||
background: #e6e9ef;
|
||||
}
|
|
@ -0,0 +1,123 @@
|
|||
.mocha {
|
||||
--bg: #1e1e2e;
|
||||
--fg: #cdd6f4;
|
||||
--sidebar-bg: #181825;
|
||||
--sidebar-fg: #cdd6f4;
|
||||
--sidebar-non-existant: #6c7086;
|
||||
--sidebar-active: #89b4fa;
|
||||
--sidebar-spacer: #6c7086;
|
||||
--scrollbar: #6c7086;
|
||||
--icons: #6c7086;
|
||||
--icons-hover: #7f849c;
|
||||
--links: #89b4fa;
|
||||
--inline-code-color: #fab387;
|
||||
--theme-popup-bg: #181825;
|
||||
--theme-popup-border: #6c7086;
|
||||
--theme-hover: #6c7086;
|
||||
--quote-bg: #181825;
|
||||
--quote-border: #11111b;
|
||||
--table-border-color: #11111b;
|
||||
--table-header-bg: #181825;
|
||||
--table-alternate-bg: #11111b;
|
||||
--searchbar-border-color: #11111b;
|
||||
--searchbar-bg: #181825;
|
||||
--searchbar-fg: #cdd6f4;
|
||||
--searchbar-shadow-color: #11111b;
|
||||
--searchresults-header-fg: #cdd6f4;
|
||||
--searchresults-border-color: #11111b;
|
||||
--searchresults-li-bg: #1e1e2e;
|
||||
--search-mark-bg: #fab387;
|
||||
}
|
||||
|
||||
.macchiato {
|
||||
--bg: #24273a;
|
||||
--fg: #cad3f5;
|
||||
--sidebar-bg: #1e2030;
|
||||
--sidebar-fg: #cad3f5;
|
||||
--sidebar-non-existant: #6e738d;
|
||||
--sidebar-active: #8aadf4;
|
||||
--sidebar-spacer: #6e738d;
|
||||
--scrollbar: #6e738d;
|
||||
--icons: #6e738d;
|
||||
--icons-hover: #8087a2;
|
||||
--links: #8aadf4;
|
||||
--inline-code-color: #f5a97f;
|
||||
--theme-popup-bg: #1e2030;
|
||||
--theme-popup-border: #6e738d;
|
||||
--theme-hover: #6e738d;
|
||||
--quote-bg: #1e2030;
|
||||
--quote-border: #181926;
|
||||
--table-border-color: #181926;
|
||||
--table-header-bg: #1e2030;
|
||||
--table-alternate-bg: #181926;
|
||||
--searchbar-border-color: #181926;
|
||||
--searchbar-bg: #1e2030;
|
||||
--searchbar-fg: #cad3f5;
|
||||
--searchbar-shadow-color: #181926;
|
||||
--searchresults-header-fg: #cad3f5;
|
||||
--searchresults-border-color: #181926;
|
||||
--searchresults-li-bg: #24273a;
|
||||
--search-mark-bg: #f5a97f;
|
||||
}
|
||||
|
||||
.frappe {
|
||||
--bg: #303446;
|
||||
--fg: #c6d0f5;
|
||||
--sidebar-bg: #292c3c;
|
||||
--sidebar-fg: #c6d0f5;
|
||||
--sidebar-non-existant: #737994;
|
||||
--sidebar-active: #8caaee;
|
||||
--sidebar-spacer: #737994;
|
||||
--scrollbar: #737994;
|
||||
--icons: #737994;
|
||||
--icons-hover: #838ba7;
|
||||
--links: #8caaee;
|
||||
--inline-code-color: #ef9f76;
|
||||
--theme-popup-bg: #292c3c;
|
||||
--theme-popup-border: #737994;
|
||||
--theme-hover: #737994;
|
||||
--quote-bg: #292c3c;
|
||||
--quote-border: #232634;
|
||||
--table-border-color: #232634;
|
||||
--table-header-bg: #292c3c;
|
||||
--table-alternate-bg: #232634;
|
||||
--searchbar-border-color: #232634;
|
||||
--searchbar-bg: #292c3c;
|
||||
--searchbar-fg: #c6d0f5;
|
||||
--searchbar-shadow-color: #232634;
|
||||
--searchresults-header-fg: #c6d0f5;
|
||||
--searchresults-border-color: #232634;
|
||||
--searchresults-li-bg: #303446;
|
||||
--search-mark-bg: #ef9f76;
|
||||
}
|
||||
|
||||
.latte {
|
||||
--bg: #eff1f5;
|
||||
--fg: #4c4f69;
|
||||
--sidebar-bg: #e6e9ef;
|
||||
--sidebar-fg: #4c4f69;
|
||||
--sidebar-non-existant: #9ca0b0;
|
||||
--sidebar-active: #1e66f5;
|
||||
--sidebar-spacer: #9ca0b0;
|
||||
--scrollbar: #9ca0b0;
|
||||
--icons: #9ca0b0;
|
||||
--icons-hover: #8c8fa1;
|
||||
--links: #1e66f5;
|
||||
--inline-code-color: #fe640b;
|
||||
--theme-popup-bg: #e6e9ef;
|
||||
--theme-popup-border: #9ca0b0;
|
||||
--theme-hover: #9ca0b0;
|
||||
--quote-bg: #e6e9ef;
|
||||
--quote-border: #dce0e8;
|
||||
--table-border-color: #dce0e8;
|
||||
--table-header-bg: #e6e9ef;
|
||||
--table-alternate-bg: #dce0e8;
|
||||
--searchbar-border-color: #dce0e8;
|
||||
--searchbar-bg: #e6e9ef;
|
||||
--searchbar-fg: #4c4f69;
|
||||
--searchbar-shadow-color: #dce0e8;
|
||||
--searchresults-header-fg: #4c4f69;
|
||||
--searchresults-border-color: #dce0e8;
|
||||
--searchresults-li-bg: #eff1f5;
|
||||
--search-mark-bg: #fe640b;
|
||||
}
|
|
@ -0,0 +1,318 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html lang="{{ language }}" class="sidebar-visible no-js {{ default_theme }}">
|
||||
<head>
|
||||
<!-- Book generated using mdBook -->
|
||||
<meta charset="UTF-8">
|
||||
<title>{{ title }}</title>
|
||||
{{#if is_print }}
|
||||
<meta name="robots" content="noindex" />
|
||||
{{/if}}
|
||||
{{#if base_url}}
|
||||
<base href="{{ base_url }}">
|
||||
{{/if}}
|
||||
|
||||
|
||||
<!-- Custom HTML head -->
|
||||
{{> head}}
|
||||
|
||||
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
||||
<meta name="description" content="{{ description }}">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="theme-color" content="#ffffff" />
|
||||
|
||||
{{#if favicon_svg}}
|
||||
<link rel="icon" href="{{ path_to_root }}favicon.svg">
|
||||
{{/if}}
|
||||
{{#if favicon_png}}
|
||||
<link rel="shortcut icon" href="{{ path_to_root }}favicon.png">
|
||||
{{/if}}
|
||||
<link rel="stylesheet" href="{{ path_to_root }}css/variables.css">
|
||||
<link rel="stylesheet" href="{{ path_to_root }}css/general.css">
|
||||
<link rel="stylesheet" href="{{ path_to_root }}css/chrome.css">
|
||||
{{#if print_enable}}
|
||||
<link rel="stylesheet" href="{{ path_to_root }}css/print.css" media="print">
|
||||
{{/if}}
|
||||
|
||||
<!-- Fonts -->
|
||||
<link rel="stylesheet" href="{{ path_to_root }}FontAwesome/css/font-awesome.css">
|
||||
{{#if copy_fonts}}
|
||||
<link rel="stylesheet" href="{{ path_to_root }}fonts/fonts.css">
|
||||
{{/if}}
|
||||
|
||||
<!-- Highlight.js Stylesheets -->
|
||||
<link rel="stylesheet" href="{{ path_to_root }}highlight.css">
|
||||
<link rel="stylesheet" href="{{ path_to_root }}tomorrow-night.css">
|
||||
<link rel="stylesheet" href="{{ path_to_root }}ayu-highlight.css">
|
||||
|
||||
<!-- Custom theme stylesheets -->
|
||||
{{#each additional_css}}
|
||||
<link rel="stylesheet" href="{{ ../path_to_root }}{{ this }}">
|
||||
{{/each}}
|
||||
|
||||
{{#if mathjax_support}}
|
||||
<!-- MathJax -->
|
||||
<script async type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
||||
{{/if}}
|
||||
</head>
|
||||
<body>
|
||||
<!-- Provide site root to javascript -->
|
||||
<script type="text/javascript">
|
||||
var path_to_root = "{{ path_to_root }}";
|
||||
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "{{ preferred_dark_theme }}" : "{{ default_theme }}";
|
||||
</script>
|
||||
|
||||
<!-- Work around some values being stored in localStorage wrapped in quotes -->
|
||||
<script type="text/javascript">
|
||||
try {
|
||||
var theme = localStorage.getItem('mdbook-theme');
|
||||
var sidebar = localStorage.getItem('mdbook-sidebar');
|
||||
|
||||
if (theme.startsWith('"') && theme.endsWith('"')) {
|
||||
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
|
||||
}
|
||||
|
||||
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
|
||||
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
|
||||
}
|
||||
} catch (e) { }
|
||||
</script>
|
||||
|
||||
<!-- Set the theme before any content is loaded, prevents flash -->
|
||||
<script type="text/javascript">
|
||||
var theme;
|
||||
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
|
||||
if (theme === null || theme === undefined) { theme = default_theme; }
|
||||
var html = document.querySelector('html');
|
||||
html.classList.remove('no-js')
|
||||
html.classList.remove('{{ default_theme }}')
|
||||
html.classList.add(theme);
|
||||
html.classList.add('js');
|
||||
</script>
|
||||
|
||||
<!-- Hide / unhide sidebar before it is displayed -->
|
||||
<script type="text/javascript">
|
||||
var html = document.querySelector('html');
|
||||
var sidebar = 'hidden';
|
||||
if (document.body.clientWidth >= 1080) {
|
||||
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
|
||||
sidebar = sidebar || 'visible';
|
||||
}
|
||||
html.classList.remove('sidebar-visible');
|
||||
html.classList.add("sidebar-" + sidebar);
|
||||
</script>
|
||||
|
||||
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
|
||||
<div class="sidebar-scrollbox">
|
||||
{{#toc}}{{/toc}}
|
||||
</div>
|
||||
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
|
||||
</nav>
|
||||
|
||||
<div id="page-wrapper" class="page-wrapper">
|
||||
|
||||
<div class="page">
|
||||
{{> header}}
|
||||
<div id="menu-bar-hover-placeholder"></div>
|
||||
<div id="menu-bar" class="menu-bar sticky bordered">
|
||||
<div class="left-buttons">
|
||||
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
|
||||
<i class="fa fa-bars"></i>
|
||||
</button>
|
||||
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
|
||||
<i class="fa fa-paint-brush"></i>
|
||||
</button>
|
||||
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
|
||||
<li role="none"><button role="menuitem" class="theme" id="light">{{ theme_option "Light" }}</button></li>
|
||||
<li role="none"><button role="menuitem" class="theme" id="rust">{{ theme_option "Rust" }}</button></li>
|
||||
<li role="none"><button role="menuitem" class="theme" id="coal">{{ theme_option "Coal" }}</button></li>
|
||||
<li role="none"><button role="menuitem" class="theme" id="navy">{{ theme_option "Navy" }}</button></li>
|
||||
<li role="none"><button role="menuitem" class="theme" id="ayu">{{ theme_option "Ayu" }}</button></li>
|
||||
<li role="none"><button role="menuitem" class="theme" id="latte">{{ theme_option "Latte" }}</button></li>
|
||||
<li role="none"><button role="menuitem" class="theme" id="frappe">{{ theme_option "Frappé" }}</button></li>
|
||||
<li role="none"><button role="menuitem" class="theme" id="macchiato">{{ theme_option "Macchiato" }}</button></li>
|
||||
<li role="none"><button role="menuitem" class="theme" id="mocha">{{ theme_option "Mocha" }}</button></li>
|
||||
</ul>
|
||||
{{#if search_enabled}}
|
||||
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
|
||||
<i class="fa fa-search"></i>
|
||||
</button>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
<h1 class="menu-title">{{ book_title }}</h1>
|
||||
|
||||
<div class="right-buttons">
|
||||
{{#if print_enable}}
|
||||
<a href="{{ path_to_root }}print.html" title="Print this book" aria-label="Print this book">
|
||||
<i id="print-button" class="fa fa-print"></i>
|
||||
</a>
|
||||
{{/if}}
|
||||
{{#if git_repository_url}}
|
||||
<a href="{{git_repository_url}}" title="Git repository" aria-label="Git repository">
|
||||
<i id="git-repository-button" class="fa {{git_repository_icon}}"></i>
|
||||
</a>
|
||||
{{/if}}
|
||||
{{#if git_repository_edit_url}}
|
||||
<a href="{{git_repository_edit_url}}" title="Suggest an edit" aria-label="Suggest an edit">
|
||||
<i id="git-edit-button" class="fa fa-edit"></i>
|
||||
</a>
|
||||
{{/if}}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{#if search_enabled}}
|
||||
<div id="search-wrapper" class="hidden">
|
||||
<form id="searchbar-outer" class="searchbar-outer">
|
||||
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
|
||||
</form>
|
||||
<div id="searchresults-outer" class="searchresults-outer hidden">
|
||||
<div id="searchresults-header" class="searchresults-header"></div>
|
||||
<ul id="searchresults">
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
|
||||
<script type="text/javascript">
|
||||
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
|
||||
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
|
||||
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
|
||||
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
|
||||
});
|
||||
</script>
|
||||
|
||||
<div id="content" class="content">
|
||||
<main>
|
||||
{{{ content }}}
|
||||
</main>
|
||||
|
||||
<nav class="nav-wrapper" aria-label="Page navigation">
|
||||
<!-- Mobile navigation buttons -->
|
||||
{{#previous}}
|
||||
<a rel="prev" href="{{ path_to_root }}{{link}}" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||
<i class="fa fa-angle-left"></i>
|
||||
</a>
|
||||
{{/previous}}
|
||||
|
||||
{{#next}}
|
||||
<a rel="next" href="{{ path_to_root }}{{link}}" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||
<i class="fa fa-angle-right"></i>
|
||||
</a>
|
||||
{{/next}}
|
||||
|
||||
<div style="clear: both"></div>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<nav class="nav-wide-wrapper" aria-label="Page navigation">
|
||||
{{#previous}}
|
||||
<a rel="prev" href="{{ path_to_root }}{{link}}" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
|
||||
<i class="fa fa-angle-left"></i>
|
||||
</a>
|
||||
{{/previous}}
|
||||
|
||||
{{#next}}
|
||||
<a rel="next" href="{{ path_to_root }}{{link}}" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
|
||||
<i class="fa fa-angle-right"></i>
|
||||
</a>
|
||||
{{/next}}
|
||||
</nav>
|
||||
|
||||
</div>
|
||||
|
||||
{{#if live_reload_endpoint}}
|
||||
<!-- Livereload script (if served using the cli tool) -->
|
||||
<script type="text/javascript">
|
||||
const wsProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
|
||||
const wsAddress = wsProtocol + "//" + location.host + "/" + "{{{live_reload_endpoint}}}";
|
||||
const socket = new WebSocket(wsAddress);
|
||||
socket.onmessage = function (event) {
|
||||
if (event.data === "reload") {
|
||||
socket.close();
|
||||
location.reload();
|
||||
}
|
||||
};
|
||||
|
||||
window.onbeforeunload = function() {
|
||||
socket.close();
|
||||
}
|
||||
</script>
|
||||
{{/if}}
|
||||
|
||||
{{#if google_analytics}}
|
||||
<!-- Google Analytics Tag -->
|
||||
<script type="text/javascript">
|
||||
var localAddrs = ["localhost", "127.0.0.1", ""];
|
||||
|
||||
// make sure we don't activate google analytics if the developer is
|
||||
// inspecting the book locally...
|
||||
if (localAddrs.indexOf(document.location.hostname) === -1) {
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
ga('create', '{{google_analytics}}', 'auto');
|
||||
ga('send', 'pageview');
|
||||
}
|
||||
</script>
|
||||
{{/if}}
|
||||
|
||||
{{#if playground_line_numbers}}
|
||||
<script type="text/javascript">
|
||||
window.playground_line_numbers = true;
|
||||
</script>
|
||||
{{/if}}
|
||||
|
||||
{{#if playground_copyable}}
|
||||
<script type="text/javascript">
|
||||
window.playground_copyable = true;
|
||||
</script>
|
||||
{{/if}}
|
||||
|
||||
{{#if playground_js}}
|
||||
<script src="{{ path_to_root }}ace.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="{{ path_to_root }}editor.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="{{ path_to_root }}mode-rust.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="{{ path_to_root }}theme-dawn.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="{{ path_to_root }}theme-tomorrow_night.js" type="text/javascript" charset="utf-8"></script>
|
||||
{{/if}}
|
||||
|
||||
{{#if search_js}}
|
||||
<script src="{{ path_to_root }}elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="{{ path_to_root }}mark.min.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="{{ path_to_root }}searcher.js" type="text/javascript" charset="utf-8"></script>
|
||||
{{/if}}
|
||||
|
||||
<script src="{{ path_to_root }}clipboard.min.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="{{ path_to_root }}highlight.js" type="text/javascript" charset="utf-8"></script>
|
||||
<script src="{{ path_to_root }}book.js" type="text/javascript" charset="utf-8"></script>
|
||||
|
||||
<!-- Custom JS scripts -->
|
||||
{{#each additional_js}}
|
||||
<script type="text/javascript" src="{{ ../path_to_root }}{{this}}"></script>
|
||||
{{/each}}
|
||||
|
||||
{{#if is_print}}
|
||||
{{#if mathjax_support}}
|
||||
<script type="text/javascript">
|
||||
window.addEventListener('load', function() {
|
||||
MathJax.Hub.Register.StartupHook('End', function() {
|
||||
window.setTimeout(window.print, 100);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{{else}}
|
||||
<script type="text/javascript">
|
||||
window.addEventListener('load', function() {
|
||||
window.setTimeout(window.print, 100);
|
||||
});
|
||||
</script>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
</body>
|
||||