mirror of https://github.com/vapor/docs.git
Starting on docs v3
This commit is contained in:
parent
1b3c613cc1
commit
056c3e6f12
|
|
@ -0,0 +1,149 @@
|
|||
# Async
|
||||
|
||||
Async provides the fundament for asynchronous libraries. It consists of Futures and Streams.
|
||||
|
||||
## Promise and Future
|
||||
|
||||
When working with asynchronous APIs, one of the problems you'll face is not knowing when a variable is set.
|
||||
|
||||
When querying a database synchronously, the thread is blocked until a result has been received. At which point the result will be returned to you and the thread continues from where you left off querying the database.
|
||||
|
||||
```swift
|
||||
let user = try database.fetchUser(named: "Admin")
|
||||
|
||||
print(user.username)
|
||||
```
|
||||
|
||||
In the asynchronous world, you won't receive a result immediately. Instead, you'll receive a result in a callback.
|
||||
|
||||
```swift
|
||||
// Callback `found` will receive the user. If an error occurred, the `onError` callback will be called instead.
|
||||
try database.fetchUser(named: "Admin", found: { user in
|
||||
print(user.username)
|
||||
}, onError: { error in
|
||||
print(error)
|
||||
})
|
||||
```
|
||||
|
||||
You can imagine code becoming complex. Difficult to read and comprehend.
|
||||
|
||||
Promises and futures are two types that this library introduces to solve this.
|
||||
|
||||
### Creating a promise
|
||||
|
||||
Promises are important if you're implementing a function that returns a result in the future, such as the database shown above.
|
||||
|
||||
Promises need to be created without a result. They can then be completed with the expectation or an error at any point.
|
||||
|
||||
You can extract a `future` from the `promise` that you can hand to the API consumer.
|
||||
|
||||
```swift
|
||||
// the example `fetchUser` implementation
|
||||
func fetchUser(named name: String) -> Future<User> {
|
||||
// Creates a promise that can be fulfilled in the future
|
||||
let promise = Promise<User>()
|
||||
|
||||
// Run a query asynchronously, looking for the user
|
||||
asyncDatabaseQuery(where: "username" == name, onComplete: { databaseResult in
|
||||
do {
|
||||
// Initialize the user using the datbase result
|
||||
// This can throw an error if the result is empty or invalid
|
||||
let user = try User(decodingFrom: databaseResult)
|
||||
|
||||
// If initialization is successful, complete the promise.
|
||||
//
|
||||
// Completing the promise will notify the promise's associated future with this user
|
||||
promise.complete(user)
|
||||
} catch {
|
||||
// If initialization is successful, fail the promise.
|
||||
//
|
||||
// Failing the promise will notify the promise's associated future with an error
|
||||
promise.fail(error)
|
||||
}
|
||||
})
|
||||
|
||||
// After spawning the asynchronous operation, return the promise's associated future
|
||||
//
|
||||
// The future can then be used by the API consumer
|
||||
return promise.future
|
||||
}
|
||||
```
|
||||
|
||||
### On future completion
|
||||
|
||||
When a promise completes, you can chain the result/error into a closure:
|
||||
|
||||
```swift
|
||||
// The future provided by the above function will be used
|
||||
let future: Future<User> = fetchUser(named: "Admin")
|
||||
|
||||
// `.then`'s closure will be executed on success
|
||||
future.then { user in
|
||||
print(user.username)
|
||||
// `.catch` will catch any error on failure
|
||||
}.catch { error in
|
||||
print(error)
|
||||
}
|
||||
```
|
||||
|
||||
### Catching specific errors
|
||||
|
||||
Sometimes you only care for specific errors, for example, for logging.
|
||||
|
||||
```swift
|
||||
// The future provided by the above function will be used
|
||||
let future: Future<User> = fetchUser(named: "Admin")
|
||||
|
||||
// `.then`'s closure will be executed on success
|
||||
future.then { user in
|
||||
print(user.username)
|
||||
// This `.catch` will only catch `DatabaseError`s
|
||||
}.catch(DatabaseError.self) { databaseError in
|
||||
print(databaseError)
|
||||
// `.catch` will catch any error on failure, including `DatabaseError` types
|
||||
}.catch { error in
|
||||
print(error)
|
||||
}
|
||||
```
|
||||
|
||||
### Mapping results
|
||||
|
||||
Futures can be mapped to different results asynchronously.
|
||||
|
||||
```swift
|
||||
// The future provided by the above function will be used
|
||||
let future: Future<User> = fetchUser(named: "Admin")
|
||||
|
||||
// Maps the user to it's username
|
||||
let futureUsername: Future<String> = future.map { user in
|
||||
return user.username
|
||||
}
|
||||
|
||||
// Mapped futures can be mapped and chained, too
|
||||
futureUsername.then { username in
|
||||
print(username)
|
||||
}
|
||||
```
|
||||
|
||||
### For synchronous APIs
|
||||
|
||||
Sometimes, an API needs to be used synchronously in a synchronous envinronment.
|
||||
|
||||
Rather than using a synchronous API with all edge cases involved, we recommend using the `try future.sync()` function.
|
||||
|
||||
```swift
|
||||
// The future provided by the above function will be used
|
||||
let future: Future<User> = fetchUser(named: "Admin")
|
||||
|
||||
// This will either receive the user if the promise was completed or throw an error if the promise was failed.
|
||||
let user: User = try future.sync()
|
||||
```
|
||||
|
||||
This will wait for a result indefinitely, blocking the thread.
|
||||
|
||||
If you expect a result with a specified duration, say, 30 seconds:
|
||||
|
||||
```swift
|
||||
// This will also throw an error if the deadline wasn't met
|
||||
let user = try future.sync(deadline: .seconds(30))
|
||||
```
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
# Using Core
|
||||
|
||||
## With Vapor
|
||||
|
||||
This package is included with Vapor by default, just add:
|
||||
|
||||
```swift
|
||||
import Async
|
||||
```
|
||||
|
||||
## Without Vapor
|
||||
|
||||
Async is a powerful library for any Swift project. To include it in your package, add the following to your `Package.swift` file.
|
||||
|
||||
```swift
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "Project",
|
||||
dependencies: [
|
||||
...
|
||||
.package(url: "https://github.com/vapor/async.git", majorVersion: 2),
|
||||
],
|
||||
targets: [
|
||||
.target(name: "Project", dependencies: ["Async", ... ])
|
||||
]
|
||||
)
|
||||
```
|
||||
|
||||
Use `import Async` to access Async's APIs.
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
# Vapor Documentation
|
||||
|
||||
This is the documentation for Vapor, a Web Framework for Swift that works on iOS, macOS, and Ubuntu; and all of the packages that Vapor offers.
|
||||
|
||||
Vapor is the most used web framework for Swift. It provides a beautifully expressive and easy to use foundation for your next website or API.
|
||||
|
||||
|
||||
## Getting Started
|
||||
|
||||
If this is your first time using Vapor, head to the [Getting Started](getting-started/install-on-macos.md) section to install Swift and create your first app.
|
||||
|
||||
## Like Vapor?
|
||||
|
||||
Our small team works hard to make Vapor awesome (and free). Support the framework by starring Vapor on GitHub or donating $1 monthly--it helps us a lot. Thanks!
|
||||
|
||||
<a href="https://github.com/vapor/vapor" target="_blank">
|
||||
<img src="https://cloud.githubusercontent.com/assets/1342803/26243875/5490d02c-3c85-11e7-9667-d56eb97c2cf9.png" style="height:40px">
|
||||
</a>
|
||||
<a href="https://opencollective.com/vapor" target="_blank">
|
||||
<img src="https://cloud.githubusercontent.com/assets/1342803/26243876/54913ce2-3c85-11e7-9848-121adbe92198.png" style="margin-left: 10px; height:40px">
|
||||
</a>
|
||||
|
||||
|
||||
## Other Sources
|
||||
|
||||
Here are some other great places to find information about Vapor.
|
||||
|
||||
### API
|
||||
|
||||
Auto-generated API documentation is located at [api.vapor.codes](http://api.vapor.codes).
|
||||
|
||||
### Stack Overflow
|
||||
|
||||
View or ask questions related to Vapor on Stack Overflow using the [`vapor`](http://stackoverflow.com/questions/tagged/vapor) tag.
|
||||
|
||||
### GitHub
|
||||
|
||||
#### Source Code
|
||||
|
||||
To view the framework's source code and code documentation, visit [Vapor's GitHub](https://github.com/vapor/vapor).
|
||||
|
||||
#### Issues
|
||||
|
||||
To view open bug reports and feature requests, or to create one, visit the [issues](https://github.com/vapor/vapor/issues) tab on [Vapor's GitHub](https://github.com/vapor/vapor).
|
||||
|
||||
## Packages
|
||||
|
||||
Vapor is a modular framework built for a modular language. Code is split up into modules which are grouped to form packages. Packages can be added to your project by adding the package's Git url to your `Package.swift` file. Once a package is included, all of its modules will be available to `import`. You can read more about packages and modules in the Swift Package Manager [conceptual overview](https://swift.org/package-manager/).
|
||||
|
||||
Below is a list of packages and modules that come with or can be used by Vapor projects. Packages will have a link to their respective GitHub page.
|
||||
|
||||
### Core
|
||||
|
||||
Core packages are maintained by the Vapor team.
|
||||
|
||||
#### Included
|
||||
|
||||
The following packages are included with Vapor by default.
|
||||
|
||||
!!! tip
|
||||
These packages can also be used individually
|
||||
|
||||
- [Vapor](https://github.com/vapor/vapor): Swift's most used web framework.
|
||||
- Auth: User authentication and persistance.
|
||||
- Sessions: Secure, ephemeral cookie based data storage.
|
||||
- Cookies: HTTP cookies.
|
||||
- Routing: Advanced router with type-safe parameterization.
|
||||
- [Engine](https://github.com/vapor/engine): Core transport layers.
|
||||
- HTTP: HTTP client and server.
|
||||
- URI: URI parsing and serializing.
|
||||
- WebSockets: Full-duplex communication channels over a single TCP connection.
|
||||
- SMTP: Send email using Sendgrid and Gmail.
|
||||
- [Multipart](https://github.com/vapor/multipart): Fast, streaming, non-blocking multipart parser and serializer.
|
||||
- Multipart: Parses and serializes `multipart/mixed`.
|
||||
- FormData: Parses and serializes `multipart/form-data`.
|
||||
- [JSON](https://github.com/vapor/json): Conveniences for working with JSON in Swift.
|
||||
- [Console](https://github.com/vapor/console): Swift wrapper for console IO and commands.
|
||||
- [TLS](https://github.com/vapor/tls): Swift wrapper for CLibreSSL's new TLS.
|
||||
- [Crypto](https://github.com/vapor/crypto): Cryptography from LibreSSL and Swift.
|
||||
- Digests: Hashing with and without authentication.
|
||||
- Ciphers: Encryption and decryption
|
||||
- Random: Pseudo and cryptographically secure randomness.
|
||||
- BCrypt: Pure Swift implementation.
|
||||
- [Node](https://github.com/vapor/node): Data structure for easy type conversions.
|
||||
- [Polymorphic](https://github.com/vapor/polymorphic): Syntax for easily accessing values from common types like JSON.
|
||||
- [Path Indexable](https://github.com/vapor/path-indexable): A protocol for powerful subscript access of common types like JSON.
|
||||
- [Core](https://github.com/vapor/core): Core extensions, type-aliases, and functions that facilitate common tasks.
|
||||
- [Socks](https://github.com/vapor/socks): Swift C Socket API wrapper.
|
||||
- [Bits](https://github.com/vapor/bits): Low level byte manipulation helpers
|
||||
|
||||
#### Providers
|
||||
|
||||
These are officially supported packages for Vapor that are not included by default.
|
||||
|
||||
- [Fluent](https://github.com/vapor/fluent): Models, relationships, and querying for NoSQL and SQL databases.
|
||||
- [Fluent Provider](https://github.com/vapor/fluent-provider): Fluent provider for Vapor.
|
||||
- [MySQL](https://github.com/vapor/mysql): Robust MySQL interface for Swift.
|
||||
- [MySQL Driver](https://github.com/vapor/mysql-driver): MySQL driver for Fluent.
|
||||
- [MySQL Provider](https://github.com/vapor/mysql-provider): MySQL provider for Vapor.
|
||||
- [Leaf](https://github.com/vapor/leaf): An extensible templating language.
|
||||
- [Leaf Provider](https://github.com/vapor/leaf-provider): Leaf provider for Vapor.
|
||||
- [Redis](https://github.com/vapor/redbird): Pure-Swift Redis client implemented from the original protocol spec.
|
||||
- [Redis Provider](https://github.com/vapor/redis-provider): Redis cache provider for Vapor.
|
||||
- [JWT](https://github.com/vapor/jwt): JSON Web Tokens in Swift.
|
||||
- [JWT Provider](https://github.com/vapor/jwt-provider): JWT conveniences for Vapor.
|
||||
|
||||
### Community
|
||||
|
||||
These are packages maintained by community members that work great with Vapor.
|
||||
|
||||
- [PostgreSQL](https://github.com/vapor/postgresql): Robust PostgreSQL interface for Swift.
|
||||
- [PostgreSQL Driver](https://github.com/vapor/postgresql-driver): PostgreSQL driver for Fluent.
|
||||
- [PostgreSQL Provider](https://github.com/vapor/postgresql-provider): PostgreSQL provider for Vapor.
|
||||
- [MongoKitten](https://github.com/OpenKitten/MongoKitten): Native MongoDB driver for Swift, written in Swift
|
||||
- [Mongo Driver](https://github.com/vapor/mongo-driver): MongoKitten driver for Fluent.
|
||||
- [Mongo Provider](https://github.com/vapor/mongo-provider): MongoKitten provider for Vapor.
|
||||
- [Kitura Provider](https://github.com/vapor/kitura-provider): Use IBM's Kitura HTTP server in Vapor.
|
||||
- [SwiftyBeaver](https://github.com/vapor-community/swiftybeaver-provider): Adds the powerful logging of SwiftyBeaver to Vapor.
|
||||
- [APNS](https://github.com/matthijs2704/vapor-apns): Simple APNS Library for Vapor (Swift).
|
||||
- [VaporFCM](https://github.com/mdab121/vapor-fcm): Simple FCM (iOS + Android Push Notifications) library built for Vapor in Swift.
|
||||
- [VaporS3Signer](https://github.com/JustinM1/VaporS3Signer): Generate V4 Auth Header/Pre-Signed URL for AWS S3 REST API
|
||||
- [Flock](https://github.com/jakeheis/Flock): Automated deployment of Swift projects to servers
|
||||
- [VaporFlock](https://github.com/jakeheis/VaporFlock): Use Flock to deploy Vapor applications
|
||||
- [VaporForms](https://github.com/bygri/vapor-forms): Brings simple, dynamic and re-usable web form handling to Vapor.
|
||||
- [Jobs](https://github.com/BrettRToomey/Jobs): A minimalistic job/background-task system for Swift.
|
||||
- [Heimdall](https://github.com/himani93/heimdall): An easy to use HTTP request logger.
|
||||
- [SteamPress](https://github.com/brokenhandsio/SteamPress): A blogging engine for Vapor.
|
||||
- [Vapor Security Headers](https://github.com/brokenhandsio/VaporSecurityHeaders): Add common security headers to your Vapor Application.
|
||||
- [MarkdownProvider](https://github.com/vapor-community/markdown-provider) - Easily use Markdown from Leaf.
|
||||
- [Vapor OAuth](https://github.com/brokenhandsio/vapor-oauth) - An OAuth2 Provider library for Vapor
|
||||
|
||||
### Providers
|
||||
|
||||
Vapor providers are a convenient way to add functionality to your Vapor projects. For a full list of providers, check out the [`vapor-provider`](https://github.com/search?utf8=✓&q=topic%3Avapor-provider&type=Repositories) tag on GitHub.
|
||||
|
||||
## Authors
|
||||
|
||||
[Tanner Nelson](mailto:tanner@vapor.codes), [Logan Wright](mailto:logan@vapor.codes), and the hundreds of members of Vapor.
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
site_name: 'Vapor Docs'
|
||||
copyright: 'Copyright © 2017 Qutheory, LLC'
|
||||
|
||||
pages:
|
||||
- Overview: 'index.md'
|
||||
|
||||
markdown_extensions:
|
||||
- admonition
|
||||
- codehilite(guess_lang=false)
|
||||
- footnotes
|
||||
- meta
|
||||
- toc(permalink=true)
|
||||
|
||||
theme: 'material'
|
||||
theme_dir: 'vapor-material'
|
||||
repo_url: https://github.com/vapor/documentation
|
||||
|
||||
extra_css:
|
||||
- 'stylesheets/extra.css'
|
||||
edit_uri: edit/master/2.0/docs/
|
||||
extra:
|
||||
logo: 'images/droplet-white.svg'
|
||||
social:
|
||||
- type: 'twitter'
|
||||
link: 'https://twitter.com/@codevapor'
|
||||
- type: 'slack'
|
||||
link: 'http://vapor.team/'
|
||||
font:
|
||||
text: 'Roboto Slab'
|
||||
code: 'Source Code Pro'
|
||||
|
||||
google_analytics:
|
||||
- 'UA-76177358-4'
|
||||
- 'auto'
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
{% extends "base.html" %}
|
||||
{% block content %}
|
||||
<h1>404 - Not found</h1>
|
||||
{% endblock %}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.0 KiB |
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="352" height="448" viewBox="0 0 352 448" id="bitbucket"><path fill="currentColor" d="M203.75 214.75q2 15.75-12.625 25.25t-27.875 1.5q-9.75-4.25-13.375-14.5t-.125-20.5 13-14.5q9-4.5 18.125-3t16 8.875 6.875 16.875zm27.75-5.25q-3.5-26.75-28.25-41T154 165.25q-15.75 7-25.125 22.125t-8.625 32.375q1 22.75 19.375 38.75t41.375 14q22.75-2 38-21t12.5-42zM291.25 74q-5-6.75-14-11.125t-14.5-5.5T245 54.25q-72.75-11.75-141.5.5-10.75 1.75-16.5 3t-13.75 5.5T60.75 74q7.5 7 19 11.375t18.375 5.5T120 93.75Q177 101 232 94q15.75-2 22.375-3t18.125-5.375T291.25 74zm14.25 258.75q-2 6.5-3.875 19.125t-3.5 21-7.125 17.5-14.5 14.125q-21.5 12-47.375 17.875t-50.5 5.5-50.375-4.625q-11.5-2-20.375-4.5T88.75 412 70.5 401.125t-13-15.375q-6.25-24-14.25-73l1.5-4 4.5-2.25q55.75 37 126.625 37t126.875-37q5.25 1.5 6 5.75t-1.25 11.25-2 9.25zM350.75 92.5q-6.5 41.75-27.75 163.75-1.25 7.5-6.75 14t-10.875 10T291.75 288q-63 31.5-152.5 22-62-6.75-98.5-34.75-3.75-3-6.375-6.625t-4.25-8.75-2.25-8.5-1.5-9.875T25 232.75q-2.25-12.5-6.625-37.5t-7-40.375T5.5 118 0 78.5Q.75 72 4.375 66.375T12.25 57t11.25-7.5T35 43.875t12-4.625q31.25-11.5 78.25-16 94.75-9.25 169 12.5Q333 47.25 348 66.25q4 5 4.125 12.75t-1.375 13.5z"/></svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="416" height="448" viewBox="0 0 416 448" id="github"><path fill="currentColor" d="M160 304q0 10-3.125 20.5t-10.75 19T128 352t-18.125-8.5-10.75-19T96 304t3.125-20.5 10.75-19T128 256t18.125 8.5 10.75 19T160 304zm160 0q0 10-3.125 20.5t-10.75 19T288 352t-18.125-8.5-10.75-19T256 304t3.125-20.5 10.75-19T288 256t18.125 8.5 10.75 19T320 304zm40 0q0-30-17.25-51T296 232q-10.25 0-48.75 5.25Q229.5 240 208 240t-39.25-2.75Q130.75 232 120 232q-29.5 0-46.75 21T56 304q0 22 8 38.375t20.25 25.75 30.5 15 35 7.375 37.25 1.75h42q20.5 0 37.25-1.75t35-7.375 30.5-15 20.25-25.75T360 304zm56-44q0 51.75-15.25 82.75-9.5 19.25-26.375 33.25t-35.25 21.5-42.5 11.875-42.875 5.5T212 416q-19.5 0-35.5-.75t-36.875-3.125-38.125-7.5-34.25-12.875T37 371.5t-21.5-28.75Q0 312 0 260q0-59.25 34-99-6.75-20.5-6.75-42.5 0-29 12.75-54.5 27 0 47.5 9.875t47.25 30.875Q171.5 96 212 96q37 0 70 8 26.25-20.5 46.75-30.25T376 64q12.75 25.5 12.75 54.5 0 21.75-6.75 42 34 40 34 99.5z"/></svg>
|
||||
|
After Width: | Height: | Size: 991 B |
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="500" height="500" viewBox="0 0 500 500" id="gitlab"><path fill="currentColor" d="M93.667 473.347l90.684-279.097H2.983l90.684 279.097z" transform="translate(156.198 1.16)"/><path fill="currentColor" d="M221.333 473.345L130.649 194.25H3.557l217.776 279.095z" transform="translate(28.531 1.16)" opacity=".7"/><path fill="currentColor" d="M32 195.155L4.441 279.97a18.773 18.773 0 0 0 6.821 20.99l238.514 173.29L32 195.155z" transform="translate(.089 .256)" opacity=".5"/><path fill="currentColor" d="M2.667-84.844h127.092L75.14-252.942c-2.811-8.649-15.047-8.649-17.856 0L2.667-84.844z" transform="translate(29.422 280.256)"/><path fill="currentColor" d="M2.667 473.345L93.351 194.25h127.092L2.667 473.345z" transform="translate(247.198 1.16)" opacity=".7"/><path fill="currentColor" d="M221.334 195.155l27.559 84.815a18.772 18.772 0 0 1-6.821 20.99L3.557 474.25l217.777-279.095z" transform="translate(246.307 .256)" opacity=".5"/><path fill="currentColor" d="M130.667-84.844H3.575l54.618-168.098c2.811-8.649 15.047-8.649 17.856 0l54.618 168.098z" transform="translate(336.974 280.256)"/></svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,158 @@
|
|||
{% import "partials/language.html" as lang %}
|
||||
<!DOCTYPE html>
|
||||
<html class="no-js">
|
||||
<head>
|
||||
{% block site_meta %}
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
{% if config.site_description %}
|
||||
<meta name="description" content="{{ config.site_description }}">
|
||||
{% endif %}
|
||||
{% if page.canonical_url %}
|
||||
<link rel="canonical" href="{{ page.canonical_url }}">
|
||||
{% endif %}
|
||||
{% if config.site_author %}
|
||||
<meta name="author" content="{{ config.site_author }}">
|
||||
{% endif %}
|
||||
{% if config.site_favicon %}
|
||||
<link rel="shortcut icon" href="{{ base_url }}/{{ config.site_favicon }}">
|
||||
{% else %}
|
||||
<link rel="shortcut icon" href="{{ base_url }}/assets/images/favicon.png">
|
||||
{% endif %}
|
||||
<meta name="generator" content="mkdocs-{{ mkdocs_version }}, mkdocs-material-1.1.1">
|
||||
{% endblock %}
|
||||
{% block htmltitle %}
|
||||
{% if page.title and not page.is_homepage %}
|
||||
<title>{{ page.title }} - {{ config.site_name }}</title>
|
||||
{% else %}
|
||||
<title>{{ config.site_name }}</title>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% block libs %}
|
||||
<script src="{{ base_url }}/assets/javascripts/modernizr-56ade86843.js"></script>
|
||||
{% endblock %}
|
||||
{% block styles %}
|
||||
<link rel="stylesheet" href="{{ base_url }}/assets/stylesheets/application-e5b48ab351.css">
|
||||
{% if config.extra.palette %}
|
||||
<link rel="stylesheet" href="{{ base_url }}/assets/stylesheets/application-892b79c5c5.palette.css">
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% block fonts %}
|
||||
{% if config.extra.font != "none" %}
|
||||
{% set text = config.extra.get("font", {}).text | default("Roboto") %}
|
||||
{% set code = config.extra.get("font", {}).code
|
||||
| default("Roboto Mono") %}
|
||||
{% set font = text + ':300,400,400i,700|' + code | replace(' ', '+') %}
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family={{ font }}">
|
||||
<style>body,input{font-family:"{{ text }}","Helvetica Neue",Helvetica,Arial,sans-serif}code,kbd,pre{font-family:"{{ code }}","Courier New",Courier,monospace}</style>
|
||||
{% endif %}
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
|
||||
{% endblock %}
|
||||
{% for path in extra_css %}
|
||||
<link rel="stylesheet" href="{{ path }}">
|
||||
{% endfor %}
|
||||
{% block extrahead %}{% endblock %}
|
||||
</head>
|
||||
{% set palette = config.extra.get("palette", {}) %}
|
||||
{% set primary = palette.primary | replace(" ", "-") | lower %}
|
||||
{% set accent = palette.accent | replace(" ", "-") | lower %}
|
||||
{% if primary or accent %}
|
||||
<body data-md-color-primary="{{ primary }}" data-md-color-accent="{{ accent }}">
|
||||
{% else %}
|
||||
<body>
|
||||
{% endif %}
|
||||
<svg class="md-svg">
|
||||
<defs>
|
||||
{% set platform = config.extra.repo_icon or config.repo_url %}
|
||||
{% if "github" in platform %}
|
||||
{% include "assets/images/icons/github-1da075986e.svg" %}
|
||||
{% elif "gitlab" in platform %}
|
||||
{% include "assets/images/icons/gitlab-5ad3f9f9e5.svg" %}
|
||||
{% elif "bitbucket" in platform %}
|
||||
{% include "assets/images/icons/bitbucket-670608a71a.svg" %}
|
||||
{% endif %}
|
||||
</defs>
|
||||
</svg>
|
||||
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="drawer">
|
||||
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="search">
|
||||
<label class="md-overlay" data-md-component="overlay" for="drawer"></label>
|
||||
{% block header %}
|
||||
{% include "partials/header.html" %}
|
||||
{% endblock %}
|
||||
<div class="md-container">
|
||||
{% set feature = config.extra.get("feature", {}) %}
|
||||
{% if feature.tabs %}
|
||||
{% include "partials/tabs.html" %}
|
||||
{% endif %}
|
||||
<main class="md-main">
|
||||
<div class="md-main__inner md-grid" data-md-component="container">
|
||||
{% block site_nav %}
|
||||
{% if nav %}
|
||||
<div class="md-sidebar md-sidebar--primary" data-md-component="navigation">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
{% include "partials/nav.html" %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if page.toc %}
|
||||
<div class="md-sidebar md-sidebar--secondary" data-md-component="toc">
|
||||
<div class="md-sidebar__scrollwrap">
|
||||
<div class="md-sidebar__inner">
|
||||
{% include "partials/toc.html" %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
<div class="md-content">
|
||||
<article class="md-content__inner md-typeset">
|
||||
{% if config.edit_uri %}
|
||||
<a href="{{ page.edit_url }}" title="{{ lang.t('edit.link.title') }}" class="md-icon md-content__edit">edit</a>
|
||||
{% endif %}
|
||||
{% block content %}
|
||||
{% if not "\x3ch1" in page.content %}
|
||||
<h1>{{ page.title | default(config.site_name, true)}}</h1>
|
||||
{% endif %}
|
||||
{{ page.content }}
|
||||
{% endblock %}
|
||||
{% if config.extra.disqus and not page.is_homepage %}
|
||||
<h2>{{ lang.t('comments') }}</h2>
|
||||
<div id="disqus_thread"></div>
|
||||
<script>
|
||||
var disqus_config = function () {
|
||||
this.page.url = "{{ page.canonical_url }}";
|
||||
this.page.identifier =
|
||||
"{{ page.canonical_url | replace(config.site_url, "") }}";
|
||||
};
|
||||
(function() {
|
||||
var d = document, s = d.createElement("script");
|
||||
s.src = "//{{ config.extra.disqus }}.disqus.com/embed.js";
|
||||
s.setAttribute("data-timestamp", +new Date());
|
||||
(d.head || d.body).appendChild(s);
|
||||
})();
|
||||
</script>
|
||||
{% endif %}
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
{% block footer %}
|
||||
{% include "partials/footer.html" %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
{% block scripts %}
|
||||
<script src="{{ base_url }}/assets/javascripts/application-f6cd941c96.js"></script>
|
||||
<script>app.initialize({url:{base:"{{ base_url }}"}})</script>
|
||||
{% for path in extra_javascript %}
|
||||
<script src="{{ path }}"></script>
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
{% block analytics %}
|
||||
{% if config.google_analytics %}
|
||||
<script>!function(e,t,n,a,o,c,i){e.GoogleAnalyticsObject=o,e[o]=e[o]||function(){(e[o].q=e[o].q||[]).push(arguments)},e[o].l=1*new Date,c=t.createElement(n),i=t.getElementsByTagName(n)[0],c.async=1,c.src=a,i.parentNode.insertBefore(c,i)}(window,document,"script","https://www.google-analytics.com/analytics.js","ga"),ga("create","{{ config.google_analytics[0] }}","{{ config.google_analytics[1] }}"),ga("set","anonymizeIp",!0),ga("send","pageview");var links=document.getElementsByTagName("a");Array.prototype.map.call(links,function(e){e.host!=document.location.host&&e.addEventListener("click",function(){var t=e.getAttribute("data-md-action")||"follow";ga("send","event","outbound",t,e.href)})}),document.forms.search.query.addEventListener("blur",function(){if(this.value){var e=document.location.pathname;ga("send","pageview",e+"?q="+this.value)}})</script>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1 @@
|
|||
{% extends "base.html" %}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
{% import "partials/language.html" as lang %}
|
||||
<footer class="md-footer">
|
||||
{% if page.previous_page or page.next_page %}
|
||||
<div class="md-footer-nav">
|
||||
<nav class="md-footer-nav__inner md-grid">
|
||||
{% if page.previous_page %}
|
||||
<a href="{{ page.previous_page.url }}" title="{{ page.previous_page.title }}" class="md-flex md-footer-nav__link md-footer-nav__link--prev" rel="prev">
|
||||
<div class="md-flex__cell md-flex__cell--shrink">
|
||||
<i class="md-icon md-icon--arrow-back md-footer-nav__button"></i>
|
||||
</div>
|
||||
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title">
|
||||
<span class="md-flex__ellipsis">
|
||||
<span class="md-footer-nav__direction">
|
||||
{{ lang.t('footer.previous') }}
|
||||
</span>
|
||||
{{ page.previous_page.title }}
|
||||
</span>
|
||||
</div>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if page.next_page %}
|
||||
<a href="{{ page.next_page.url }}" title="{{ page.next_page.title }}" class="md-flex md-footer-nav__link md-footer-nav__link--next" rel="next">
|
||||
<div class="md-flex__cell md-flex__cell--stretch md-footer-nav__title">
|
||||
<span class="md-flex__ellipsis">
|
||||
<span class="md-footer-nav__direction">
|
||||
{{ lang.t('footer.next') }}
|
||||
</span>
|
||||
{{ page.next_page.title }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="md-flex__cell md-flex__cell--shrink">
|
||||
<i class="md-icon md-icon--arrow-forward md-footer-nav__button"></i>
|
||||
</div>
|
||||
</a>
|
||||
{% endif %}
|
||||
</nav>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="md-footer-meta md-typeset">
|
||||
<div class="md-footer-meta__inner md-grid">
|
||||
<div class="md-footer-copyright">
|
||||
{% if config.copyright %}
|
||||
<div class="md-footer-copyright__highlight">
|
||||
{{ config.copyright }}
|
||||
</div>
|
||||
{% endif %}
|
||||
powered by
|
||||
<a href="http://www.mkdocs.org" title="MkDocs">MkDocs</a>
|
||||
and
|
||||
<a href="http://squidfunk.github.io/mkdocs-material/" title="Material for MkDocs">
|
||||
Material for MkDocs</a>
|
||||
</div>
|
||||
{% block social %}
|
||||
{% include "partials/social.html" %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
<header class="md-header">
|
||||
<nav class="md-header-nav md-grid">
|
||||
<div class="md-flex">
|
||||
<div class="md-flex__cell md-flex__cell--shrink">
|
||||
{% if config.extra.logo %}
|
||||
<a href="{{ nav.homepage.url }}" title="{{ config.site_name }}" class="md-logo md-header-nav__button">
|
||||
<img src="{{ base_url }}/{{ config.extra.logo }}" width="24" height="24">
|
||||
</a>
|
||||
{% else %}
|
||||
<a href="{{ nav.homepage.url }}" title="{{ config.site_name }}" class="md-icon md-icon--home md-header-nav__button">
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="md-flex__cell md-flex__cell--shrink">
|
||||
<label class="md-icon md-icon--menu md-header-nav__button" for="drawer"></label>
|
||||
</div>
|
||||
<div class="md-flex__cell md-flex__cell--stretch">
|
||||
<span class="md-flex__ellipsis md-header-nav__title">
|
||||
{% block site_name %}
|
||||
{% if page %}
|
||||
{% for parent in page.ancestors %}
|
||||
<span class="md-header-nav__parent">
|
||||
{{ parent.title }}
|
||||
</span>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{{ page.title | default(config.site_name, true) }}
|
||||
{% endblock %}
|
||||
</span>
|
||||
</div>
|
||||
<div class="md-flex__cell md-flex__cell--shrink">
|
||||
{% block search_box %}
|
||||
<label class="md-icon md-icon--search md-header-nav__button" for="search"></label>
|
||||
{% include "partials/search.html" %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
<div class="md-flex__cell md-flex__cell--shrink">
|
||||
<div class="md-header-nav__source">
|
||||
{% if config.repo_url %}
|
||||
{% include "partials/source.html" %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{% macro t(key) %}{{ {
|
||||
"edit.link.title": "Edit this page",
|
||||
"comments": "Comments",
|
||||
"footer.previous": "Previous",
|
||||
"footer.next": "Next",
|
||||
"search.placeholder": "Search",
|
||||
"source.link.title": "Go to repository",
|
||||
"toc.title": "Table of contents"
|
||||
}[key] }}{% endmacro %}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
{% set class = "md-nav__item" %}
|
||||
{% if nav_item.active %}
|
||||
{% set class = "md-nav__item md-nav__item--active" %}
|
||||
{% endif %}
|
||||
{% if nav_item.children %}
|
||||
<li class="{{ class }} md-nav__item--nested">
|
||||
{% if nav_item.active %}
|
||||
<input class="md-toggle md-nav__toggle" data-md-toggle="{{ path }}" type="checkbox" id="{{ path }}" checked>
|
||||
{% else %}
|
||||
<input class="md-toggle md-nav__toggle" data-md-toggle="{{ path }}" type="checkbox" id="{{ path }}">
|
||||
{% endif %}
|
||||
<label class="md-nav__link" for="{{ path }}">
|
||||
{{ nav_item.title }}
|
||||
</label>
|
||||
<nav class="md-nav" data-md-component="collapsible" data-md-level="{{ level }}">
|
||||
<label class="md-nav__title" for="{{ path }}">
|
||||
{{ nav_item.title }}
|
||||
</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix>
|
||||
{% set base = path %}
|
||||
{% for nav_item in nav_item.children %}
|
||||
{% set path = base + "-" + loop.index | string %}
|
||||
{% set level = level + 1 %}
|
||||
{% include "partials/nav-item.html" %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</nav>
|
||||
</li>
|
||||
{% elif nav_item == page %}
|
||||
<li class="{{ class }}">
|
||||
{% set toc_ = page.toc %}
|
||||
<input class="md-toggle md-nav__toggle" data-md-toggle="toc" type="checkbox" id="toc">
|
||||
{% if toc_ | first is defined %}
|
||||
{% set toc_ = (toc_ | first).children %}
|
||||
{% endif %}
|
||||
{% if toc_ | first is defined %}
|
||||
<label class="md-nav__link md-nav__link--active" for="toc">
|
||||
{{ nav_item.title }}
|
||||
</label>
|
||||
{% endif %}
|
||||
<a href="{{ nav_item.url }}" title="{{ nav_item.title }}" class="md-nav__link md-nav__link--active">
|
||||
{{ nav_item.title }}
|
||||
</a>
|
||||
{% if toc_ | first is defined %}
|
||||
{% include "partials/toc.html" %}
|
||||
{% endif %}
|
||||
</li>
|
||||
{% else %}
|
||||
<li class="{{ class }}">
|
||||
<a href="{{ nav_item.url }}" title="{{ nav_item.title }}" class="md-nav__link">
|
||||
{{ nav_item.title }}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
<nav class="md-nav md-nav--primary" data-md-level="0">
|
||||
<label class="md-nav__title md-nav__title--site" for="drawer">
|
||||
{% if config.extra.logo %}
|
||||
<i class="md-logo md-nav__button">
|
||||
<img src="{{ base_url }}/{{ config.extra.logo }}">
|
||||
</i>
|
||||
{% else %}
|
||||
<i class="md-icon md-icon--home md-nav__button"></i>
|
||||
{% endif %}
|
||||
{{ config.site_name }}
|
||||
</label>
|
||||
{% if config.repo_url %}
|
||||
<div class="md-nav__source">
|
||||
{% include "partials/source.html" %}
|
||||
</div>
|
||||
{% endif %}
|
||||
<ul class="md-nav__list" data-md-scrollfix>
|
||||
{% for nav_item in nav %}
|
||||
{% set path = "nav-" + loop.index | string %}
|
||||
{% set level = 1 %}
|
||||
{% include "partials/nav-item.html" %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</nav>
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
{% import "partials/language.html" as lang %}
|
||||
<div class="md-search" data-md-component="search">
|
||||
<div class="md-search__overlay"></div>
|
||||
<div class="md-search__inner">
|
||||
<form class="md-search__form" name="search">
|
||||
<input type="text" class="md-search__input" name="query" placeholder="{{ lang.t('search.placeholder') }}" accesskey="s" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="query">
|
||||
<label class="md-icon md-search__icon" for="search"></label>
|
||||
</form>
|
||||
<div class="md-search__output">
|
||||
<div class="md-search__scrollwrap" data-md-scrollfix>
|
||||
<div class="md-search-result" data-md-component="result"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
{% if config.extra.social %}
|
||||
<div class="md-footer-social">
|
||||
{% set path = "ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" %}
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/{{ path }}">
|
||||
{% for social in config.extra.social %}
|
||||
<a href="{{ social.link }}" class="md-footer-social__link fa fa-{{ social.type }}"></a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
{% import "partials/language.html" as lang %}
|
||||
{% set platform = config.extra.repo_icon or config.repo_url %}
|
||||
{% if "github" in platform %}
|
||||
{% set repo_type = "github" %}
|
||||
{% elif "gitlab" in platform %}
|
||||
{% set repo_type = "gitlab" %}
|
||||
{% elif "bitbucket" in platform %}
|
||||
{% set repo_type = "bitbucket" %}
|
||||
{% else %}
|
||||
{% set repo_type = "" %}
|
||||
{% endif %}
|
||||
{% block repo %}
|
||||
<a href="{{ config.repo_url }}" title="{{ lang.t('source.link.title') }}" class="md-source" data-md-source="{{ repo_type }}">
|
||||
{% if repo_type %}
|
||||
<div class="md-source__icon">
|
||||
<svg viewBox="0 0 24 24" width="24" height="24">
|
||||
<use xlink:href="#{{ repo_type }}" width="24" height="24"></use>
|
||||
</svg>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="md-source__repository">
|
||||
{{ config.repo_name }}
|
||||
</div>
|
||||
</a>
|
||||
{% endblock %}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
{% if nav_item.is_homepage %}
|
||||
<li class="md-tabs__item">
|
||||
{% if not page.ancestors | length and nav | selectattr("url", page.url) %}
|
||||
<a href="{{ nav_item.url }}" title="{{ nav_item.title }}" class="md-tabs__link md-tabs__link--active">
|
||||
{{ nav_item.title }}
|
||||
</a>
|
||||
{% else %}
|
||||
<a href="{{ nav_item.url }}" title="{{ nav_item.title }}" class="md-tabs__link">
|
||||
{{ nav_item.title }}
|
||||
</a>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% elif nav_item.children and nav_item.children | length > 0 %}
|
||||
<li class="md-tabs__item">
|
||||
{% if nav_item.active %}
|
||||
<a href="{{ (nav_item.children | first).url }}" title="{{ nav_item.title }}" class="md-tabs__link md-tabs__link--active">
|
||||
{{ nav_item.title }}
|
||||
</a>
|
||||
{% else %}
|
||||
<a href="{{ (nav_item.children | first).url }}" title="{{ nav_item.title }}" class="md-tabs__link">
|
||||
{{ nav_item.title }}
|
||||
</a>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% endif %}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
{% set class = "md-tabs" %}
|
||||
{% if page.ancestors | length > 0 %}
|
||||
{% set class = "md-tabs md-tabs--active" %}
|
||||
{% endif %}
|
||||
<nav class="{{ class }}" data-md-component="tabs">
|
||||
<div class="md-tabs__inner md-grid">
|
||||
<ul class="md-tabs__list">
|
||||
{% for nav_item in nav %}
|
||||
{% include "partials/tabs-item.html" %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<li class="md-nav__item">
|
||||
<a href="{{ toc_item.url }}" title="{{ toc_item.title }}" class="md-nav__link">
|
||||
{{ toc_item.title }}
|
||||
</a>
|
||||
{% if toc_item.children %}
|
||||
<nav class="md-nav">
|
||||
<ul class="md-nav__list">
|
||||
{% for toc_item in toc_item.children %}
|
||||
{% include "partials/toc-item.html" %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</nav>
|
||||
{% endif %}
|
||||
</li>
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
{% import "partials/language.html" as lang %}
|
||||
<nav class="md-nav md-nav--secondary">
|
||||
{% set toc_ = page.toc %}
|
||||
{% if toc_ | first is defined and "\x3ch1 id=" in page.content %}
|
||||
{% set toc_ = (toc_ | first).children %}
|
||||
{% endif %}
|
||||
{% if toc_ | first is defined %}
|
||||
<label class="md-nav__title" for="toc">{{ lang.t('toc.title') }}</label>
|
||||
<ul class="md-nav__list" data-md-scrollfix>
|
||||
{% for toc_item in toc_ %}
|
||||
{% include "partials/toc-item.html" %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</nav>
|
||||
Loading…
Reference in New Issue