mirror of https://github.com/vapor/docs.git
595 lines
25 KiB
HTML
595 lines
25 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
|
|
<title>Vapor Documentation</title>
|
|
|
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Code+Pro">
|
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Quicksand:400,700,300">
|
|
<link rel="stylesheet" href="/1.5/styles/vapor-code.css">
|
|
<link rel="stylesheet" href="/1.5/styles/main.css">
|
|
</head>
|
|
<body>
|
|
|
|
<header>
|
|
<a class="logo" href="/1.5/">
|
|
<img src="/1.5/images/droplet.svg" alt="Vapor">
|
|
<h1>Vapor <em>Docs</em></h1>
|
|
</a>
|
|
<ul>
|
|
<li>
|
|
<a href="http://vapor.codes">Home</a>
|
|
</li>
|
|
<li>
|
|
<a href="http://example.vapor.codes">Example</a>
|
|
</li>
|
|
<li>
|
|
<a href="https://github.com/vapor/vapor">GitHub</a>
|
|
</li>
|
|
<li>
|
|
<a href="https://twitter.com/@codevapor">Twitter</a>
|
|
</li>
|
|
<li>
|
|
<a href="http://vapor.team">Slack</a>
|
|
</li>
|
|
</ul>
|
|
</header>
|
|
|
|
|
|
|
|
<nav>
|
|
<a href="#" class="toggle show">☰</a>
|
|
<a href="#" class="toggle close">×</a>
|
|
|
|
<div class="scroll">
|
|
<section>
|
|
<h3>Getting Started</h3>
|
|
<ul>
|
|
<li class="">
|
|
<a href="/1.5/getting-started/install-swift-3-macos.html">
|
|
Install Swift 3: macOS
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/getting-started/install-swift-3-ubuntu.html">
|
|
Install Swift 3: Ubuntu
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/getting-started/install-toolbox.html">
|
|
Install Toolbox
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/getting-started/hello-world.html">
|
|
Hello, World
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/getting-started/manual.html">
|
|
Manual
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/getting-started/xcode.html">
|
|
Xcode
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</section>
|
|
<section>
|
|
<h3>Guide</h3>
|
|
<ul>
|
|
<li class="">
|
|
<a href="/1.5/guide/droplet.html">
|
|
Droplet
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/guide/folder-structure.html">
|
|
Folder Structure
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/guide/json.html">
|
|
JSON
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/guide/config.html">
|
|
Config
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/guide/views.html">
|
|
Views
|
|
</a>
|
|
</li>
|
|
<li class="active">
|
|
<a href="/1.5/guide/leaf.html">
|
|
Leaf
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/guide/controllers.html">
|
|
Controllers
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/guide/middleware.html">
|
|
Middleware
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/guide/validation.html">
|
|
Validation
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/guide/provider.html">
|
|
Provider
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/guide/sessions.html">
|
|
Sessions
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/guide/hash.html">
|
|
Hash
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/guide/commands.html">
|
|
Commands
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</section>
|
|
<section>
|
|
<h3>Routing</h3>
|
|
<ul>
|
|
<li class="">
|
|
<a href="/1.5/routing/basic.html">
|
|
Basic
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/routing/parameters.html">
|
|
Route Parameters
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/routing/query-parameters.html">
|
|
Query Parameters
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/routing/group.html">
|
|
Group
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/routing/collection.html">
|
|
Collection
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</section>
|
|
<section>
|
|
<h3>Fluent</h3>
|
|
<ul>
|
|
<li class="">
|
|
<a href="/1.5/fluent/driver.html">
|
|
Driver
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/fluent/model.html">
|
|
Model
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/fluent/query.html">
|
|
Query
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/fluent/relation.html">
|
|
Relation
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</section>
|
|
<section>
|
|
<h3>Auth</h3>
|
|
<ul>
|
|
<li class="">
|
|
<a href="/1.5/auth/user.html">
|
|
User
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/auth/middleware.html">
|
|
Middleware
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/auth/request.html">
|
|
Request
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/auth/protect.html">
|
|
Protect
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</section>
|
|
<section>
|
|
<h3>HTTP</h3>
|
|
<ul>
|
|
<li class="">
|
|
<a href="/1.5/http/request.html">
|
|
Request
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/http/response.html">
|
|
Response
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/http/body.html">
|
|
Body
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/http/response-representable.html">
|
|
ResponseRepresentable
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/http/responder.html">
|
|
Responder
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/http/client.html">
|
|
Client
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/http/server.html">
|
|
Server
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/http/cors.html">
|
|
CORS
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</section>
|
|
<section>
|
|
<h3>WebSockets</h3>
|
|
<ul>
|
|
<li class="">
|
|
<a href="/1.5/websockets/droplet.html">
|
|
Droplet
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/websockets/custom.html">
|
|
Custom
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</section>
|
|
<section>
|
|
<h3>Testing</h3>
|
|
<ul>
|
|
<li class="">
|
|
<a href="/1.5/testing/modules.html">
|
|
Modules
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/testing/basic.html">
|
|
Basic
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</section>
|
|
<section>
|
|
<h3>Deploy</h3>
|
|
<ul>
|
|
<li class="">
|
|
<a href="/1.5/deploy/nginx.html">
|
|
Nginx
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/deploy/supervisor.html">
|
|
Supervisor
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</section>
|
|
<section>
|
|
<h3>Version (1.5)</h3>
|
|
<ul>
|
|
<li class="">
|
|
<a href="/1.5/switch/1_5.html">
|
|
1.5
|
|
</a>
|
|
</li>
|
|
<li class="">
|
|
<a href="/1.5/switch/2_0.html">
|
|
2.0
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</section>
|
|
</div>
|
|
</nav>
|
|
|
|
<main>
|
|
<a href="https://github.com/vapor/documentation/blob/master/CONTRIBUTING.md" class="edit">✎ Edit on GitHub</a>
|
|
<h1 id="leaf">Leaf</h1>
|
|
<p>Welcome to Leaf. Leaf's goal is to be a simple templating language that can make generating views easier. There's a lot of great templating languages, use what's best for you, maybe that's Leaf! The goals of Leaf are as follows:</p>
|
|
<ul>
|
|
<li>Small set of strictly enforced rules</li>
|
|
<li>Consistency</li>
|
|
<li>Parser first mentality</li>
|
|
<li>Extensibility</li>
|
|
</ul>
|
|
<h2 id="syntax">Syntax</h2>
|
|
<h3 id="structure">Structure</h3>
|
|
<p>Leaf Tags are made up of 4 Elements:</p>
|
|
<ul>
|
|
<li>Token: <code>#</code> is the Token</li>
|
|
<li>Name: A <code>string</code> that identifies the tag</li>
|
|
<li>Parameter List: <code>()</code> May accept 0 or more arguments</li>
|
|
<li>Body (optional): <code>{}</code> Must be separated from the Parameter List by a space</li>
|
|
</ul>
|
|
<p>There can be many different usages of these 4 elements depending on the Tag's implementation. Let's look at a few examples of how Leaf's built-in Tags might be used:</p>
|
|
<ul>
|
|
<li><code>#()</code></li>
|
|
<li><code>#(variable)</code></li>
|
|
<li><code>#import("template")</code></li>
|
|
<li><code>#export("link") { <a href="#()"></a> }</code></li>
|
|
<li><code>#index(friends, "0")</code></li>
|
|
<li><code>#loop(friends, "friend") { <li>#(friend.name)</li> }</code></li>
|
|
<li><code>#raw() { <a href="#raw">Anything goes!@#$%^&*</a> }</code></li>
|
|
</ul>
|
|
<h3 id="using-the">Using the <code>#</code> token in HTML</h3>
|
|
<p>The <code>#</code> token cannot be escaped. Use the <code>#()</code> or <code>#raw() {}</code> Tag to output a <code>#</code> in a Leaf Template. <code>#()</code> => <code>#</code></p>
|
|
<h3 id="raw-html">Raw HTML</h3>
|
|
<p>All Leaf output is escaped by default. Use the <code>#raw() {}</code> Tag for unescaped output.
|
|
<code>#raw() { <a href="#link">Link</a> }</code> => <code><a href="#link">Link</a></code></p>
|
|
<blockquote>
|
|
<p>IMPORTANT! Make sure you are not using the <code>#raw() {}</code> Tag with user input.</p>
|
|
</blockquote>
|
|
<h3 id="chaining">Chaining</h3>
|
|
<p>The double token: <code>##</code> indicates a chain. It can be applied to any standard Tag. If the previous Tag fails, the chained Tag will be given an opportunity to run.</p>
|
|
<pre><code>#if(hasFriends) ##embed("getFriends")</code></pre>
|
|
<h3 id="leafs-built-in-tags">Leaf's built-in Tags</h3>
|
|
<h4 id="token">Token: <code>#()</code></h4>
|
|
<pre><code>#() #()hashtags #()FTW => # #Hashtags #FTW</code></pre>
|
|
<h4 id="raw">Raw: <code>#raw() {}</code></h4>
|
|
<pre><code>#raw() {
|
|
Do whatever w/ #'s here, this code won't be rendered as leaf document and is not escaped.
|
|
It's a great place for things like Javascript or large HTML sections.
|
|
}</code></pre>
|
|
<h4 id="equal">Equal: <code>#equal(lhs, rhs) {}</code></h4>
|
|
<pre><code>#equal(leaf, leaf) { Leaf == Leaf } => Leaf == Leaf
|
|
#equal(leaf, mustache) { Leaf == Mustache } =></code></pre>
|
|
<h4 id="variable">Variable: <code>#(variable)</code></h4>
|
|
<pre><code>Hello, #(name)!</code></pre>
|
|
<h4 id="loop">Loop: <code>#loop(object, "index")</code></h4>
|
|
<pre><code>#loop(friends, "friend") {
|
|
Hello, #(friend.name)!
|
|
}</code></pre>
|
|
<h4 id="index">Index: <code>#index(object, _ index: Int|String)</code></h4>
|
|
<pre><code>Hello, #index(friends, 0)!
|
|
Hello, #index(friends, "best")!</code></pre>
|
|
<h4 id="if---else">If - Else: <code>#if(bool) ##else() { this }</code></h4>
|
|
<pre><code>#if(entering) {
|
|
Hello, there!
|
|
} ##if(leaving) {
|
|
Goodbye!
|
|
} ##else() {
|
|
I've been here the whole time.
|
|
}</code></pre>
|
|
<h4 id="import">Import: <code>#import("template")</code></h4>
|
|
<h4 id="export">Export: <code>#export("template") { Leaf/HTML }</code></h4>
|
|
<h4 id="extend">Extend: <code>#extend("template")</code></h4>
|
|
<h4 id="embed">Embed: <code>#embed("template")</code></h4>
|
|
<blockquote>
|
|
<p>When using these Layout Tags, omit the template file's .leaf extension.</p>
|
|
</blockquote>
|
|
<pre><code>/// base.leaf
|
|
<!DOCTYPE html>
|
|
#import("html")
|
|
|
|
/// html.leaf
|
|
#extend("base")
|
|
|
|
#export("html") { <html>#embed("body")</html> }
|
|
|
|
/// body.leaf
|
|
<body></body></code></pre>
|
|
<p>Leaf renders <code>html.leaf</code> as:</p>
|
|
<pre><code><!DOCTYPE html>
|
|
<html><body></body></html></code></pre>
|
|
<h3 id="custom-tags">Custom Tags</h3>
|
|
<p>Look at the existing tags for advanced scenarios, let's look at a basic example by creating <code>Index</code> together. This tag will take two arguments, an array, and an index to access.</p>
|
|
<pre><code class="language-swift">class Index: BasicTag {
|
|
let name = "index"
|
|
|
|
func run(arguments: [Argument]) throws -> Node? {
|
|
guard
|
|
arguments.count == 2,
|
|
let array = arguments[0].value?.nodeArray,
|
|
let index = arguments[1].value?.int,
|
|
index < array.count
|
|
else { return nil }
|
|
return array[index]
|
|
}
|
|
}</code></pre>
|
|
<p>We can now register this Tag in our <code>main.swift</code> file with:</p>
|
|
<pre><code class="language-swift">if let leaf = drop.view as? LeafRenderer {
|
|
leaf.stem.register(Index())
|
|
}</code></pre>
|
|
<p>And use it just like we did <a href="#index">above</a>.</p>
|
|
<blockquote>
|
|
<p>Note: Use of non-alphanumeric characters in Tag Names is <strong>strongly discouraged</strong> and may be disallowed in future versions of Leaf.</p>
|
|
</blockquote>
|
|
<h2 id="syntax-highlighting">Syntax Highlighting</h2>
|
|
<h3 id="atom">Atom</h3>
|
|
<p><a href="https://atom.io/packages/language-leaf">language-leaf</a> by ButkiewiczP</p>
|
|
<h3 id="xcode">Xcode</h3>
|
|
<p>It is not currently possible to implement Leaf Syntax Highlighting in Xcode, however, using Xcode's HTML Syntax Coloring can help a bit. Select one or more Leaf files and then choose Editor > Syntax Coloring > HTML. Your selected Leaf files will now use Xcode's HTML Syntax Coloring. Unfortunately the usefulness of this is limited because this association will be removed when <code>vapor xcode</code> is run.</p>
|
|
<p>There appears to be a way to <a href="http://stackoverflow.com/questions/9050035/how-to-make-xcode-recognize-a-custom-file-extension-as-objective-c-for-syntax-hi">make Xcode file associations persist</a> but that requires a bit more kung-fu.</p>
|
|
<h3 id="vs-code">VS Code</h3>
|
|
<p><a href="https://marketplace.visualstudio.com/items?itemName=Francisco.html-leaf">html-leaf</a> by FranciscoAmado</p>
|
|
<h3 id="clion-amp-appcode">CLion & AppCode</h3>
|
|
<p>Some preliminary work has been done to implement a Leaf Plugin for CLion & AppCode but lack of skill and interest in Java has slowed progress! If you have IntelliJ SDK experience and want to help with this, message Tom Holland on <a href="http://vapor.team">Vapor Slack</a></p>
|
|
</main>
|
|
|
|
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
|
|
<script src="/1.5/scripts/highlight.pack.js"></script>
|
|
|
|
<script>
|
|
hljs.registerLanguage("leaf", function (hljs) {
|
|
/* Author: Hale Chan <halechan@qq.com> */
|
|
return {
|
|
c: [
|
|
{
|
|
cN: 'function',
|
|
b: '#+',
|
|
e: '[)] ',
|
|
rB: true,
|
|
eE: false,
|
|
c : [
|
|
{
|
|
b: '[(]',
|
|
e: '[)]',
|
|
eE: true,
|
|
c: [
|
|
{
|
|
cN: 'string',
|
|
b: '"',
|
|
e: '"'
|
|
},
|
|
{
|
|
cN: 'title',
|
|
b: '[A-Za-z_][A-Za-z_0-9]*'
|
|
}
|
|
]
|
|
},
|
|
{
|
|
cN: 'keyword',
|
|
b: '#+([A-Za-z$_][0-9A-Za-z$_]*)?',
|
|
eP: true
|
|
},
|
|
]
|
|
}
|
|
]
|
|
};
|
|
});
|
|
</script>
|
|
|
|
<script>
|
|
$(function() {
|
|
// Syntax highlighting
|
|
hljs.initHighlightingOnLoad();
|
|
|
|
if (navigator.userAgent.indexOf('Safari') != -1 && navigator.userAgent.indexOf('Chrome') == -1) {
|
|
$('body').addClass('safari');
|
|
}
|
|
|
|
$('h1, h2, h3, h4, h5, h6').each(function(key, item) {
|
|
var $item = $(item);
|
|
var id = $item.attr('id');
|
|
if (id) {
|
|
var link = $('<a>');
|
|
link.attr('href', '#' + id);
|
|
$item.wrap(link);
|
|
}
|
|
})
|
|
|
|
$('a.toggle').on('click', function(e){
|
|
e.preventDefault();
|
|
console.log('hi');
|
|
var body = $('body');
|
|
if (body.hasClass('toggled')) {
|
|
body.removeClass('toggled');
|
|
} else {
|
|
body.addClass('toggled');
|
|
}
|
|
})
|
|
|
|
var lastScroll = 0;
|
|
var isUp = false;
|
|
var win = $(window);
|
|
|
|
win.on('scroll', function(){
|
|
var scrollTop = win.scrollTop();
|
|
var scrollBottom = win.scrollTop() + win.height();
|
|
var docHeight = $(document).height();
|
|
|
|
if ( scrollTop < 0 || scrollBottom >= docHeight ){
|
|
return;
|
|
}
|
|
|
|
if (scrollTop > (lastScroll + 0) && scrollTop >= 0) {
|
|
if (!isUp) {
|
|
$('a.toggle.show').addClass('hide')
|
|
}
|
|
isUp = true;
|
|
lastScroll = scrollTop;
|
|
} else if (scrollTop < (lastScroll - 0)) {
|
|
if (isUp) {
|
|
$('a.toggle.show').removeClass('hide')
|
|
}
|
|
isUp = false;
|
|
lastScroll = scrollTop;
|
|
}
|
|
});
|
|
|
|
// scroll to the active nav item
|
|
$("nav .scroll").animate({
|
|
scrollTop: $("nav .active").offset().top - 157
|
|
}, 0);
|
|
|
|
// var lastScrollTop = 0;
|
|
// $(window).scroll(function(event){
|
|
// var st = $(this).scrollTop();
|
|
// if (st > lastScrollTop){
|
|
// $('a.toggle.show').addClass('hide')
|
|
// } else {
|
|
// $('a.toggle.show').removeClass('hide')
|
|
// }
|
|
// lastScrollTop = st;
|
|
// });
|
|
});
|
|
</script>
|
|
|
|
<script>
|
|
(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', 'UA-76177358-4', 'auto');
|
|
ga('send', 'pageview');
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|