From 8ec6bd61be0f81057bdf3a86c253713978061d4c Mon Sep 17 00:00:00 2001 From: Benedikt Reichert Date: Sat, 12 Nov 2016 14:14:47 +0100 Subject: [PATCH 01/22] Updated minor version Updated to reflect current version (1.1.12). --- getting-started/manual.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/getting-started/manual.md b/getting-started/manual.md index 5333ab1c..ba91aa2b 100644 --- a/getting-started/manual.md +++ b/getting-started/manual.md @@ -60,7 +60,7 @@ import PackageDescription let package = Package( name: "Hello", dependencies: [ - .Package(url: "https://github.com/vapor/vapor.git", majorVersion: 1, minor: 0) + .Package(url: "https://github.com/vapor/vapor.git", majorVersion: 1, minor: 1) ] ) ``` From 4e69f97b6163c86a4c5d589dbcd3702182abd916 Mon Sep 17 00:00:00 2001 From: Benedikt Reichert Date: Sat, 12 Nov 2016 14:19:08 +0100 Subject: [PATCH 02/22] Fixed broken link to Provider --- guide/droplet.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guide/droplet.md b/guide/droplet.md index cce77d7f..20ebfba5 100644 --- a/guide/droplet.md +++ b/guide/droplet.md @@ -94,7 +94,7 @@ The `Droplet` will continue to use the default logger until you modify the `Conf The `Droplet` init method is fairly simple since most properties are variable and can be changed after initialization. -Most plugins for Vapor come with a [Provider](providers.md), these take care of configuration details for you. +Most plugins for Vapor come with a [Provider](provider.md), these take care of configuration details for you. ```swift Droplet( From a8b828037185dea43d8fcbc7fe96905711663675 Mon Sep 17 00:00:00 2001 From: Casper Rasmussen Date: Sun, 13 Nov 2016 09:06:46 +0100 Subject: [PATCH 03/22] Update config.md --- guide/config.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/guide/config.md b/guide/config.md index e5e3af5e..24c15b49 100644 --- a/guide/config.md +++ b/guide/config.md @@ -46,7 +46,7 @@ Let's add a custom key to the `servers.json` file: This can be accessed from your application's config using the following. ```swift -let customValue = app.config["server", "http", "custom-key"].string +let customValue = drop.config["server", "http", "custom-key"]?.string ?? "default" ``` That's it, feel free to add and utilize keys as necessary to make your application configuration easier. @@ -71,13 +71,13 @@ You can access your config directory with the following syntax. `app.config[<#fi We can access this file by making sure the first argument in our subscript is keys. To get the first name in our list: ```swift -let name = app.config["keys", "test-names", 0].string +let name = drop.config["keys", "test-names", 0]?.string ?? "default" ``` Or our mongo url: ```swift -let mongoUrl = app.config["keys", "mongo", "url"].string +let mongoUrl = drop.config["keys", "mongo", "url"].?string ?? "default" ``` ## Advanced Configurations From 3dcc9498c7430d3ce786ed3889088ac32407adcd Mon Sep 17 00:00:00 2001 From: Logan Wright Date: Sun, 13 Nov 2016 16:36:49 -0500 Subject: [PATCH 04/22] explicit testable import --- testing/basic.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/testing/basic.md b/testing/basic.md index 1c3a5a3b..d70d1cc0 100644 --- a/testing/basic.md +++ b/testing/basic.md @@ -48,7 +48,7 @@ drop.run() The first thing we'll do is in my testing target, add a file called `Droplet+Test.swift`. It will look like this: ```swift -import Vapor +@testable import Vapor func makeTestDroplet() throws -> Droplet { let drop = Droplet(arguments: ["dummy/path/", "prepare"], ...) @@ -58,7 +58,7 @@ func makeTestDroplet() throws -> Droplet { } ``` -This looks a lot like our initializer in `main.swift`, but there are 2 very key differences. +This looks a lot like our initializer in `main.swift`, but there are 3 very key differences. ### Droplet(arguments: ["dummy/path/", "prepare"], ... @@ -68,6 +68,10 @@ The `arguments:` parameter in our `Droplet` creation. This is rarely used except You'll notice here that we're calling `runCommands()` instead of `run()`. This allows the `Droplet` to do all the setup it would normally do before booting without actually binding to a socket or exiting. +### `@testable import Vapor` + +We'll need to import the testable compilation of Vapor to access the `runCommands` function. This is currently not public as a protection against accidental bugs in live apps. + ## Test Our Droplet Now that all of this has been created, we're ready to start testing our application's `Droplet`. Here's how a really basic test might look: From 9ecad20821e8c89ce3e0c10f641548847b0999f5 Mon Sep 17 00:00:00 2001 From: Tanner Nelson Date: Thu, 17 Nov 2016 12:08:27 -0500 Subject: [PATCH 05/22] leaf highlighting --- guide/leaf.md | 4 +-- template/default.twig | 40 ++++++++++++++++++++++++++++++ template/scripts/highlight.pack.js | 4 +-- 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/guide/leaf.md b/guide/leaf.md index b8c964f0..aa6c528a 100644 --- a/guide/leaf.md +++ b/guide/leaf.md @@ -97,7 +97,7 @@ Loop a variable The double token, `##` indicates a chain. If the previous tag fails, this tag will be given an opportunity to run. It can be applied to any standard tag, for example, above we chain to else, but we could also chain to loops. -``` +```leaf #empty(friends) { Try adding some friends! } ##loop(friends, "friend") { @@ -129,7 +129,7 @@ Leaf renders `html.leaf` as: #### Embedding -```swift +```leaf /// base.leaf #import("html") diff --git a/template/default.twig b/template/default.twig index b5d91911..70849437 100644 --- a/template/default.twig +++ b/template/default.twig @@ -69,6 +69,46 @@ + + ",rE:!0,sL:["actionscript","javascript","handlebars","xml"]}},{cN:"meta",v:[{b:/<\?xml/,e:/\?>/,r:10},{b:/<\?\w+/,e:/\?>/}]},{cN:"tag",b:"",c:[{cN:"name",b:/[^\/><\s]+/,r:0},t]}]}});hljs.registerLanguage("http",function(e){var t="HTTP/[0-9\\.]+";return{aliases:["https"],i:"\\S",c:[{b:"^"+t,e:"$",c:[{cN:"number",b:"\\b\\d{3}\\b"}]},{b:"^[A-Z]+ (.*?) "+t+"$",rB:!0,e:"$",c:[{cN:"string",b:" ",e:" ",eB:!0,eE:!0},{b:t},{cN:"keyword",b:"[A-Z]+"}]},{cN:"attribute",b:"^\\w",e:": ",eE:!0,i:"\\n|\\s|=",starts:{e:"$",r:0}},{b:"\\n\\n",starts:{sL:[],eW:!0}}]}});hljs.registerLanguage("javascript",function(e){var r="[A-Za-z$_][0-9A-Za-z$_]*",t={keyword:"in of if for while finally var new function do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const export super debugger as async await static import from as",literal:"true false null undefined NaN Infinity",built_in:"eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError Number Math Date String RegExp Array Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require module console window document Symbol Set Map WeakSet WeakMap Proxy Reflect Promise"},a={cN:"number",v:[{b:"\\b(0[bB][01]+)"},{b:"\\b(0[oO][0-7]+)"},{b:e.CNR}],r:0},n={cN:"subst",b:"\\$\\{",e:"\\}",k:t,c:[]},c={cN:"string",b:"`",e:"`",c:[e.BE,n]};n.c=[e.ASM,e.QSM,c,a,e.RM];var s=n.c.concat([e.CBCM,e.CLCM]);return{aliases:["js","jsx"],k:t,c:[{cN:"meta",r:10,b:/^\s*['"]use (strict|asm)['"]/},{cN:"meta",b:/^#!/,e:/$/},e.ASM,e.QSM,c,e.CLCM,e.CBCM,a,{b:/[{,]\s*/,r:0,c:[{b:r+"\\s*:",rB:!0,r:0,c:[{cN:"attr",b:r,r:0}]}]},{b:"("+e.RSR+"|\\b(case|return|throw)\\b)\\s*",k:"return throw case",c:[e.CLCM,e.CBCM,e.RM,{cN:"function",b:"(\\(.*?\\)|"+r+")\\s*=>",rB:!0,e:"\\s*=>",c:[{cN:"params",v:[{b:r},{b:/\(\s*\)/},{b:/\(/,e:/\)/,eB:!0,eE:!0,k:t,c:s}]}]},{b://,sL:"xml",c:[{b:/<\w+\s*\/>/,skip:!0},{b:/<\w+/,e:/(\/\w+|\w+\/)>/,skip:!0,c:[{b:/<\w+\s*\/>/,skip:!0},"self"]}]}],r:0},{cN:"function",bK:"function",e:/\{/,eE:!0,c:[e.inherit(e.TM,{b:r}),{cN:"params",b:/\(/,e:/\)/,eB:!0,eE:!0,c:s}],i:/\[|%/},{b:/\$[(.]/},e.METHOD_GUARD,{cN:"class",bK:"class",e:/[{;=]/,eE:!0,i:/[:"\[\]]/,c:[{bK:"extends"},e.UTM]},{bK:"constructor",e:/\{/,eE:!0}],i:/#(?!!)/}});hljs.registerLanguage("css",function(e){var c="[a-zA-Z-][a-zA-Z0-9_-]*",t={b:/[A-Z\_\.\-]+\s*:/,rB:!0,e:";",eW:!0,c:[{cN:"attribute",b:/\S/,e:":",eE:!0,starts:{eW:!0,eE:!0,c:[{b:/[\w-]+\(/,rB:!0,c:[{cN:"built_in",b:/[\w-]+/},{b:/\(/,e:/\)/,c:[e.ASM,e.QSM]}]},e.CSSNM,e.QSM,e.ASM,e.CBCM,{cN:"number",b:"#[0-9A-Fa-f]+"},{cN:"meta",b:"!important"}]}}]};return{cI:!0,i:/[=\/|'\$]/,c:[e.CBCM,{cN:"selector-id",b:/#[A-Za-z0-9_-]+/},{cN:"selector-class",b:/\.[A-Za-z0-9_-]+/},{cN:"selector-attr",b:/\[/,e:/\]/,i:"$"},{cN:"selector-pseudo",b:/:(:)?[a-zA-Z0-9\_\-\+\(\)"'.]+/},{b:"@(font-face|page)",l:"[a-z-]+",k:"font-face page"},{b:"@",e:"[{;]",i:/:/,c:[{cN:"keyword",b:/\w+/},{b:/\s/,eW:!0,eE:!0,r:0,c:[e.ASM,e.QSM,e.CSSNM]}]},{cN:"selector-tag",b:c,r:0},{b:"{",e:"}",i:/\S/,c:[e.CBCM,t]}]}});hljs.registerLanguage("bash",function(e){var t={cN:"variable",v:[{b:/\$[\w\d#@][\w\d_]*/},{b:/\$\{(.*?)}/}]},s={cN:"string",b:/"/,e:/"/,c:[e.BE,t,{cN:"variable",b:/\$\(/,e:/\)/,c:[e.BE]}]},a={cN:"string",b:/'/,e:/'/};return{aliases:["sh","zsh"],l:/-?[a-z\._]+/,k:{keyword:"if then else elif fi for while in do done case esac function",literal:"true false",built_in:"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp",_:"-ne -eq -lt -gt -f -d -e -s -l -a"},c:[{cN:"meta",b:/^#![^\n]+sh\s*$/,r:10},{cN:"function",b:/\w[\w\d_]*\s*\(\s*\)\s*\{/,rB:!0,c:[e.inherit(e.TM,{b:/\w[\w\d_]*/})],r:0},e.HCM,s,a,t]}});hljs.registerLanguage("swift",function(e){var t={keyword:"__COLUMN__ __FILE__ __FUNCTION__ __LINE__ as as! as? associativity break case catch class continue convenience default defer deinit didSet do dynamic dynamicType else enum extension fallthrough false final for func get guard if import in indirect infix init inout internal is lazy left let mutating nil none nonmutating operator optional override postfix precedence prefix private protocol Protocol public repeat required rethrows return right self Self set static struct subscript super switch throw throws true try try! try? Type typealias unowned var weak where while willSet",literal:"true false nil",built_in:"abs advance alignof alignofValue anyGenerator assert assertionFailure bridgeFromObjectiveC bridgeFromObjectiveCUnconditional bridgeToObjectiveC bridgeToObjectiveCUnconditional c contains count countElements countLeadingZeros debugPrint debugPrintln distance dropFirst dropLast dump encodeBitsAsWords enumerate equal fatalError filter find getBridgedObjectiveCType getVaList indices insertionSort isBridgedToObjectiveC isBridgedVerbatimToObjectiveC isUniquelyReferenced isUniquelyReferencedNonObjC join lazy lexicographicalCompare map max maxElement min minElement numericCast overlaps partition posix precondition preconditionFailure print println quickSort readLine reduce reflect reinterpretCast reverse roundUpToAlignment sizeof sizeofValue sort split startsWith stride strideof strideofValue swap toString transcode underestimateCount unsafeAddressOf unsafeBitCast unsafeDowncast unsafeUnwrap unsafeReflect withExtendedLifetime withObjectAtPlusZero withUnsafePointer withUnsafePointerToObject withUnsafeMutablePointer withUnsafeMutablePointers withUnsafePointer withUnsafePointers withVaList zip"},i={cN:"type",b:"\\b[A-Z][\\wÀ-ʸ']*",r:0},n=e.C("/\\*","\\*/",{c:["self"]}),r={cN:"subst",b:/\\\(/,e:"\\)",k:t,c:[]},a={cN:"number",b:"\\b([\\d_]+(\\.[\\deE_]+)?|0x[a-fA-F0-9_]+(\\.[a-fA-F0-9p_]+)?|0b[01_]+|0o[0-7_]+)\\b",r:0},o=e.inherit(e.QSM,{c:[r,e.BE]});return r.c=[a],{k:t,c:[o,e.CLCM,n,i,a,{cN:"function",bK:"func",e:"{",eE:!0,c:[e.inherit(e.TM,{b:/[A-Za-z$_][0-9A-Za-z$_]*/}),{b://},{cN:"params",b:/\(/,e:/\)/,endsParent:!0,k:t,c:["self",a,o,e.CBCM,{b:":"}],i:/["']/}],i:/\[|%/},{cN:"class",bK:"struct protocol class extension enum",k:t,e:"\\{",eE:!0,c:[e.inherit(e.TM,{b:/[A-Za-z$_][\u00C0-\u02B80-9A-Za-z$_]*/})]},{cN:"meta",b:"(@warn_unused_result|@exported|@lazy|@noescape|@NSCopying|@NSManaged|@objc|@convention|@required|@noreturn|@IBAction|@IBDesignable|@IBInspectable|@IBOutlet|@infix|@prefix|@postfix|@autoclosure|@testable|@available|@nonobjc|@NSApplicationMain|@UIApplicationMain)"},{bK:"import",e:/$/,c:[e.CLCM,n]}]}});hljs.registerLanguage("json",function(e){var i={literal:"true false null"},n=[e.QSM,e.CNM],r={e:",",eW:!0,eE:!0,c:n,k:i},t={b:"{",e:"}",c:[{cN:"attr",b:/"/,e:/"/,c:[e.BE],i:"\\n"},e.inherit(r,{b:/:/})],i:"\\S"},c={b:"\\[",e:"\\]",c:[e.inherit(r)],i:"\\S"};return n.splice(n.length,0,t,c),{c:n,k:i,i:"\\S"}}); \ No newline at end of file From 0799f8ed3d5e23d22d71a00b81db52fbf265a2e1 Mon Sep 17 00:00:00 2001 From: Tanner Nelson Date: Thu, 17 Nov 2016 12:11:24 -0500 Subject: [PATCH 06/22] also include echo tags --- template/default.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/template/default.twig b/template/default.twig index 70849437..f12e7f22 100644 --- a/template/default.twig +++ b/template/default.twig @@ -99,7 +99,7 @@ }, { cN: 'keyword', - b: '#+[A-Za-z$_][0-9A-Za-z$_]*', + b: '#+([A-Za-z$_][0-9A-Za-z$_]*)?', eP: true }, ] From 0471eb6c16fcfdea87f4767a1a830c9d411d3be7 Mon Sep 17 00:00:00 2001 From: isaoeka Date: Sun, 27 Nov 2016 23:30:56 +0900 Subject: [PATCH 07/22] Fix the position of try In addition, correction of missing designation https://github.com/vapor/mysql-provider/blob/master/Sources/VaporMySQL/Provider.swift#L61-L75 --- guide/provider.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/guide/provider.md b/guide/provider.md index 506e83ac..db8bfd18 100644 --- a/guide/provider.md +++ b/guide/provider.md @@ -74,8 +74,8 @@ import VaporMySQL let drop = Droplet() -let mysql = VaporMySQL.Provider(host: "localhost", user: "root") -try drop.addProvider(mysql) +let mysql = try VaporMySQL.Provider(host: "localhost", user: "root", password: "", database: "vapor") +drop.addProvider(mysql) ... From e0558c438eea5559182377abff2e16f52aa80dd9 Mon Sep 17 00:00:00 2001 From: slk333 Date: Mon, 28 Nov 2016 22:12:11 +0100 Subject: [PATCH 08/22] typo (psuedo -> pseudo) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7ad73d0b..53bf1e04 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ Here are a list of all the packages and modules included with Vapor (also useabl - [Crypto](https://github.com/vapor/crypto): Cryptography from LibreSSL and Swift. - Digests: Hashing with and without authentication. - Ciphers: Encryption and decryption - - Random: Psuedo and cryptographically secure randomness. + - 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. From 994587dbf3898f5a1f9a2b0c5c7f7901e90744ad Mon Sep 17 00:00:00 2001 From: Tanner Nelson Date: Tue, 29 Nov 2016 10:55:09 -0500 Subject: [PATCH 09/22] comma typo --- routing/parameters.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routing/parameters.md b/routing/parameters.md index 846b8a5e..5525873f 100644 --- a/routing/parameters.md +++ b/routing/parameters.md @@ -109,7 +109,7 @@ The resulting path for the above example is `/v1/users/:userId/posts/:postId`. I As shown briefly above, you are still free to do traditional routing. This can be useful for especially complex situations. ```swift -drop.get("v1", "users", ":userId", "posts", ":postId", "comments": ":commentId") { request in +drop.get("v1", "users", ":userId", "posts", ":postId", "comments", ":commentId") { request in let userId = try request.parameters.extract("userId") as Int let postId = try request.parameters.extract("postId") as Int let commentId = try request.parameters.extract("commentId") as Int From 083f8ca0372eb35f4b430f4b28aebb836025e263 Mon Sep 17 00:00:00 2001 From: "Brett R. Toomey" Date: Tue, 29 Nov 2016 10:00:44 -0800 Subject: [PATCH 10/22] Added Jobs repo Added my Jobs [repo](https://github.com/BrettRToomey/Jobs) to the list of packages. --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 53bf1e04..e7807c04 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,7 @@ Here are a list of providers and third party packages that work great with Vapor - [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 +- [Jobs](https://github.com/BrettRToomey/Jobs): A minimalistic job/background-task system for Swift. ## Authors From bcaf885b442ad7627d9f32f66a68fff72cebc3bf Mon Sep 17 00:00:00 2001 From: bygri Date: Fri, 2 Dec 2016 09:49:43 +1100 Subject: [PATCH 11/22] Add VaporForms to list of providers --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 53bf1e04..b492f5cb 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,7 @@ Here are a list of providers and third party packages that work great with Vapor - [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. ## Authors From ba7c7a91b84082f21842a198999f3e71a4a09590 Mon Sep 17 00:00:00 2001 From: krystofbe Date: Fri, 2 Dec 2016 10:43:55 +0100 Subject: [PATCH 12/22] Typo --- guide/middleware.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guide/middleware.md b/guide/middleware.md index a1b2dcd4..248135fc 100644 --- a/guide/middleware.md +++ b/guide/middleware.md @@ -84,7 +84,7 @@ enum FooError: Error { } ``` -Say there is a custom error that either you defined or one of the APIs you are using `throw`s. This error must be caught when thrown, or else it will end up as a server error which may be unexpected to a user. The most obvious solution is to catch the error in the route closure. +Say there is a custom error that either you defined or one of the APIs you are using `throws`. This error must be caught when thrown, or else it will end up as a server error which may be unexpected to a user. The most obvious solution is to catch the error in the route closure. ```swift app.get("foo") { request in From d8ca0758fb4423f5d75f82786444b6231f68ae28 Mon Sep 17 00:00:00 2001 From: James Lin Date: Sun, 4 Dec 2016 20:31:33 -0500 Subject: [PATCH 13/22] added a missing ? to make the documentation work as is --- routing/parameters.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routing/parameters.md b/routing/parameters.md index 5525873f..a0886167 100644 --- a/routing/parameters.md +++ b/routing/parameters.md @@ -20,7 +20,7 @@ This creates a route that matches `users/:id` where the `:id` is an `Int`. Here' ```swift drop.get("users", ":id") { request in - guard let userId = request.parameters["id"].int else { + guard let userId = request.parameters["id"]?.int else { throw Abort.badRequest } From 0de995f4d2d436a67f2214250081f1f275f955cc Mon Sep 17 00:00:00 2001 From: Tanner Nelson Date: Wed, 7 Dec 2016 12:52:49 -0500 Subject: [PATCH 14/22] api docs --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 53bf1e04..66a02466 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,10 @@ To view the framework's source code and code documentation, visit [Vapor's GitHu You can read this guide by clicking through the folders and markdown files on [GitHub](https://github.com/vapor/documentation) or through the rendered [GitHub Pages](https://vapor.github.io/documentation/). +## API + +Auto-generated API documentation is located at [api.vapor.codes](http://api.vapor.codes). + ## Packages Here are a list of all the packages and modules included with Vapor (also useable individually). From e235046aef4b0c4398b2da3fe43ddeab604c3437 Mon Sep 17 00:00:00 2001 From: bygri Date: Thu, 8 Dec 2016 20:58:53 +1100 Subject: [PATCH 15/22] Correct typo in supervisor.md --- deploy/supervisor.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/supervisor.md b/deploy/supervisor.md index 9b3a3a86..c84b7217 100644 --- a/deploy/supervisor.md +++ b/deploy/supervisor.md @@ -33,7 +33,7 @@ The `--env=production` flag will disable verbose logging and prioritize the `Con ### Environment -You can export variables to your Vapor app with sueprvisor. +You can export variables to your Vapor app with supervisor. ```sh environment=PORT=8123 From 9ad6d8eaacce0cfec7d993633c13b3a2c1cc4b08 Mon Sep 17 00:00:00 2001 From: Tom Holland Date: Thu, 8 Dec 2016 09:58:14 -0800 Subject: [PATCH 16/22] Improved Leaf Docs --- guide/leaf.md | 209 +++++++++++++++++++++++--------------------------- 1 file changed, 97 insertions(+), 112 deletions(-) diff --git a/guide/leaf.md b/guide/leaf.md index aa6c528a..e34bc6f6 100644 --- a/guide/leaf.md +++ b/guide/leaf.md @@ -4,7 +4,7 @@ currentMenu: guide-leaf # Leaf -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: +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: - Small set of strictly enforced rules - Consistency @@ -12,78 +12,88 @@ Welcome to Leaf. Leaf's goal is to be a simple templating language that can make - Extensibility ## Syntax - -Leaf syntax is based around a single token, in this case, the hashtag: `#`. - ->It's important to note that _all_ hashtags will be parsed, there is no escaping. Use `#()` to render a plain `#`. `#()Leaf` => `#Leaf`. Or, for larger sections, use the `raw` tag. `#raw() { #Do #whatever #you #want #to #in #here!. }` - ### Structure -Here we see all the components of a Leaf tag. +Leaf Tags are made up of 4 Elements: + - Token: `#` is the Token + - Name: A `string` that identifies the tag + - Parameter List: `()` May accept 0 or more arguments + - Body(optional): `{}` Must be separated from the Parameter List by a space -```leaf -#someTag(parameter.list, goes, "here") { - This is an optional body here -} +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: + + - `#()` + - `#(variable)` + - `#import("template")` + - `#export("link") { }` + - `#index(friends, "0")` + - `#loop(friends, "friend") {
  • #(friend.name)
  • }` + - `#raw() { Anything goes!@#$%^&* }` + +### Using the `#` token in HTML + +The token cannot be escaped. Use the `#()` or `#raw() {}` Tag to output a `#` in a Leaf Template. `#()` => `#` + +### Raw HTML + +All Leaf output is escaped by default. Use the `#raw() {}` Tag for unescaped output. +`#raw() { Link }` => `Link` +> IMPORTANT! Make sure you are not using the `#raw() {}` Tag with user input. + +### Chaining + +The double token: `##` 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. + +``` +#if(hasFriends) ##embed("getFriends") ``` -##### Token +### Leaf's built-in Tags ->The `#` token will define we're a tag +#### Token: `#()` -##### Name +``` +#() #()hashtags #()FTW => # #Hashtags #FTW +``` ->In above example, it would be `someTag`. While not strictly enforced, it is **highly** encouraged that users only use alphanumeric characters in names. This may be enforced in future versions. +#### Raw: `#raw() {}` -##### Parameter List - -`Var(parameter, list), Var(goes), Const("here")` - -##### Body - -> This is an optional body here indicated w/ open and closed curly brackets. - -#### Using # in html with Leaf - -If you need # to appear alone in your html, simply using `#()` will render as #. Alternatively, the raw tag is available for larger sections of code: - -```leaf +``` #raw() { - Do whatever w/ #'s here, this code - won't be rendered as leaf document. - It's a great place for things like Javascript or large HTML sections. + 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. } ``` -## Syntax Highlighting +#### Equal: `#equal(lhs, rhs) {}` -### Atom +``` +#equal(leaf, leaf) { Leaf == Leaf } => Leaf == Leaf +#equal(leaf, mustache) { Leaf == Mustache } => +``` -[language-leaf](https://atom.io/packages/language-leaf) by ButkiewiczP +#### Variable: `#(variable)` -## Examples - -#### Variable - -Variables are added w/ just a number sign. - -```leaf +``` Hello, #(name)! ``` -#### Loop +#### Loop: `#loop(object, "index")` -Loop a variable - -```leaf +``` #loop(friends, "friend") { Hello, #(friend.name)! } ``` +#### Index: `#loop(object, "index")` -#### If - Else +``` +Hello, #index(friends, "0")! +``` -```leaf +#### If - Else: `#if(bool) ##else() { this }` + +``` #if(entering) { Hello, there! } ##if(leaving) { @@ -93,21 +103,14 @@ Loop a variable } ``` -#### Chaining +#### Import: `#import("template")` +#### Export: `#export("template") { Leaf/HTML }` +#### Extend: `#extend("template")` +#### Embed: `#embed("template")` -The double token, `##` indicates a chain. If the previous tag fails, this tag will be given an opportunity to run. It can be applied to any standard tag, for example, above we chain to else, but we could also chain to loops. +> When using these Layout Tags, omit the template file's .leaf extension. -```leaf -#empty(friends) { - Try adding some friends! -} ##loop(friends, "friend") { -
  • #(friend.name)
  • -} ``` - -#### Extending - -```swift /// base.leaf #import("html") @@ -115,38 +118,15 @@ The double token, `##` indicates a chain. If the previous tag fails, this tag wi /// html.leaf #extend("base") -#export("html") { - -} -``` - -Leaf renders `html.leaf` as: - -```html - - -``` - -#### Embedding - -```leaf -/// base.leaf - -#import("html") - -/// html.leaf -#extend("base") - -#export("html") { - #embed("body") -} +#export("html") { #embed("body") } /// body.leaf ``` + Leaf renders `html.leaf` as: -```html +``` ``` @@ -155,40 +135,45 @@ Leaf renders `html.leaf` as: Look at the existing tags for advanced scenarios, let's look at a basic example by creating `Index` together. This tag will take two arguments, an array, and an index to access. -``` +```swift class Index: BasicTag { - let name = "index" + 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 } + 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] } } ``` -Now, after creating our `Stem`, we can register the tag: +We can now register this Tag in our `main.swift` file with: -``` -stem.register(Index()) -``` - -And use it like so: - -``` -Hello, #index(friends, "0")! -``` - -We can also chain `else` to this like we did earlier if we want to check existence first: - -``` -#index(friends, "0") { - Hello, #(self)! -} ##else() { - Nobody's there! +```swift +if let leaf = drop.view as? LeafRenderer { + leaf.stem.register(Version()) } ``` + +And use it just like we did [above](#index). + +> Note: Use of non-alphanumeric characters in Tag Names is **strongly discouraged** and may be disallowed in future versions of Leaf. + +## Syntax Highlighting + +### Atom + +[language-leaf](https://atom.io/packages/language-leaf) by ButkiewiczP + +### Xcode +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 `vapor xcode` is run. + +There appears to be a way to [make Xcode file associations persist](http://stackoverflow.com/questions/9050035/how-to-make-xcode-recognize-a-custom-file-extension-as-objective-c-for-syntax-hi) but that requires a bit more kung-fu. + +### CLion & AppCode + +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 [Vapor Slack](http://vapor.team) From 9f83ba384e1fb2465a428178b7649f1c251df486 Mon Sep 17 00:00:00 2001 From: Brian Date: Fri, 9 Dec 2016 14:17:14 +0100 Subject: [PATCH 17/22] Fix sample middleware code --- guide/middleware.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/guide/middleware.md b/guide/middleware.md index a1b2dcd4..1b5957d1 100644 --- a/guide/middleware.md +++ b/guide/middleware.md @@ -180,14 +180,14 @@ Middleware pairs great with request/response extensions and storage. final class PokemonMiddleware: Middleware { let drop: Droplet init(drop: Droplet) { - self.drop = dropt + self.drop = drop } func respond(to request: Request, chainingTo next: Responder) throws -> Response { let response = try next.respond(to: request) if let pokemon = response.pokemon { - request.accept.prefers("html") { + if request.accept.prefers("html") { response.view = try drop.view("pokemon.mustache", context: pokemon) } else { response.json = try pokemon.makeJSON() From 0736a983e4605ec58f41b91e4716934ee765cac6 Mon Sep 17 00:00:00 2001 From: bygri Date: Sat, 10 Dec 2016 22:21:55 +1100 Subject: [PATCH 18/22] VaporForms and Jobs into Chinese readme Only names and links until the descriptions can be translated --- README.zh-hant.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.zh-hant.md b/README.zh-hant.md index 3a4a702e..967902d4 100644 --- a/README.zh-hant.md +++ b/README.zh-hant.md @@ -67,6 +67,8 @@ Vapor 是一個在 Swift 上很受歡迎的 Web framework。它提供了清楚 - [VaporS3Signer](https://github.com/JustinM1/VaporS3Signer): 用來產生 HTTP request 的 headers 及已經簽證過的 URL,用來 request AWS S3 的 REST API。 - [Flock](https://github.com/jakeheis/Flock): 自動將 Swift 專案發佈上主機。 - [VaporFlock](https://github.com/jakeheis/VaporFlock): 利用 Flock 發佈 Vapor applications。 +- [VaporForms](https://github.com/bygri/vapor-forms)。 +- [Jobs](https://github.com/BrettRToomey/Jobs)。 ## 作者們 From 9417b1cd373f0e111053d3a5f621f25a9d380434 Mon Sep 17 00:00:00 2001 From: Anton Strogonoff Date: Sun, 11 Dec 2016 06:42:55 +0300 Subject: [PATCH 19/22] Fixed broken links to GitHub searches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apparently GitHub has renamed “query” to “q”. Not critical, but better when links from the docs work straight away. --- fluent/driver.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fluent/driver.md b/fluent/driver.md index 285b2eea..062899a4 100644 --- a/fluent/driver.md +++ b/fluent/driver.md @@ -13,8 +13,8 @@ This graphic shows the relation between Drivers and Providers using MySQL as an If you want to use Fluent without Vapor, you will import Drivers into your package. If you are using Vapor, you will import Providers. Search GitHub for: -- [Fluent Drivers](https://github.com/vapor?utf8=✓&query=-driver) -- [Vapor Providers](https://github.com/vapor?utf8=✓&query=-provider) +- [Fluent Drivers](https://github.com/vapor?utf8=✓&q=-driver) +- [Vapor Providers](https://github.com/vapor?utf8=✓&q=-provider) Not all drivers have providers yet, and not all drivers or providers are up to date with the latest Vapor 1.0. This is a great way to contribute! From 4182d40309895cc33b90e3ffe8da7cf61ada5152 Mon Sep 17 00:00:00 2001 From: Anton Strogonoff Date: Sun, 11 Dec 2016 06:45:01 +0300 Subject: [PATCH 20/22] Fixed a broken link to GitHub search --- guide/provider.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/guide/provider.md b/guide/provider.md index db8bfd18..2a4b5920 100644 --- a/guide/provider.md +++ b/guide/provider.md @@ -12,7 +12,7 @@ Adding a provider to your application takes 2-3 steps. ### Add Package -All of Vapor's providers end with the `-provider` syntax. You can see a list of [available providers](https://github.com/vapor?utf8=✓&query=-provider) by searching on our GitHub. +All of Vapor's providers end with the `-provider` syntax. You can see a list of [available providers](https://github.com/vapor?utf8=✓&q=-provider) by searching on our GitHub. To add the provider to your package, add it as a dependency in your `Package.swift` file. From c4d5b713faeeb93f87b014676033e52596a32af5 Mon Sep 17 00:00:00 2001 From: Sundeep Gupta Date: Wed, 14 Dec 2016 16:26:42 -0500 Subject: [PATCH 21/22] Explicitly unwrap optionals in JSON example Without this, compiler fails --- guide/json.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/guide/json.md b/guide/json.md index 2579ede9..8b6d4fd9 100644 --- a/guide/json.md +++ b/guide/json.md @@ -27,11 +27,11 @@ To specifically target JSON, use the `request.json` property. ```swift drop.post("json") { request in - guard let name = request.json["name"].string else { - throw Abort.badRequest - } + guard let name = request.json?["name"]?.string else { + throw Abort.badRequest + } - return "Hello, \(name)!" + return "Hello, \(name)!" } ``` The above snippet will only work if the request is sent with JSON data. From dee69ac5f11db60762a61b295f54f6b88780197c Mon Sep 17 00:00:00 2001 From: Ankit Goel Date: Thu, 15 Dec 2016 21:15:35 +0530 Subject: [PATCH 22/22] Adds heimdall repo --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 5d63d0b8..67ec075d 100644 --- a/README.md +++ b/README.md @@ -76,6 +76,7 @@ Here are a list of providers and third party packages that work great with Vapor - [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. ## Authors