mirror of
https://github.com/labstack/echo.git
synced 2025-01-12 01:22:21 +02:00
Moved website from echo to echox
Signed-off-by: Vishal Rana <vr@labstack.com>
This commit is contained in:
parent
5b5df5bf44
commit
861712f469
@ -1,7 +0,0 @@
|
||||
FROM reg.lab.st/argo
|
||||
MAINTAINER Vishal Rana <vr@labstack.com>
|
||||
|
||||
ADD argo.json /etc
|
||||
ADD public /www
|
||||
|
||||
CMD ["-c", "/etc/argo.json"]
|
@ -1,14 +0,0 @@
|
||||
{
|
||||
"www": {
|
||||
"listen": ":80",
|
||||
"hosts": {
|
||||
"*": {
|
||||
"paths": {
|
||||
"/*": {
|
||||
"dir": "/www"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
{
|
||||
"baseurl": "https://labstack.com/echo",
|
||||
"languageCode": "en-us",
|
||||
"title": "Echo",
|
||||
"canonifyurls": true,
|
||||
|
||||
"menu": {
|
||||
"side": [{
|
||||
"name": "Guide",
|
||||
"pre": "<i class='fa fa-book'></i>",
|
||||
"weight": 1,
|
||||
"identifier": "guide",
|
||||
"url": "guide"
|
||||
}, {
|
||||
"Name": "Recipes",
|
||||
"Pre": "<i class='fa fa-code'></i>",
|
||||
"Weight": 2,
|
||||
"Identifier": "recipes",
|
||||
"URL": "recipes"
|
||||
}]
|
||||
},
|
||||
|
||||
"params": {
|
||||
"description": "Golang micro web framework, High performance, Minimalistic and Fast.",
|
||||
"googleAnayticsId": "UA-51208124-3"
|
||||
}
|
||||
}
|
@ -1,106 +0,0 @@
|
||||
---
|
||||
title: Customization
|
||||
menu:
|
||||
side:
|
||||
parent: guide
|
||||
weight: 3
|
||||
---
|
||||
|
||||
### HTTP error handler
|
||||
|
||||
`Echo#SetHTTPErrorHandler(h HTTPErrorHandler)`
|
||||
|
||||
Registers a custom `Echo#HTTPErrorHandler`.
|
||||
|
||||
Default handler rules:
|
||||
|
||||
- If error is of type `Echo#HTTPError` it sends HTTP response with status code `HTTPError.Code`
|
||||
and message `HTTPError.Message`.
|
||||
- Else it sends `500 - Internal Server Error`.
|
||||
- If debug mode is enabled, it uses `error.Error()` as status message.
|
||||
|
||||
### Debug
|
||||
|
||||
`Echo#SetDebug(on bool)`
|
||||
|
||||
Enable/disable debug mode.
|
||||
|
||||
### Log prefix
|
||||
|
||||
`Echo#SetLogPrefix(prefix string)`
|
||||
|
||||
SetLogPrefix sets the prefix for the logger. Default value is `echo`.
|
||||
|
||||
### Log output
|
||||
|
||||
`Echo#SetLogOutput(w io.Writer)`
|
||||
|
||||
SetLogOutput sets the output destination for the logger. Default value is `os.Stdout`
|
||||
|
||||
To completely disable logs use `Echo#SetLogOutput(io.Discard)`
|
||||
|
||||
### Log level
|
||||
|
||||
`Echo#SetLogLevel(l log.Level)`
|
||||
|
||||
SetLogLevel sets the log level for the logger. Default value is `log.ERROR`.
|
||||
|
||||
### Engine
|
||||
|
||||
#### Standard HTTP server
|
||||
|
||||
```go
|
||||
e.Run(standard.New(":1323"))
|
||||
```
|
||||
|
||||
##### From TLS
|
||||
|
||||
```go
|
||||
e.Run(standard.NewFromTLS(":1323", "<certfile>", "<keyfile>"))
|
||||
```
|
||||
|
||||
##### From config
|
||||
|
||||
```go
|
||||
e.Run(standard.NewFromConfig(&Config{}))
|
||||
```
|
||||
|
||||
#### FastHTTP server
|
||||
|
||||
```go
|
||||
e.Run(fasthttp.New(":1323"))
|
||||
```
|
||||
|
||||
##### From TLS
|
||||
|
||||
```go
|
||||
e.Run(fasthttp.NewFromTLS(":1323", "<certfile>", "<keyfile>"))
|
||||
```
|
||||
|
||||
|
||||
##### From config
|
||||
```go
|
||||
e.Run(fasthttp.NewFromConfig(&Config{}))
|
||||
```
|
||||
|
||||
#### Configuration
|
||||
|
||||
##### `Address`
|
||||
|
||||
Address to bind.
|
||||
|
||||
##### `TLSCertfile`
|
||||
|
||||
TLS certificate file path
|
||||
|
||||
##### `TLSKeyfile`
|
||||
|
||||
TLS key file path
|
||||
|
||||
##### `ReadTimeout`
|
||||
|
||||
HTTP read timeout
|
||||
|
||||
##### `WriteTimeout`
|
||||
|
||||
HTTP write timeout
|
@ -1,48 +0,0 @@
|
||||
---
|
||||
title: Error Handling
|
||||
menu:
|
||||
side:
|
||||
parent: guide
|
||||
weight: 8
|
||||
---
|
||||
|
||||
Echo advocates centralized HTTP error handling by returning `error` from middleware
|
||||
and handlers.
|
||||
|
||||
It allows you to:
|
||||
|
||||
- Debug by writing stack trace to the HTTP response.
|
||||
- Customize HTTP responses.
|
||||
- Recover from panics inside middleware or handlers.
|
||||
|
||||
For example, when basic auth middleware finds invalid credentials it returns
|
||||
`401 - Unauthorized` error, aborting the current HTTP request.
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo"
|
||||
)
|
||||
|
||||
func main() {
|
||||
e := echo.New()
|
||||
e.Use(func(c echo.Context) error {
|
||||
// Extract the credentials from HTTP request header and perform a security
|
||||
// check
|
||||
|
||||
// For invalid credentials
|
||||
return echo.NewHTTPError(http.StatusUnauthorized)
|
||||
})
|
||||
e.Get("/welcome", welcome)
|
||||
e.Run(":1323")
|
||||
}
|
||||
|
||||
func welcome(c echo.Context) error {
|
||||
return c.String(http.StatusOK, "Welcome!")
|
||||
}
|
||||
```
|
||||
|
||||
See how [HTTPErrorHandler](/guide/customization#http-error-handler) handles it.
|
@ -1,26 +0,0 @@
|
||||
---
|
||||
title: Installation
|
||||
menu:
|
||||
side:
|
||||
parent: guide
|
||||
weight: 1
|
||||
---
|
||||
|
||||
Echo is developed and tested using Go `1.5.x` and `1.6.x`
|
||||
|
||||
#### Install the latest stable version of Echo via `go get`
|
||||
|
||||
```sh
|
||||
$ go get github.com/labstack/echo
|
||||
```
|
||||
|
||||
#### Update
|
||||
|
||||
```sh
|
||||
$ go get -u github.com/labstack/echo
|
||||
```
|
||||
|
||||
#### [Migrating from v1](/guide/migrating)
|
||||
|
||||
Echo follows [semantic versioning](http://semver.org) managed through GitHub releases.
|
||||
Specific version of Echo can be installed using a [package manager](https://github.com/avelino/awesome-go#package-management).
|
@ -1,67 +0,0 @@
|
||||
---
|
||||
title: Middleware
|
||||
menu:
|
||||
side:
|
||||
parent: guide
|
||||
weight: 5
|
||||
---
|
||||
|
||||
Middleware is a function which is chained in the HTTP request-response cycle. Middleware
|
||||
has access to the request and response objects which it utilizes to perform a specific
|
||||
action, for example, logging every request.
|
||||
|
||||
### Logger
|
||||
|
||||
Logs each HTTP request with method, path, status, response time and bytes served.
|
||||
|
||||
*Example*
|
||||
|
||||
```go
|
||||
e.Use(Logger())
|
||||
|
||||
// Output: `2015/06/07 18:16:16 GET / 200 13.238µs 14`
|
||||
```
|
||||
|
||||
### BasicAuth
|
||||
|
||||
BasicAuth middleware provides an HTTP basic authentication.
|
||||
|
||||
- For valid credentials it calls the next handler in the chain.
|
||||
- For invalid Authorization header it sends "404 - Bad Request" response.
|
||||
- For invalid credentials, it sends "401 - Unauthorized" response.
|
||||
|
||||
*Example*
|
||||
|
||||
```go
|
||||
g := e.Group("/admin")
|
||||
e.Use(middleware.BasicAuth(func(username, password string) bool {
|
||||
if username == "joe" && password == "secret" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}))
|
||||
```
|
||||
|
||||
### Gzip
|
||||
|
||||
Gzip middleware compresses HTTP response using gzip compression scheme.
|
||||
|
||||
*Example*
|
||||
|
||||
```go
|
||||
e.Use(mw.Gzip())
|
||||
```
|
||||
|
||||
### Recover
|
||||
|
||||
Recover middleware recovers from panics anywhere in the chain and handles the
|
||||
control to the centralized
|
||||
[HTTPErrorHandler]({{< relref "guide/customization.md#http-error-handler">}}).
|
||||
|
||||
*Example*
|
||||
|
||||
```go
|
||||
e.Use(middleware.Recover())
|
||||
```
|
||||
|
||||
### [Recipes](https://github.com/labstack/echox/tree/master/recipe/middleware)
|
@ -1,32 +0,0 @@
|
||||
---
|
||||
title: Migrating
|
||||
menu:
|
||||
side:
|
||||
parent: guide
|
||||
weight: 2
|
||||
---
|
||||
|
||||
### Migrating from v1
|
||||
|
||||
#### Change log
|
||||
|
||||
- Good news, 85% of the API remains the same.
|
||||
- `Engine` interface to abstract `HTTP` server implementation, allowing
|
||||
us to use HTTP servers beyond Go standard library. It currently supports standard HTTP server and [FastHTTP](https://github.com/valyala/fasthttp).
|
||||
- Context, Request and Response are converted to interfaces. [More...](https://github.com/labstack/echo/issues/146)
|
||||
- Handler signature is changed to `func (c echo.Context) error`.
|
||||
- Dropped auto wrapping of handler and middleware to enforce compile time check.
|
||||
- Handler only accepts `Echo#Handler` interface.
|
||||
- Middleware only accepts `Echo#Middleware` interface.
|
||||
- `Echo#HandlerFunc` adapter to use ordinary functions as handlers.
|
||||
- `Echo#MiddlewareFunc` adapter to use ordinary functions as middleware.
|
||||
- Middleware is run before hitting the router, which doesn't require `Echo#Hook` API as
|
||||
it can be achieved via middleware.
|
||||
- Ability to define middleware at route level.
|
||||
- `Echo#HTTPError` exposed it's fields `Code` and `Message`.
|
||||
|
||||
#### How?
|
||||
|
||||
Quite easy
|
||||
- Browse through [recipes](/recipes/hello-world) freshly converted to v2.
|
||||
- Read documentation and dig into test cases.
|
@ -1,99 +0,0 @@
|
||||
---
|
||||
title: Request
|
||||
menu:
|
||||
side:
|
||||
parent: guide
|
||||
weight: 6
|
||||
---
|
||||
|
||||
### Handler path
|
||||
|
||||
`Context#Path()` returns the registered path for the handler, it can be used in the
|
||||
middleware for logging purpose.
|
||||
|
||||
*Example*
|
||||
|
||||
```go
|
||||
e.Use(func(c echo.Context) error {
|
||||
println(c.Path()) // Prints `/users/:name`
|
||||
return nil
|
||||
})
|
||||
e.Get("/users/:name", func(c echo.Context) error) {
|
||||
return c.String(http.StatusOK, name)
|
||||
})
|
||||
```
|
||||
|
||||
### golang.org/x/net/context
|
||||
|
||||
`echo.Context` embeds `context.Context` interface, so all it's properties
|
||||
are available right from `echo.Context`.
|
||||
|
||||
*Example*
|
||||
|
||||
```go
|
||||
e.Get("/users/:name", func(c echo.Context) error) {
|
||||
c.Context = context.WithValue(nil, "key", "val")
|
||||
// Pass it down...
|
||||
// Use it...
|
||||
println(c.Value("key"))
|
||||
return c.String(http.StatusOK, name)
|
||||
})
|
||||
```
|
||||
|
||||
### Path parameter
|
||||
|
||||
Path parameter can be retrieved either by name `Context#Param(name string) string`
|
||||
or by index `Context#P(i int) string`. Getting parameter by index gives a slightly
|
||||
better performance.
|
||||
|
||||
*Example*
|
||||
|
||||
```go
|
||||
e.Get("/users/:name", func(c echo.Context) error {
|
||||
// By name
|
||||
name := c.Param("name")
|
||||
|
||||
// By index
|
||||
name := c.P(0)
|
||||
|
||||
return c.String(http.StatusOK, name)
|
||||
})
|
||||
```
|
||||
|
||||
```sh
|
||||
$ curl http://localhost:1323/users/joe
|
||||
```
|
||||
|
||||
### Query parameter
|
||||
|
||||
Query parameter can be retrieved by name using `Context#Query(name string)`.
|
||||
|
||||
*Example*
|
||||
|
||||
```go
|
||||
e.Get("/users", func(c echo.Context) error {
|
||||
name := c.Query("name")
|
||||
return c.String(http.StatusOK, name)
|
||||
})
|
||||
```
|
||||
|
||||
```sh
|
||||
$ curl -G -d "name=joe" http://localhost:1323/users
|
||||
```
|
||||
|
||||
### Form parameter
|
||||
|
||||
Form parameter can be retrieved by name using `Context#Form(name string)`.
|
||||
|
||||
*Example*
|
||||
|
||||
```go
|
||||
e.Post("/users", func(c echo.Context) error {
|
||||
name := c.Form("name")
|
||||
return c.String(http.StatusOK, name)
|
||||
})
|
||||
```
|
||||
|
||||
```sh
|
||||
$ curl -d "name=joe" http://localhost:1323/users
|
||||
```
|
@ -1,122 +0,0 @@
|
||||
---
|
||||
title: Response
|
||||
menu:
|
||||
side:
|
||||
parent: guide
|
||||
weight: 7
|
||||
---
|
||||
|
||||
### Template
|
||||
|
||||
`Context#Render(code int, name string, data interface{}) error`
|
||||
|
||||
Renders a template with data and sends a text/html response with status code. Templates
|
||||
can be registered using `Echo.SetRenderer()`, allowing us to use any template engine.
|
||||
|
||||
Below is an example using Go `html/template`
|
||||
|
||||
- Implement `echo.Render` interface
|
||||
|
||||
```go
|
||||
type Template struct {
|
||||
templates *template.Template
|
||||
}
|
||||
|
||||
func (t *Template) Render(w io.Writer, name string, data interface{}, c echo.Context) error {
|
||||
return t.templates.ExecuteTemplate(w, name, data)
|
||||
}
|
||||
```
|
||||
|
||||
- Pre-compile templates
|
||||
|
||||
`public/views/hello.html`
|
||||
|
||||
```html
|
||||
{{define "hello"}}Hello, {{.}}!{{end}}
|
||||
```
|
||||
|
||||
```go
|
||||
t := &Template{
|
||||
templates: template.Must(template.ParseGlob("public/views/*.html")),
|
||||
}
|
||||
```
|
||||
|
||||
- Register templates
|
||||
|
||||
```go
|
||||
e := echo.New()
|
||||
e.SetRenderer(t)
|
||||
e.Get("/hello", Hello)
|
||||
```
|
||||
|
||||
- Render template
|
||||
|
||||
```go
|
||||
func Hello(c echo.Context) error {
|
||||
return c.Render(http.StatusOK, "hello", "World")
|
||||
}
|
||||
```
|
||||
|
||||
### JSON
|
||||
|
||||
`Context.JSON(code int, v interface{}) error`
|
||||
|
||||
Sends a JSON HTTP response with status code.
|
||||
|
||||
### JSONP
|
||||
|
||||
`Context.JSONP(code int, callback string, i interface{}) error`
|
||||
|
||||
Sends a JSONP HTTP response with status code. It uses `callback` to construct the
|
||||
JSONP payload.
|
||||
|
||||
### XML
|
||||
|
||||
`Context.XML(code int, v interface{}) error`
|
||||
|
||||
Sends an XML HTTP response with status code.
|
||||
|
||||
### HTML
|
||||
|
||||
`c.HTML(code int, html string) error`
|
||||
|
||||
Sends an HTML response with status code.
|
||||
|
||||
### String
|
||||
|
||||
`Context#String(code int, s string) error`
|
||||
|
||||
Sends a string response with status code.
|
||||
|
||||
### File
|
||||
|
||||
`func (c *context) File(file string) error`
|
||||
|
||||
Sends a response with the content of the file.
|
||||
|
||||
### Attachment
|
||||
|
||||
`Context#Attachment(file string) error`
|
||||
|
||||
Sends a response as file attachment, prompting client to save the file.
|
||||
|
||||
### Static Files
|
||||
|
||||
`Echo#Use(middleware.Static(root string))`
|
||||
|
||||
Serves static files from the provided `root` directory.
|
||||
|
||||
`Echo#Static(prefix, root string)`
|
||||
|
||||
Serves files from provided `root` directory for `/<prefix>*` HTTP path.
|
||||
|
||||
`Echo#File(path, file string)`
|
||||
|
||||
Serves provided `file` for `/<path>` HTTP path.
|
||||
|
||||
*Examples*
|
||||
|
||||
- Serving static files with no prefix `e.Use(middleware.Static("public"))`
|
||||
- Serving static files with a prefix `e.Static("/static", "assets")`
|
||||
- Serving an index page `e.File("/", "public/index.html")`
|
||||
- Serving a favicon `e.File("/favicon.ico", "images/facicon.ico")`
|
@ -1,108 +0,0 @@
|
||||
---
|
||||
title: Routing
|
||||
menu:
|
||||
side:
|
||||
parent: guide
|
||||
weight: 4
|
||||
---
|
||||
|
||||
Echo's router is [fast, optimized]({{< relref "index.md#performance">}}) and
|
||||
flexible. It's based on [radix tree](http://en.wikipedia.org/wiki/Radix_tree) data
|
||||
structure which makes route lookup really fast. Router leverages [sync pool](https://golang.org/pkg/sync/#Pool)
|
||||
to reuse memory and achieve zero dynamic memory allocation with no GC overhead.
|
||||
|
||||
Routes can be registered by specifying HTTP method, path and a handler. For example,
|
||||
code below registers a route for method `GET`, path `/hello` and a handler which sends
|
||||
`Hello!` HTTP response.
|
||||
|
||||
```go
|
||||
e.Get("/hello", func(c echo.Context) error {
|
||||
return c.String(http.StatusOK, "Hello!")
|
||||
})
|
||||
```
|
||||
|
||||
You can use `Echo.Any(path string, h Handler)` to register a handler for all HTTP methods.
|
||||
If you want to register it for some methods use `Echo.Match(methods []string, path string, h Handler)`.
|
||||
|
||||
Echo defines handler function as `func(echo.Context) error` where `echo.Context` primarily
|
||||
holds HTTP request and response interfaces.
|
||||
|
||||
### Match-any
|
||||
|
||||
Matches zero or more characters in the path. For example, pattern `/users/*` will
|
||||
match:
|
||||
|
||||
- `/users/`
|
||||
- `/users/1`
|
||||
- `/users/1/files/1`
|
||||
- `/users/anything...`
|
||||
|
||||
### Path matching order
|
||||
|
||||
- Static
|
||||
- Param
|
||||
- Match any
|
||||
|
||||
#### Example
|
||||
|
||||
```go
|
||||
e.Get("/users/:id", func(c echo.Context) error {
|
||||
return c.String(http.StatusOK, "/users/:id")
|
||||
})
|
||||
|
||||
e.Get("/users/new", func(c echo.Context) error {
|
||||
return c.String(http.StatusOK, "/users/new")
|
||||
})
|
||||
|
||||
e.Get("/users/1/files/*", func(c echo.Context) error {
|
||||
return c.String(http.StatusOK, "/users/1/files/*")
|
||||
})
|
||||
```
|
||||
|
||||
Above routes would resolve in the following order:
|
||||
|
||||
- `/users/new`
|
||||
- `/users/:id`
|
||||
- `/users/1/files/*`
|
||||
|
||||
> Routes can be written in any order.
|
||||
|
||||
### Group
|
||||
|
||||
`Echo#Group(prefix string, m ...Middleware) *Group`
|
||||
|
||||
Routes with common prefix can be grouped to define a new sub-router with optional
|
||||
middleware. In addition to specified middleware group also inherits parent middleware.
|
||||
To add middleware later in the group you can use `Group.Use(m ...Middleware)`.
|
||||
Groups can also be nested.
|
||||
|
||||
In the code below, we create an admin group which requires basic HTTP authentication
|
||||
for routes `/admin/*`.
|
||||
|
||||
```go
|
||||
e.Group("/admin")
|
||||
e.Use(middleware.BasicAuth(func(username, password string) bool {
|
||||
if username == "joe" && password == "secret" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}))
|
||||
```
|
||||
|
||||
### URI building
|
||||
|
||||
`Echo.URI` can be used to generate URI for any handler with specified path parameters.
|
||||
It's helpful to centralize all your URI patterns which ease in refactoring your
|
||||
application.
|
||||
|
||||
`e.URI(h, 1)` will generate `/users/1` for the route registered below
|
||||
|
||||
```go
|
||||
// Handler
|
||||
h := func(c echo.Context) error {
|
||||
return c.String(http.StatusOK, "OK")
|
||||
}
|
||||
|
||||
// Route
|
||||
e.Get("/users/:id", h)
|
||||
```
|
@ -1,100 +0,0 @@
|
||||
---
|
||||
title: Index
|
||||
---
|
||||
|
||||
# ![Echo](/images/echo.svg) Echo
|
||||
|
||||
A fast and unfancy micro web framework for Go.
|
||||
|
||||
---
|
||||
|
||||
## Features
|
||||
|
||||
- Fast HTTP router which smartly prioritize routes.
|
||||
- Run with standard HTTP server or FastHTTP server.
|
||||
- Extensible middleware framework.
|
||||
- Router groups with nesting.
|
||||
- Handy functions to send variety of HTTP responses.
|
||||
- Centralized HTTP error handling.
|
||||
- Template rendering with any template engine.
|
||||
|
||||
## Performance
|
||||
|
||||
<iframe width="600" height="371" seamless frameborder="0" scrolling="no" src="https://docs.google.com/spreadsheets/d/1phsG_NPmEOaTVTw6lasK3CeEwBlbkhzAWPiyrBznm1g/pubchart?oid=178095723&format=interactive"></iframe>
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Installation
|
||||
|
||||
```sh
|
||||
$ go get github.com/labstack/echo
|
||||
```
|
||||
|
||||
### Hello, World!
|
||||
|
||||
Create `main.go`
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo"
|
||||
"github.com/labstack/echo/engine/standard"
|
||||
"github.com/labstack/echo/middleware"
|
||||
)
|
||||
|
||||
// Handler
|
||||
func hello() echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
return c.String(http.StatusOK, "Hello, World!\n")
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Echo instance
|
||||
e := echo.New()
|
||||
|
||||
// Middleware
|
||||
e.Use(middleware.Logger())
|
||||
e.Use(middleware.Recover())
|
||||
|
||||
// Routes
|
||||
e.Get("/", hello())
|
||||
|
||||
// Start server
|
||||
e.Run(standard.New(":1323"))
|
||||
}
|
||||
```
|
||||
|
||||
Start server
|
||||
|
||||
```sh
|
||||
$ go run main.go
|
||||
```
|
||||
|
||||
Browse to [http://localhost:1323](http://localhost:1323) and you should see
|
||||
Hello, World! on the page.
|
||||
|
||||
### Next?
|
||||
- Browse [recipes](/recipes/hello-world)
|
||||
- Head over to [guide](/guide/installation)
|
||||
|
||||
## Contribute
|
||||
|
||||
**Use issues for everything**
|
||||
|
||||
- Report issues
|
||||
- Discuss before sending pull request
|
||||
- Suggest new features
|
||||
- Improve/fix documentation
|
||||
|
||||
## Credits
|
||||
- [Vishal Rana](https://github.com/vishr) - Author
|
||||
- [Nitin Rana](https://github.com/nr17) - Consultant
|
||||
- [Contributors](https://github.com/labstack/echo/graphs/contributors)
|
||||
|
||||
## License
|
||||
|
||||
[MIT](https://github.com/labstack/echo/blob/master/LICENSE)
|
@ -1,19 +0,0 @@
|
||||
---
|
||||
title: CORS
|
||||
menu:
|
||||
side:
|
||||
parent: recipes
|
||||
weight: 3
|
||||
---
|
||||
|
||||
### Server
|
||||
|
||||
`main.go`
|
||||
|
||||
{{< embed "cors/main.go" >}}
|
||||
|
||||
### Maintainers
|
||||
|
||||
- [vishr](https://github.com/vishr)
|
||||
|
||||
### [Source Code]({{< source "cors" >}})
|
@ -1,19 +0,0 @@
|
||||
---
|
||||
title: CRUD
|
||||
menu:
|
||||
side:
|
||||
parent: recipes
|
||||
weight: 2
|
||||
---
|
||||
|
||||
### Server
|
||||
|
||||
`main.go`
|
||||
|
||||
{{< embed "crud/main.go" >}}
|
||||
|
||||
### Maintainers
|
||||
|
||||
- [vishr](https://github.com/vishr)
|
||||
|
||||
### [Source Code]({{< source "crud" >}})
|
@ -1,20 +0,0 @@
|
||||
---
|
||||
title: Embed Resources
|
||||
menu:
|
||||
side:
|
||||
identifier: "embed-resources"
|
||||
parent: recipes
|
||||
weight: 14
|
||||
---
|
||||
|
||||
### With go.rice
|
||||
|
||||
`main.go`
|
||||
|
||||
{{< embed "embed-resources/main.go" >}}
|
||||
|
||||
### Maintainers
|
||||
|
||||
- [caarlos0](https://github.com/caarlos0)
|
||||
|
||||
### [Source Code]({{< source "embed-resources" >}})
|
@ -1,53 +0,0 @@
|
||||
---
|
||||
title: File Upload
|
||||
menu:
|
||||
side:
|
||||
parent: recipes
|
||||
weight: 7
|
||||
---
|
||||
|
||||
- Multipart/form-data file upload
|
||||
- Multiple form fields and files
|
||||
|
||||
Use `req.ParseMultipartForm(16 << 20)` for manually parsing multipart form. It gives
|
||||
us an option to specify the maximum memory used while parsing the request body.
|
||||
|
||||
If you just want to upload a single file:
|
||||
|
||||
```go
|
||||
file, fh, err := req.FormFile("file")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// Destination
|
||||
dst, err := os.Create(fh.Filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer dst.Close()
|
||||
|
||||
// Copy
|
||||
if _, err = io.Copy(dst, file); err != nil {
|
||||
return err
|
||||
}
|
||||
```
|
||||
|
||||
### Server
|
||||
|
||||
`main.go`
|
||||
|
||||
{{< embed "file-upload/main.go" >}}
|
||||
|
||||
### Client
|
||||
|
||||
`index.html`
|
||||
|
||||
{{< embed "file-upload/public/index.html" >}}
|
||||
|
||||
### Maintainers
|
||||
|
||||
- [vishr](https://github.com/vishr)
|
||||
|
||||
### [Source Code]({{< source "file-upload" >}})
|
@ -1,135 +0,0 @@
|
||||
---
|
||||
title: Google App Engine
|
||||
menu:
|
||||
side:
|
||||
parent: recipes
|
||||
weight: 12
|
||||
---
|
||||
|
||||
Google App Engine (GAE) provides a range of hosting options from pure PaaS (App Engine Classic)
|
||||
through Managed VMs to fully self-managed or container-driven Compute Engine instances. Echo
|
||||
works great with all of these but requires a few changes to the usual examples to run on the
|
||||
AppEngine Classic and Managed VM options. With a small amount of effort though it's possible
|
||||
to produce a codebase that will run on these and also non-managed platforms automatically.
|
||||
|
||||
We'll walk through the changes needed to support each option.
|
||||
|
||||
### Standalone
|
||||
|
||||
Wait? What? I thought this was about AppEngine! Bear with me - the easiest way to show the changes
|
||||
required is to start with a setup for standalone and work from there plus there's no reason we
|
||||
wouldn't want to retain the ability to run our app anywhere, right?
|
||||
|
||||
We take advantage of the go [build constraints or tags](http://golang.org/pkg/go/build/) to change
|
||||
how we create and run the Echo server for each platform while keeping the rest of the application
|
||||
(e.g. handler wireup) the same across all of them.
|
||||
|
||||
First, we have the normal setup based on the examples but we split it into two files - `app.go` will
|
||||
be common to all variations and holds the Echo instance variable. We initialise it from a function
|
||||
and because it is a `var` this will happen _before_ any `init()` functions run - a feature that we'll
|
||||
use to connect our handlers later.
|
||||
|
||||
`app.go`
|
||||
|
||||
{{< embed "google-app-engine/app.go" >}}
|
||||
|
||||
A separate source file contains the function to create the Echo instance and add the static
|
||||
file handlers and middleware. Note the build tag on the first line which says to use this when _not_
|
||||
bulding with appengine or appenginevm tags (which thoese platforms automatically add for us). We also
|
||||
have the `main()` function to start serving our app as normal. This should all be very familiar.
|
||||
|
||||
`app-standalone.go`
|
||||
|
||||
{{< embed "google-app-engine/app-standalone.go" >}}
|
||||
|
||||
The handler-wireup that would normally also be a part of this Echo setup moves to separate files which
|
||||
take advantage of the ability to have multiple `init()` functions which run _after_ the `e` Echo var is
|
||||
initialised but _before_ the `main()` function is executed. These allow additional handlers to attach
|
||||
themselves to the instance - I've found the `Group` feature naturally fits into this pattern with a file
|
||||
per REST endpoint, often with a higher-level `api` group created that they attach to instead of the root
|
||||
Echo instance directly (so things like CORS middleware can be added at this higher common-level).
|
||||
|
||||
`users.go`
|
||||
|
||||
{{< embed "google-app-engine/users.go" >}}
|
||||
|
||||
If we run our app it should execute as it did before when everything was in one file although we have
|
||||
at least gained the ability to organize our handlers a little more cleanly.
|
||||
|
||||
### AppEngine Classic and Managed VMs
|
||||
|
||||
So far we've seen how to split apart the Echo creation and setup but still have the same app that
|
||||
still only runs standalone. Now we'll see hwo those changes allow us to add support for AppEngine
|
||||
hosting.
|
||||
|
||||
Refer to the [AppEngine site](https://cloud.google.com/appengine/docs/go/) for full configuration
|
||||
and deployment information.
|
||||
|
||||
#### app.yaml configuration file
|
||||
|
||||
Both of these are Platform as as Service options running on either sandboxed micro-containers
|
||||
or managed Compute Engine instances. Both require an `app.yaml` file to describe the app to
|
||||
the service. While the app _could_ still serve all it's static files itself, one of the benefits
|
||||
of the platform is having Google's infrastructure handle that for us so it can be offloaded and
|
||||
the app only has to deal with dynamic requests. The platform also handles logging and http gzip
|
||||
compression so these can be removed from the codebase as well.
|
||||
|
||||
The yaml file also contains other options to control instance size and auto-scaling so for true
|
||||
deployment freedom you would likely have separate `app-classic.yaml` and `app-vm.yaml` files and
|
||||
this can help when making the transition from AppEngine Classic to Managed VMs.
|
||||
|
||||
`app-engine.yaml`
|
||||
|
||||
{{< embed "google-app-engine/app-engine.yaml" >}}
|
||||
|
||||
#### Router configuration
|
||||
|
||||
We'll now use the [build constraints](http://golang.org/pkg/go/build/) again like we did when creating
|
||||
our `app-standalone.go` instance but this time with the opposite tags to use this file _if_ the build has
|
||||
the appengine or appenginevm tags (added automatically when deploying to these platforms).
|
||||
|
||||
This allows us to replace the `createMux()` function to create our Echo server _without_ any of the
|
||||
static file handling and logging + gzip middleware which is no longer required. Also worth nothing is
|
||||
that GAE classic provides a wrapper to handle serving the app so instead of a `main()` function where
|
||||
we run the server, we instead wire up the router to the default `http.Handler` instead.
|
||||
|
||||
`app-engine.go`
|
||||
|
||||
{{< embed "google-app-engine/app-engine.go" >}}
|
||||
|
||||
Managed VMs are slightly different. They are expected to respond to requests on port 8080 as well
|
||||
as special health-check requests used by the service to detect if an instance is still running in
|
||||
order to provide automated failover and instance replacement. The `google.golang.org/appengine`
|
||||
package provides this for us so we have a slightly different version for Managed VMs:
|
||||
|
||||
`app-managed.go`
|
||||
|
||||
{{< embed "google-app-engine/app-managed.go" >}}
|
||||
|
||||
So now we have three different configurations. We can build and run our app as normal so it can
|
||||
be executed locally, on a full Compute Engine instance or any other traditional hosting provider
|
||||
(including EC2, Docker etc...). This build will ignore the code in appengine and appenginevm tagged
|
||||
files and the `app.yaml` file is meaningless to anything other than the AppEngine platform.
|
||||
|
||||
We can also run locally using the [Google AppEngine SDK for Go](https://cloud.google.com/appengine/downloads)
|
||||
either emulating [AppEngine Classic](https://cloud.google.com/appengine/docs/go/tools/devserver):
|
||||
|
||||
goapp serve
|
||||
|
||||
Or [Managed VMs](https://cloud.google.com/appengine/docs/managed-vms/sdk#run-local):
|
||||
|
||||
gcloud config set project [your project id]
|
||||
gcloud preview app run .
|
||||
|
||||
And of course we can deploy our app to both of these platforms for easy and inexpensive auto-scaling joy.
|
||||
|
||||
Depending on what your app actually does it's possible you may need to make other changes to allow
|
||||
switching between AppEngine provided service such as Datastore and alternative storage implementations
|
||||
such as MongoDB. A combination of go interfaces and build constraints can make this fairly straightforward
|
||||
but is outside the scope of this recipe.
|
||||
|
||||
### Maintainers
|
||||
|
||||
- [CaptainCodeman](https://github.com/CaptainCodeman)
|
||||
|
||||
### [Source Code]({{< source "google-app-engine" >}})
|
@ -1,28 +0,0 @@
|
||||
---
|
||||
title: Graceful Shutdown
|
||||
menu:
|
||||
side:
|
||||
parent: recipes
|
||||
weight: 13
|
||||
---
|
||||
|
||||
### With [grace](https://github.com/facebookgo/grace)
|
||||
|
||||
`main.go`
|
||||
|
||||
{{< embed "graceful-shutdown/grace/main.go" >}}
|
||||
|
||||
### With [graceful](https://github.com/tylerb/graceful)
|
||||
|
||||
`main.go`
|
||||
|
||||
{{< embed "graceful-shutdown/graceful/main.go" >}}
|
||||
|
||||
### Maintainers
|
||||
|
||||
- [mertenvg](https://github.com/mertenvg)
|
||||
|
||||
### Source Code
|
||||
|
||||
- [graceful]({{< source "graceful-shutdown/graceful" >}})
|
||||
- [grace]({{< source "graceful-shutdown/grace" >}})
|
@ -1,19 +0,0 @@
|
||||
---
|
||||
title: Hello World
|
||||
menu:
|
||||
side:
|
||||
parent: recipes
|
||||
weight: 1
|
||||
---
|
||||
|
||||
### Server
|
||||
|
||||
`main.go`
|
||||
|
||||
{{< embed "hello-world/main.go" >}}
|
||||
|
||||
### Maintainers
|
||||
|
||||
- [vishr](https://github.com/vishr)
|
||||
|
||||
### [Source Code]({{< source "hello-world" >}})
|
@ -1,27 +0,0 @@
|
||||
---
|
||||
title: JSONP
|
||||
menu:
|
||||
side:
|
||||
parent: recipes
|
||||
weight: 6
|
||||
---
|
||||
|
||||
JSONP is a method that allows cross-domain server calls. You can read more about it at the JSON versus JSONP Tutorial.
|
||||
|
||||
### Server
|
||||
|
||||
`main.go`
|
||||
|
||||
{{< embed "jsonp/main.go" >}}
|
||||
|
||||
### Client
|
||||
|
||||
`index.html`
|
||||
|
||||
{{< embed "jsonp/public/index.html" >}}
|
||||
|
||||
### Maintainers
|
||||
|
||||
- [willf](https://github.com/willf)
|
||||
|
||||
### [Source Code]({{< source "jsonp" >}})
|
@ -1,58 +0,0 @@
|
||||
---
|
||||
title: JWT Authentication
|
||||
menu:
|
||||
side:
|
||||
parent: recipes
|
||||
weight: 11
|
||||
---
|
||||
|
||||
Most applications dealing with client authentication will require a more secure
|
||||
mechanism than that provided by [basic authentication](https://github.com/labstack/echo/blob/master/middleware/auth.go). [JSON Web Tokens](http://jwt.io/)
|
||||
are one such mechanism - JWTs are a compact means of transferring cryptographically
|
||||
signed claims between the client and server.
|
||||
|
||||
This recipe demonstrates the use of a simple JWT authentication Echo middleware
|
||||
using Dave Grijalva's [jwt-go](https://github.com/dgrijalva/jwt-go). This middleware
|
||||
expects the token to be present in an Authorization HTTP header using the method
|
||||
"Bearer", although JWTs are also frequently sent using cookies, the request URL,
|
||||
or even the request body. We will use the HS236 signing method, note that several
|
||||
other algorithms are available.
|
||||
|
||||
`main.go`
|
||||
|
||||
{{< embed "jwt-authentication/main.go" >}}
|
||||
|
||||
Run `main.go` and making a request to the root path `/` returns a 200 OK response,
|
||||
as this route does not use our JWT authentication middleware. Sending requests to
|
||||
`/restricted` (our authenticated route) with either no Authorization header or invalid
|
||||
Authorization headers / tokens will return 401 Unauthorized.
|
||||
|
||||
```sh
|
||||
# Unauthenticated route
|
||||
$ curl localhost:1323/ => No auth required for this route.
|
||||
|
||||
# No Authentication header
|
||||
$ curl localhost:1323/restricted => Unauthorized
|
||||
|
||||
# Invalid Authentication method
|
||||
$ curl localhost:1323/restricted -H "Authorization: Invalid " => Unauthorized
|
||||
|
||||
# Invalid token
|
||||
$ curl localhost:1323/restricted -H "Authorization: Bearer InvalidToken" => Unauthorized
|
||||
```
|
||||
|
||||
Running `token.go` (source) will print JWT that is valid against this middleware
|
||||
to stdout. You can use this token to test succesful authentication on the `/restricted` path.
|
||||
|
||||
{{< embed "jwt-authentication/token/token.go" >}}
|
||||
|
||||
```sh
|
||||
# Valid token
|
||||
$ curl localhost:1323/restricted -H "Authorization: Bearer <token>" => Access granted with JWT.
|
||||
```
|
||||
|
||||
### Maintainers
|
||||
|
||||
- [axdg](https://github.com/axdg)
|
||||
|
||||
### [Source Code]({{< source "jwt-authentication" >}})
|
@ -1,20 +0,0 @@
|
||||
---
|
||||
title: Middleware
|
||||
menu:
|
||||
side:
|
||||
identifier: "recipe-miiddleware"
|
||||
parent: recipes
|
||||
weight: 3
|
||||
---
|
||||
|
||||
### Server
|
||||
|
||||
`main.go`
|
||||
|
||||
{{< embed "middleware/main.go" >}}
|
||||
|
||||
### Maintainers
|
||||
|
||||
- [vishr](https://github.com/vishr)
|
||||
|
||||
### [Source Code]({{< source "middleware" >}})
|
@ -1,28 +0,0 @@
|
||||
---
|
||||
title: Streaming File Upload
|
||||
menu:
|
||||
side:
|
||||
parent: recipes
|
||||
weight: 8
|
||||
---
|
||||
|
||||
- Streaming multipart/form-data file upload
|
||||
- Multiple form fields and files
|
||||
|
||||
### Server
|
||||
|
||||
`main.go`
|
||||
|
||||
{{< embed "streaming-file-upload/main.go" >}}
|
||||
|
||||
### Client
|
||||
|
||||
`index.html`
|
||||
|
||||
{{< embed "streaming-file-upload/public/index.html" >}}
|
||||
|
||||
### Maintainers
|
||||
|
||||
- [vishr](https://github.com/vishr)
|
||||
|
||||
### [Source Code]({{< source "streaming-file-upload" >}})
|
@ -1,38 +0,0 @@
|
||||
---
|
||||
title: Streaming Response
|
||||
menu:
|
||||
side:
|
||||
parent: recipes
|
||||
weight: 9
|
||||
---
|
||||
|
||||
- Send data as it is produced
|
||||
- Streaming JSON response with chunked transfer encoding
|
||||
|
||||
### Server
|
||||
|
||||
`main.go`
|
||||
|
||||
{{< embed "streaming-response/main.go" >}}
|
||||
|
||||
### Client
|
||||
|
||||
```sh
|
||||
$ curl localhost:1323
|
||||
```
|
||||
|
||||
## Output
|
||||
|
||||
```sh
|
||||
{"Altitude":-97,"Latitude":37.819929,"Longitude":-122.478255}
|
||||
{"Altitude":1899,"Latitude":39.096849,"Longitude":-120.032351}
|
||||
{"Altitude":2619,"Latitude":37.865101,"Longitude":-119.538329}
|
||||
{"Altitude":42,"Latitude":33.812092,"Longitude":-117.918974}
|
||||
{"Altitude":15,"Latitude":37.77493,"Longitude":-122.419416}
|
||||
```
|
||||
|
||||
### Maintainers
|
||||
|
||||
- [vishr](https://github.com/vishr)
|
||||
|
||||
### [Source Code]({{< source "streaming-response" >}})
|
@ -1,18 +0,0 @@
|
||||
---
|
||||
title: Subdomains
|
||||
menu:
|
||||
side:
|
||||
parent: recipes
|
||||
weight: 10
|
||||
---
|
||||
|
||||
`main.go`
|
||||
|
||||
{{< embed "subdomains/main.go" >}}
|
||||
|
||||
### Maintainers
|
||||
|
||||
- [axdg](https://github.com/axdg)
|
||||
- [vishr](https://github.com/vishr)
|
||||
|
||||
### [Source Code]({{< source "subdomains" >}})
|
@ -1,26 +0,0 @@
|
||||
---
|
||||
title: Website
|
||||
draft: true
|
||||
menu:
|
||||
side:
|
||||
parent: recipes
|
||||
weight: 4
|
||||
---
|
||||
|
||||
### Server
|
||||
|
||||
`server.go`
|
||||
|
||||
{{< embed "website/main.go" >}}
|
||||
|
||||
### Client
|
||||
|
||||
`index.html`
|
||||
|
||||
{{< embed "website/public/index.html" >}}
|
||||
|
||||
### Maintainers
|
||||
|
||||
- [vishr](https://github.com/vishr)
|
||||
|
||||
### [Source Code]({{< source "website" >}})
|
@ -1,47 +0,0 @@
|
||||
---
|
||||
title: WebSocket
|
||||
menu:
|
||||
side:
|
||||
parent: recipes
|
||||
weight: 5
|
||||
---
|
||||
|
||||
### Server
|
||||
|
||||
`server.go`
|
||||
|
||||
{{< embed "websocket/main.go" >}}
|
||||
|
||||
### Client
|
||||
|
||||
`index.html`
|
||||
|
||||
{{< embed "websocket/public/index.html" >}}
|
||||
|
||||
### Output
|
||||
|
||||
`Client`
|
||||
|
||||
```sh
|
||||
Hello, Client!
|
||||
Hello, Client!
|
||||
Hello, Client!
|
||||
Hello, Client!
|
||||
Hello, Client!
|
||||
```
|
||||
|
||||
`Server`
|
||||
|
||||
```sh
|
||||
Hello, Server!
|
||||
Hello, Server!
|
||||
Hello, Server!
|
||||
Hello, Server!
|
||||
Hello, Server!
|
||||
```
|
||||
|
||||
### Maintainers
|
||||
|
||||
- [vishr](https://github.com/vishr)
|
||||
|
||||
### [Source Code]({{< source "websocket" >}})
|
@ -1,45 +0,0 @@
|
||||
{{ partial "head.html" . }}
|
||||
<body>
|
||||
{{ . }}
|
||||
<div class="mdl-layout mdl-js-layout mdl-layout--fixed-header">
|
||||
{{ partial "header.html" . }}
|
||||
<main class="mdl-layout__content">
|
||||
<div class="page-content single">
|
||||
<div class="mdl-grid">
|
||||
<div class="mdl-cell mdl-cell--3-col">
|
||||
{{ partial "menu.html" . }}
|
||||
</div>
|
||||
<div class="mdl-cell mdl-cell--9-col">
|
||||
<article>
|
||||
<header>
|
||||
<h2>{{ .Title }}</h2>
|
||||
</header>
|
||||
<section class="content">
|
||||
{{ .Content }}
|
||||
</section>
|
||||
<footer style="margin-top: 80px;">
|
||||
<div id="disqus_thread"></div>
|
||||
<script type="text/javascript">
|
||||
/* * * CONFIGURATION VARIABLES * * */
|
||||
var disqus_shortname = 'labstack';
|
||||
|
||||
/* * * DON'T EDIT BELOW THIS LINE * * */
|
||||
(function() {
|
||||
var dsq = document.createElement('script');
|
||||
dsq.type = 'text/javascript';
|
||||
dsq.async = true;
|
||||
dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js';
|
||||
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
|
||||
})();
|
||||
</script>
|
||||
</footer>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ partial "footer.html" . }}
|
||||
</main>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -1,24 +0,0 @@
|
||||
{{ partial "head.html" . }}
|
||||
|
||||
<body>
|
||||
<div class="mdl-layout mdl-js-layout mdl-layout--fixed-header">
|
||||
{{ partial "header.html" . }}
|
||||
<main class="mdl-layout__content">
|
||||
<div class="page-content">
|
||||
<div class="mdl-grid">
|
||||
<div class="mdl-cell mdl-cell--3-col">
|
||||
{{ partial "menu.html" . }}
|
||||
</div>
|
||||
<div class="mdl-cell mdl-cell--9-col">
|
||||
{{ range where .Data.Pages "Title" "Index" }}
|
||||
{{ .Content }}
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ partial "footer.html" . }}
|
||||
</main>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -1,49 +0,0 @@
|
||||
<footer class="mdl-mini-footer">
|
||||
<div class="mdl-mini-footer__left-section">
|
||||
<span class="mdl-typography__font-light">© 2015 LabStack</span>
|
||||
</div>
|
||||
<div class="mdl-mini-footer__right-section">
|
||||
<ul class="mdl-mini-footer__link-list">
|
||||
<li class="github">
|
||||
<a href="https://github.com/labstack" target="_blank">
|
||||
<i class="fa fa-github fa-2x"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li class="facebook">
|
||||
<a href="https://facebook.com/labstack" target="_blank">
|
||||
<i class="fa fa-facebook fa-2x"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li class="twitter">
|
||||
<a href="https://twitter.com/labstack" target="_blank">
|
||||
<i class="fa fa-twitter-square fa-2x"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li class="google">
|
||||
<a href="https://plus.google.com/+labstack" target="_blank">
|
||||
<i class="fa fa-google-plus-square fa-2x"></i>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</footer>
|
||||
<!-- <script src="/scripts/highlight.pack.min.js"></script> -->
|
||||
<script src="/scripts/prism.js"></script>
|
||||
<script src="/scripts/echo.js"></script>
|
||||
<!-- <script>hljs.initHighlightingOnLoad();</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', '//www.google-analytics.com/analytics.js', 'ga');
|
||||
|
||||
ga('create', '{{ .Site.Params.googleAnayticsId }}', 'auto');
|
||||
ga('send', 'pageview');
|
||||
</script>
|
@ -1,23 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="{{ .Site.LanguageCode }}">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<title>
|
||||
{{ .Site.Title }} - {{ .Site.Params.description }}{{ if ne .URL "/" }} - {{ .Title }} {{ end }}
|
||||
</title>
|
||||
<meta name="description" content="{{ .Site.Params.description }}">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<!-- <link rel="apple-touch-icon" href="apple-touch-icon.png"> -->
|
||||
<!-- Place favicon.ico in the root directory -->
|
||||
<link rel="stylesheet" href="//storage.googleapis.com/code.getmdl.io/1.0.5/material.blue-pink.min.css">
|
||||
<link rel="stylesheet" href="//fonts.googleapis.com/icon?family=Material+Icons">
|
||||
<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Roboto:300,400,500,700">
|
||||
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">
|
||||
<!-- <link rel="stylesheet" href="/styles/monokai.css"> -->
|
||||
<link rel="stylesheet" href="/styles/prism.css">
|
||||
<link rel="stylesheet" href="/styles/echo.css">
|
||||
<script src="//storage.googleapis.com/code.getmdl.io/1.0.5/material.min.js"></script>
|
||||
</head>
|
@ -1,17 +0,0 @@
|
||||
<header class="mdl-layout__header">
|
||||
<div class="mdl-layout__header-row">
|
||||
<a href="{{ .Site.BaseURL }}" class="mdl-navigation__link mdl-layout-title">
|
||||
<img src="/images/logo.svg" alt="LabStack">
|
||||
</a>
|
||||
<div class="mdl-layout-spacer"></div>
|
||||
<nav class="mdl-navigation mdl-layout--large-screen-only">
|
||||
<a href="https://github.com/labstack/echo" class="mdl-navigation__link">
|
||||
<i class="fa fa-github fa-2x"></i>
|
||||
</a>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
<div style="padding: 4px; text-align: center; background: #ff851b; color: #fff;">
|
||||
This is Echo v2 website. If you are looking for v1 docs, they can be found <a style=
|
||||
"color: #fff;" href="https://github.com/labstack/echo/tree/v1/website/content"><b>here</b>.</a>
|
||||
</div>
|
@ -1,17 +0,0 @@
|
||||
<aside class="menu">
|
||||
<div>
|
||||
{{ range .Site.Menus.side }}
|
||||
{{ if .HasChildren }}
|
||||
<h4>
|
||||
{{ .Pre }}
|
||||
{{ .Name }}
|
||||
</h4>
|
||||
{{ range .Children }}
|
||||
<a href="{{ .URL }}">
|
||||
{{ .Name }}
|
||||
</a>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
</div>
|
||||
</aside>
|
@ -1,14 +0,0 @@
|
||||
<span class="share">
|
||||
<a href="https://www.facebook.com/sharer/sharer.php?u={{ .Permalink }}" target="_blank">
|
||||
<i class="fa fa-facebook-square fa-2x"></i>
|
||||
</a>
|
||||
<a href="http://twitter.com/share?text={{ .Title }}&url={{ .Permalink }}" target="_blank">
|
||||
<i class="fa fa-twitter-square fa-2x"></i>
|
||||
</a>
|
||||
<a href="https://plus.google.com/share?url={{ .Permalink }}" target="_blank">
|
||||
<i class="fa fa-google-plus-square fa-2x"></i>
|
||||
</a>
|
||||
<a class="ui reddit icon button" href="http://www.reddit.com/submit?url={{ .Permalink }}&title={{ .Title }}" target="_blank">
|
||||
<i class="fa fa-reddit-square fa-2x"></i>
|
||||
</a>
|
||||
</span>
|
@ -1,2 +0,0 @@
|
||||
<pre data-src="https://raw.githubusercontent.com/labstack/echox/master/recipe/{{ .Get 0 }}">
|
||||
</pre>
|
@ -1 +0,0 @@
|
||||
https://github.com/labstack/echox/tree/master/recipe/{{ .Get 0 }}
|
@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="46px" height="46px" viewBox="0 0 46 46" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
|
||||
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
|
||||
<g sketch:type="MSArtboardGroup" transform="translate(-639.000000, -1341.000000)">
|
||||
<g sketch:type="MSLayerGroup" transform="translate(133.000000, 1155.000000)">
|
||||
<g id="Aim" transform="translate(507.000000, 187.000000)" sketch:type="MSShapeGroup">
|
||||
<g id="Main">
|
||||
<circle id="Oval-88" stroke="#2196f3" stroke-width="2" cx="22" cy="22" r="22"></circle>
|
||||
<circle id="Oval-89" stroke="#2196f3" stroke-width="2" cx="22" cy="22" r="15.3043478"></circle>
|
||||
<circle id="Oval-90" stroke="#2196f3" stroke-width="2" cx="22" cy="22" r="8.60869565"></circle>
|
||||
<circle id="Oval-91" fill="#2196f3" cx="22" cy="22" r="1.91304348"></circle>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.2 KiB |
@ -1 +0,0 @@
|
||||
<svg width="127" height="19" viewBox="0 0 127 19" xmlns="http://www.w3.org/2000/svg"><title>LabStack</title><path d="M16.242 19H2.344c-.22 0-.422-.04-.61-.117a1.49 1.49 0 0 1-.486-.322 1.49 1.49 0 0 1-.322-.486 1.568 1.568 0 0 1-.117-.61V2.195h3.045v13.76h12.387V19zm14.977-4.195c0 .422-.075.877-.224 1.365a4.08 4.08 0 0 1-.72 1.36 4.018 4.018 0 0 1-1.3 1.048c-.537.28-1.187.422-1.953.422h-5.496a4.71 4.71 0 0 1-1.365-.223 4.08 4.08 0 0 1-1.36-.72 4.018 4.018 0 0 1-1.048-1.3c-.28-.536-.422-1.187-.422-1.952 0-.422.074-.88.223-1.37a4.07 4.07 0 0 1 .72-1.367 4.018 4.018 0 0 1 1.3-1.048c.536-.282 1.187-.422 1.952-.422h5.496v2.906h-5.496c-.414 0-.734.127-.96.38-.227.255-.34.57-.34.944 0 .4.13.71.392.932.26.222.57.334.93.334h5.473c.415 0 .735-.125.96-.375.228-.25.34-.564.34-.94v-4.253c0-.398-.122-.714-.368-.95-.246-.233-.557-.35-.932-.35h-6.69V6.332h6.69c.422 0 .877.074 1.366.223.487.148.94.388 1.358.72.418.332.768.766 1.05 1.3.28.536.42 1.187.42 1.952v4.278zm16.57-.082a4.696 4.696 0 0 1-.41 1.87c-.142.315-.323.618-.546.907-.223.29-.492.545-.81.768-.315.222-.68.4-1.094.533-.414.134-.883.2-1.407.2h-5.496a4.696 4.696 0 0 1-1.87-.41 4.445 4.445 0 0 1-.907-.545 3.697 3.697 0 0 1-.768-.81 4.01 4.01 0 0 1-.533-1.1c-.134-.418-.2-.89-.2-1.412V.977h3.047v13.746c0 .375.117.673.35.896.236.222.53.333.88.333h5.496c.383 0 .682-.113.897-.34.215-.226.322-.523.322-.89v-4.125c0-.383-.113-.682-.34-.897-.226-.214-.52-.32-.88-.32h-5.495V6.33h5.496a4.696 4.696 0 0 1 1.87.41c.316.14.62.322.908.545.29.223.544.492.763.81.218.315.394.68.527 1.094.133.415.2.884.2 1.408v4.125zm19.09-.668a5.36 5.36 0 0 1-.23 1.623c-.152.48-.353.904-.603 1.27a4.03 4.03 0 0 1-.88.94 5.39 5.39 0 0 1-1.042.632c-.36.164-.725.285-1.096.363-.372.078-.72.117-1.05.117H50.227v-3.047H61.98c.586 0 1.04-.172 1.366-.515.324-.344.486-.805.486-1.383 0-.282-.043-.54-.13-.774a1.783 1.783 0 0 0-.368-.608 1.626 1.626 0 0 0-.586-.4 2.02 2.02 0 0 0-.768-.14h-7.007a5.43 5.43 0 0 1-1.594-.263 4.78 4.78 0 0 1-1.59-.85c-.487-.39-.894-.903-1.218-1.536-.324-.632-.486-1.406-.486-2.32 0-.914.162-1.685.486-2.314.324-.63.73-1.14 1.22-1.536a4.727 4.727 0 0 1 1.587-.855 5.43 5.43 0 0 1 1.593-.265h10.37v3.047h-10.37c-.578 0-1.03.176-1.354.528-.325.35-.487.816-.487 1.394 0 .586.162 1.05.486 1.39.323.34.775.508 1.353.508h7.031a5.38 5.38 0 0 1 2.14.516c.362.172.708.39 1.036.65.328.262.62.577.873.944.254.367.455.79.603 1.265.15.477.223 1.016.223 1.618zM80.05 9.38h-5.32V19h-3.082V9.38h-3.96V6.33h3.96V2.195h3.082v4.137h5.32V9.38zm14.356 5.425c0 .422-.074.877-.222 1.365a4.08 4.08 0 0 1-.72 1.36 4.018 4.018 0 0 1-1.302 1.048c-.535.28-1.185.422-1.95.422h-5.497a4.71 4.71 0 0 1-1.365-.223 4.08 4.08 0 0 1-1.36-.72 4.018 4.018 0 0 1-1.05-1.3c-.28-.536-.42-1.187-.42-1.952 0-.422.074-.88.222-1.37a4.07 4.07 0 0 1 .72-1.367 4.018 4.018 0 0 1 1.302-1.048c.535-.282 1.185-.422 1.95-.422h5.497v2.906h-5.495c-.414 0-.735.127-.96.38-.228.255-.34.57-.34.944 0 .4.13.71.392.932.26.222.572.334.93.334h5.474c.415 0 .735-.125.962-.375.226-.25.34-.564.34-.94v-4.253c0-.398-.123-.714-.37-.95-.246-.233-.556-.35-.93-.35H83.52V6.332h6.69c.423 0 .878.074 1.366.223.488.148.942.388 1.36.72.418.332.767.766 1.048 1.3.282.536.422 1.187.422 1.952v4.278zM109.276 19h-8.26c-.422 0-.883-.074-1.383-.223a4.067 4.067 0 0 1-1.39-.732c-.425-.34-.78-.78-1.065-1.324-.285-.542-.428-1.208-.428-1.997v-4.125a4.696 4.696 0 0 1 .41-1.87c.14-.316.322-.62.545-.908.223-.29.492-.543.81-.76.315-.22.68-.396 1.094-.53.413-.132.882-.198 1.406-.198h8.26V9.38h-8.26c-.4 0-.702.1-.91.304-.206.203-.31.515-.31.937v4.103c0 .398.106.703.317.914.21.21.52.316.926.316h8.237V19zm17.404 0h-4.395l-6.14-5.93a1.415 1.415 0 0 1-.48-1.172 1.59 1.59 0 0 1 .17-.615c.097-.19.23-.353.403-.486l5.567-4.488h4.875l-7.172 5.776L126.68 19zm-11.79 0h-3.046V.977h3.047V19z" fill="#FFF" fill-rule="evenodd"/></svg>
|
Before Width: | Height: | Size: 3.7 KiB |
@ -1,10 +0,0 @@
|
||||
(function() {
|
||||
var menu = document.querySelectorAll('.menu a');
|
||||
|
||||
for (var i = 0; i < menu.length; i++) {
|
||||
var m = menu[i];
|
||||
if (location.href === m.href) {
|
||||
m.className += 'active';
|
||||
}
|
||||
}
|
||||
})();
|
@ -1,8 +0,0 @@
|
||||
/* http://prismjs.com/download.html?themes=prism-coy&languages=markup+css+clike+javascript+go&plugins=file-highlight */
|
||||
var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(){var e=/\blang(?:uage)?-(?!\*)(\w+)\b/i,t=_self.Prism={util:{encode:function(e){return e instanceof n?new n(e.type,t.util.encode(e.content),e.alias):"Array"===t.util.type(e)?e.map(t.util.encode):e.replace(/&/g,"&").replace(/</g,"<").replace(/\u00a0/g," ")},type:function(e){return Object.prototype.toString.call(e).match(/\[object (\w+)\]/)[1]},clone:function(e){var n=t.util.type(e);switch(n){case"Object":var a={};for(var r in e)e.hasOwnProperty(r)&&(a[r]=t.util.clone(e[r]));return a;case"Array":return e.map&&e.map(function(e){return t.util.clone(e)})}return e}},languages:{extend:function(e,n){var a=t.util.clone(t.languages[e]);for(var r in n)a[r]=n[r];return a},insertBefore:function(e,n,a,r){r=r||t.languages;var l=r[e];if(2==arguments.length){a=arguments[1];for(var i in a)a.hasOwnProperty(i)&&(l[i]=a[i]);return l}var o={};for(var s in l)if(l.hasOwnProperty(s)){if(s==n)for(var i in a)a.hasOwnProperty(i)&&(o[i]=a[i]);o[s]=l[s]}return t.languages.DFS(t.languages,function(t,n){n===r[e]&&t!=e&&(this[t]=o)}),r[e]=o},DFS:function(e,n,a){for(var r in e)e.hasOwnProperty(r)&&(n.call(e,r,e[r],a||r),"Object"===t.util.type(e[r])?t.languages.DFS(e[r],n):"Array"===t.util.type(e[r])&&t.languages.DFS(e[r],n,r))}},plugins:{},highlightAll:function(e,n){for(var a,r=document.querySelectorAll('code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'),l=0;a=r[l++];)t.highlightElement(a,e===!0,n)},highlightElement:function(n,a,r){for(var l,i,o=n;o&&!e.test(o.className);)o=o.parentNode;o&&(l=(o.className.match(e)||[,""])[1],i=t.languages[l]),n.className=n.className.replace(e,"").replace(/\s+/g," ")+" language-"+l,o=n.parentNode,/pre/i.test(o.nodeName)&&(o.className=o.className.replace(e,"").replace(/\s+/g," ")+" language-"+l);var s=n.textContent,u={element:n,language:l,grammar:i,code:s};if(!s||!i)return t.hooks.run("complete",u),void 0;if(t.hooks.run("before-highlight",u),a&&_self.Worker){var g=new Worker(t.filename);g.onmessage=function(e){u.highlightedCode=e.data,t.hooks.run("before-insert",u),u.element.innerHTML=u.highlightedCode,r&&r.call(u.element),t.hooks.run("after-highlight",u),t.hooks.run("complete",u)},g.postMessage(JSON.stringify({language:u.language,code:u.code,immediateClose:!0}))}else u.highlightedCode=t.highlight(u.code,u.grammar,u.language),t.hooks.run("before-insert",u),u.element.innerHTML=u.highlightedCode,r&&r.call(n),t.hooks.run("after-highlight",u),t.hooks.run("complete",u)},highlight:function(e,a,r){var l=t.tokenize(e,a);return n.stringify(t.util.encode(l),r)},tokenize:function(e,n){var a=t.Token,r=[e],l=n.rest;if(l){for(var i in l)n[i]=l[i];delete n.rest}e:for(var i in n)if(n.hasOwnProperty(i)&&n[i]){var o=n[i];o="Array"===t.util.type(o)?o:[o];for(var s=0;s<o.length;++s){var u=o[s],g=u.inside,c=!!u.lookbehind,f=0,h=u.alias;u=u.pattern||u;for(var p=0;p<r.length;p++){var d=r[p];if(r.length>e.length)break e;if(!(d instanceof a)){u.lastIndex=0;var m=u.exec(d);if(m){c&&(f=m[1].length);var y=m.index-1+f,m=m[0].slice(f),v=m.length,k=y+v,b=d.slice(0,y+1),w=d.slice(k+1),P=[p,1];b&&P.push(b);var A=new a(i,g?t.tokenize(m,g):m,h);P.push(A),w&&P.push(w),Array.prototype.splice.apply(r,P)}}}}}return r},hooks:{all:{},add:function(e,n){var a=t.hooks.all;a[e]=a[e]||[],a[e].push(n)},run:function(e,n){var a=t.hooks.all[e];if(a&&a.length)for(var r,l=0;r=a[l++];)r(n)}}},n=t.Token=function(e,t,n){this.type=e,this.content=t,this.alias=n};if(n.stringify=function(e,a,r){if("string"==typeof e)return e;if("Array"===t.util.type(e))return e.map(function(t){return n.stringify(t,a,e)}).join("");var l={type:e.type,content:n.stringify(e.content,a,r),tag:"span",classes:["token",e.type],attributes:{},language:a,parent:r};if("comment"==l.type&&(l.attributes.spellcheck="true"),e.alias){var i="Array"===t.util.type(e.alias)?e.alias:[e.alias];Array.prototype.push.apply(l.classes,i)}t.hooks.run("wrap",l);var o="";for(var s in l.attributes)o+=(o?" ":"")+s+'="'+(l.attributes[s]||"")+'"';return"<"+l.tag+' class="'+l.classes.join(" ")+'" '+o+">"+l.content+"</"+l.tag+">"},!_self.document)return _self.addEventListener?(_self.addEventListener("message",function(e){var n=JSON.parse(e.data),a=n.language,r=n.code,l=n.immediateClose;_self.postMessage(t.highlight(r,t.languages[a],a)),l&&_self.close()},!1),_self.Prism):_self.Prism;var a=document.getElementsByTagName("script");return a=a[a.length-1],a&&(t.filename=a.src,document.addEventListener&&!a.hasAttribute("data-manual")&&document.addEventListener("DOMContentLoaded",t.highlightAll)),_self.Prism}();"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism);
|
||||
Prism.languages.markup={comment:/<!--[\w\W]*?-->/,prolog:/<\?[\w\W]+?\?>/,doctype:/<!DOCTYPE[\w\W]+?>/,cdata:/<!\[CDATA\[[\w\W]*?]]>/i,tag:{pattern:/<\/?[^\s>\/=.]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\\1|\\?(?!\1)[\w\W])*\1|[^\s'">=]+))?)*\s*\/?>/i,inside:{tag:{pattern:/^<\/?[^\s>\/]+/i,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"attr-value":{pattern:/=(?:('|")[\w\W]*?(\1)|[^\s>]+)/i,inside:{punctuation:/[=>"']/}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:/&#?[\da-z]{1,8};/i},Prism.hooks.add("wrap",function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&/,"&"))}),Prism.languages.xml=Prism.languages.markup,Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup;
|
||||
Prism.languages.css={comment:/\/\*[\w\W]*?\*\//,atrule:{pattern:/@[\w-]+?.*?(;|(?=\s*\{))/i,inside:{rule:/@[\w-]+/}},url:/url\((?:(["'])(\\(?:\r\n|[\w\W])|(?!\1)[^\\\r\n])*\1|.*?)\)/i,selector:/[^\{\}\s][^\{\};]*?(?=\s*\{)/,string:/("|')(\\(?:\r\n|[\w\W])|(?!\1)[^\\\r\n])*\1/,property:/(\b|\B)[\w-]+(?=\s*:)/i,important:/\B!important\b/i,"function":/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:]/},Prism.languages.css.atrule.inside.rest=Prism.util.clone(Prism.languages.css),Prism.languages.markup&&(Prism.languages.insertBefore("markup","tag",{style:{pattern:/(<style[\w\W]*?>)[\w\W]*?(?=<\/style>)/i,lookbehind:!0,inside:Prism.languages.css,alias:"language-css"}}),Prism.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/\s*style=("|').*?\1/i,inside:{"attr-name":{pattern:/^\s*style/i,inside:Prism.languages.markup.tag.inside},punctuation:/^\s*=\s*['"]|['"]\s*$/,"attr-value":{pattern:/.+/i,inside:Prism.languages.css}},alias:"language-css"}},Prism.languages.markup.tag));
|
||||
Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\w\W]*?\*\//,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0}],string:/(["'])(\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,"class-name":{pattern:/((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/i,lookbehind:!0,inside:{punctuation:/(\.|\\)/}},keyword:/\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,"boolean":/\b(true|false)\b/,"function":/[a-z0-9_]+(?=\()/i,number:/\b-?(?:0x[\da-f]+|\d*\.?\d+(?:e[+-]?\d+)?)\b/i,operator:/--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/,punctuation:/[{}[\];(),.:]/};
|
||||
Prism.languages.javascript=Prism.languages.extend("clike",{keyword:/\b(as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|false|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|true|try|typeof|var|void|while|with|yield)\b/,number:/\b-?(0x[\dA-Fa-f]+|0b[01]+|0o[0-7]+|\d*\.?\d+([Ee][+-]?\d+)?|NaN|Infinity)\b/,"function":/[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*(?=\()/i}),Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\\\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})]))/,lookbehind:!0}}),Prism.languages.insertBefore("javascript","class-name",{"template-string":{pattern:/`(?:\\`|\\?[^`])*`/,inside:{interpolation:{pattern:/\$\{[^}]+\}/,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}}}),Prism.languages.markup&&Prism.languages.insertBefore("markup","tag",{script:{pattern:/(<script[\w\W]*?>)[\w\W]*?(?=<\/script>)/i,lookbehind:!0,inside:Prism.languages.javascript,alias:"language-javascript"}}),Prism.languages.js=Prism.languages.javascript;
|
||||
Prism.languages.go=Prism.languages.extend("clike",{keyword:/\b(break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/,builtin:/\b(bool|byte|complex(64|128)|error|float(32|64)|rune|string|u?int(8|16|32|64|)|uintptr|append|cap|close|complex|copy|delete|imag|len|make|new|panic|print(ln)?|real|recover)\b/,"boolean":/\b(_|iota|nil|true|false)\b/,operator:/[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./,number:/\b(-?(0x[a-f\d]+|(\d+\.?\d*|\.\d+)(e[-+]?\d+)?)i?)\b/i,string:/("|'|`)(\\?.|\r|\n)*?\1/}),delete Prism.languages.go["class-name"];
|
||||
!function(){"undefined"!=typeof self&&self.Prism&&self.document&&document.querySelector&&(self.Prism.fileHighlight=function(){var e={js:"javascript",html:"markup",svg:"markup",xml:"markup",py:"python",rb:"ruby",ps1:"powershell",psm1:"powershell"};Array.prototype.forEach&&Array.prototype.slice.call(document.querySelectorAll("pre[data-src]")).forEach(function(t){for(var r,a=t.getAttribute("data-src"),s=t,n=/\blang(?:uage)?-(?!\*)(\w+)\b/i;s&&!n.test(s.className);)s=s.parentNode;if(s&&(r=(t.className.match(n)||[,""])[1]),!r){var o=(a.match(/\.(\w+)$/)||[,""])[1];r=e[o]||o}var l=document.createElement("code");l.className="language-"+r,t.textContent="",l.textContent="Loading…",t.appendChild(l);var i=new XMLHttpRequest;i.open("GET",a,!0),i.onreadystatechange=function(){4==i.readyState&&(i.status<400&&i.responseText?(l.textContent=i.responseText,Prism.highlightElement(l)):l.textContent=i.status>=400?"✖ Error "+i.status+" while fetching file: "+i.statusText:"✖ Error: File does not exist or is empty")},i.send(null)})},self.Prism.fileHighlight())}();
|
@ -1,55 +0,0 @@
|
||||
body, p, ol, ul {
|
||||
font-size: 16px;
|
||||
}
|
||||
footer {
|
||||
background-color: inherit !important;
|
||||
border-top: 2px solid #e0e0e0;
|
||||
}
|
||||
.facebook a:hover {
|
||||
color: #3B5998;
|
||||
}
|
||||
.twitter a:hover {
|
||||
color: #55ACEE;
|
||||
}
|
||||
.google a:hover {
|
||||
color: #DC4E41;
|
||||
}
|
||||
.github a:hover {
|
||||
color: #333;
|
||||
}
|
||||
:not(pre) > code {
|
||||
padding: 0 4px;
|
||||
background: #eee;
|
||||
color: #424242;
|
||||
font-size: .95em;
|
||||
font-family: Source Code Pro, Monaco, Menlo, Consolas, monospace;
|
||||
border: 1px solid #e0e0e0;
|
||||
border-radius: 2px;
|
||||
}
|
||||
a:link {
|
||||
text-decoration: none;
|
||||
}
|
||||
.page-content {
|
||||
padding: 20px 0;
|
||||
max-width: 960px;
|
||||
margin: auto;
|
||||
}
|
||||
.page-content header {
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
.menu {
|
||||
margin-right: 40px;
|
||||
}
|
||||
.menu a {
|
||||
display: block;
|
||||
color: #757575;
|
||||
padding: 5px;
|
||||
border-left:4px #F06292 solid;
|
||||
}
|
||||
.menu a:hover:not(.active) {
|
||||
background-color: #E0E0E0;
|
||||
}
|
||||
.menu .active {
|
||||
color: #FFF;
|
||||
background-color: #F06292;
|
||||
}
|
@ -1,236 +0,0 @@
|
||||
/* http://prismjs.com/download.html?themes=prism-coy&languages=markup+css+clike+javascript+go&plugins=file-highlight */
|
||||
/**
|
||||
* prism.js Coy theme for JavaScript, CoffeeScript, CSS and HTML
|
||||
* Based on https://github.com/tshedor/workshop-wp-theme (Example: http://workshop.kansan.com/category/sessions/basics or http://workshop.timshedor.com/category/sessions/basics);
|
||||
* @author Tim Shedor
|
||||
*/
|
||||
|
||||
code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
color: black;
|
||||
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
|
||||
direction: ltr;
|
||||
text-align: left;
|
||||
white-space: pre;
|
||||
word-spacing: normal;
|
||||
word-break: normal;
|
||||
word-wrap: normal;
|
||||
line-height: 1.5;
|
||||
|
||||
-moz-tab-size: 4;
|
||||
-o-tab-size: 4;
|
||||
tab-size: 4;
|
||||
|
||||
-webkit-hyphens: none;
|
||||
-moz-hyphens: none;
|
||||
-ms-hyphens: none;
|
||||
hyphens: none;
|
||||
}
|
||||
|
||||
/* Code blocks */
|
||||
pre[class*="language-"] {
|
||||
position: relative;
|
||||
margin: .5em 0;
|
||||
-webkit-box-shadow: -1px 0px 0px 0px #358ccb, 0px 0px 0px 1px #dfdfdf;
|
||||
-moz-box-shadow: -1px 0px 0px 0px #358ccb, 0px 0px 0px 1px #dfdfdf;
|
||||
box-shadow: -1px 0px 0px 0px #358ccb, 0px 0px 0px 1px #dfdfdf;
|
||||
border-left: 10px solid #358ccb;
|
||||
background-color: #fdfdfd;
|
||||
background-image: -webkit-linear-gradient(transparent 50%, rgba(69, 142, 209, 0.04) 50%);
|
||||
background-image: -moz-linear-gradient(transparent 50%, rgba(69, 142, 209, 0.04) 50%);
|
||||
background-image: -ms-linear-gradient(transparent 50%, rgba(69, 142, 209, 0.04) 50%);
|
||||
background-image: -o-linear-gradient(transparent 50%, rgba(69, 142, 209, 0.04) 50%);
|
||||
background-image: linear-gradient(transparent 50%, rgba(69, 142, 209, 0.04) 50%);
|
||||
background-size: 3em 3em;
|
||||
background-origin: content-box;
|
||||
overflow: visible;
|
||||
max-height: 30em;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
code[class*="language"] {
|
||||
max-height: inherit;
|
||||
height: 100%;
|
||||
padding: 0 1em;
|
||||
display: block;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/* Margin bottom to accomodate shadow */
|
||||
:not(pre) > code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
background-color: #fdfdfd;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
/* Inline code */
|
||||
:not(pre) > code[class*="language-"] {
|
||||
position: relative;
|
||||
padding: .2em;
|
||||
-webkit-border-radius: 0.3em;
|
||||
-moz-border-radius: 0.3em;
|
||||
-ms-border-radius: 0.3em;
|
||||
-o-border-radius: 0.3em;
|
||||
border-radius: 0.3em;
|
||||
color: #c92c2c;
|
||||
border: 1px solid rgba(0, 0, 0, 0.1);
|
||||
display: inline;
|
||||
}
|
||||
|
||||
pre[class*="language-"]:before,
|
||||
pre[class*="language-"]:after {
|
||||
content: '';
|
||||
z-index: -2;
|
||||
display: block;
|
||||
position: absolute;
|
||||
bottom: 0.75em;
|
||||
left: 0.18em;
|
||||
width: 40%;
|
||||
height: 20%;
|
||||
-webkit-box-shadow: 0px 13px 8px #979797;
|
||||
-moz-box-shadow: 0px 13px 8px #979797;
|
||||
box-shadow: 0px 13px 8px #979797;
|
||||
-webkit-transform: rotate(-2deg);
|
||||
-moz-transform: rotate(-2deg);
|
||||
-ms-transform: rotate(-2deg);
|
||||
-o-transform: rotate(-2deg);
|
||||
transform: rotate(-2deg);
|
||||
}
|
||||
|
||||
:not(pre) > code[class*="language-"]:after,
|
||||
pre[class*="language-"]:after {
|
||||
right: 0.75em;
|
||||
left: auto;
|
||||
-webkit-transform: rotate(2deg);
|
||||
-moz-transform: rotate(2deg);
|
||||
-ms-transform: rotate(2deg);
|
||||
-o-transform: rotate(2deg);
|
||||
transform: rotate(2deg);
|
||||
}
|
||||
|
||||
.token.comment,
|
||||
.token.block-comment,
|
||||
.token.prolog,
|
||||
.token.doctype,
|
||||
.token.cdata {
|
||||
color: #7D8B99;
|
||||
}
|
||||
|
||||
.token.punctuation {
|
||||
color: #5F6364;
|
||||
}
|
||||
|
||||
.token.property,
|
||||
.token.tag,
|
||||
.token.boolean,
|
||||
.token.number,
|
||||
.token.function-name,
|
||||
.token.constant,
|
||||
.token.symbol,
|
||||
.token.deleted {
|
||||
color: #c92c2c;
|
||||
}
|
||||
|
||||
.token.selector,
|
||||
.token.attr-name,
|
||||
.token.string,
|
||||
.token.char,
|
||||
.token.function,
|
||||
.token.builtin,
|
||||
.token.inserted {
|
||||
color: #2f9c0a;
|
||||
}
|
||||
|
||||
.token.operator,
|
||||
.token.entity,
|
||||
.token.url,
|
||||
.token.variable {
|
||||
color: #a67f59;
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.token.atrule,
|
||||
.token.attr-value,
|
||||
.token.keyword,
|
||||
.token.class-name {
|
||||
color: #1990b8;
|
||||
}
|
||||
|
||||
.token.regex,
|
||||
.token.important {
|
||||
color: #e90;
|
||||
}
|
||||
|
||||
.language-css .token.string,
|
||||
.style .token.string {
|
||||
color: #a67f59;
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.token.important {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.token.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
.token.italic {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.token.entity {
|
||||
cursor: help;
|
||||
}
|
||||
|
||||
.namespace {
|
||||
opacity: .7;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
pre[class*="language-"]:before,
|
||||
pre[class*="language-"]:after {
|
||||
bottom: 14px;
|
||||
-webkit-box-shadow: none;
|
||||
-moz-box-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Plugin styles */
|
||||
.token.tab:not(:empty):before,
|
||||
.token.cr:before,
|
||||
.token.lf:before {
|
||||
color: #e0d7d1;
|
||||
}
|
||||
|
||||
/* Plugin styles: Line Numbers */
|
||||
pre[class*="language-"].line-numbers {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
pre[class*="language-"].line-numbers code {
|
||||
padding-left: 3.8em;
|
||||
}
|
||||
|
||||
pre[class*="language-"].line-numbers .line-numbers-rows {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
/* Plugin styles: Line Highlight */
|
||||
pre[class*="language-"][data-line] {
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
pre[data-line] code {
|
||||
position: relative;
|
||||
padding-left: 4em;
|
||||
}
|
||||
pre .line-highlight {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user