diff --git a/HISTORY.md b/HISTORY.md
index df24ee28..b5986a14 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -36,7 +36,7 @@ Iris now supports static paths and dynamic paths for the same path prefix with z
`app.Get("/profile/{id:int}", handler)` and `app.Get("/profile/create", createHandler)` are not in conflict anymore.
-The the rest of the special Iris' routing features, including static & wildcard subdomains are still work like a charm.
+The rest of the special Iris' routing features, including static & wildcard subdomains are still work like a charm.
> This was one of the most popular community's feature requests. Click [here](https://github.com/kataras/iris/blob/master/_examples/beginner/routing/overview/main.go) to see a trivial example.
diff --git a/_examples/beginner/file-logger/main.go b/_examples/beginner/file-logger/main.go
index 738e9ded..02d362f4 100644
--- a/_examples/beginner/file-logger/main.go
+++ b/_examples/beginner/file-logger/main.go
@@ -43,7 +43,7 @@ func main() {
// navigate to http://localhost:8080
// and open the ./logs.txt file
if err := app.Run(iris.Addr(":8080"), iris.WithoutBanner); err != nil {
- app.Log("Shutdown with error: %v", err)
+ app.Log("Shutdown with error: %v\n", err)
}
}
diff --git a/context/response_recorder.go b/context/response_recorder.go
index 3cef4984..03820325 100644
--- a/context/response_recorder.go
+++ b/context/response_recorder.go
@@ -28,6 +28,12 @@ func releaseResponseRecorder(w *ResponseRecorder) {
rrpool.Put(w)
}
+// A ResponseRecorder is used mostly by context's transactions
+// in order to record and change if needed the body, status code and headers.
+//
+// Developers are not limited to manually ask to record a response.
+// To turn on the recorder from a Handler,
+// rec := context.Recorder()
type ResponseRecorder struct {
ResponseWriter
// keep track of the body in order to be
@@ -39,12 +45,16 @@ type ResponseRecorder struct {
var _ ResponseWriter = &ResponseRecorder{}
+// BeginRecord accepts its parent ResponseWriter and
+// prepares itself, the response recorder, to record and send response to the client.
func (w *ResponseRecorder) BeginRecord(underline ResponseWriter) {
w.ResponseWriter = underline
w.headers = underline.Header()
w.ResetBody()
}
+// EndResponse is auto-called when the whole client's request is done,
+// releases the response recorder and its underline ResponseWriter.
func (w *ResponseRecorder) EndResponse() {
releaseResponseRecorder(w)
w.ResponseWriter.EndResponse()
diff --git a/core/logger/dev.go b/core/logger/dev.go
index 3bbbfc1f..4e479996 100644
--- a/core/logger/dev.go
+++ b/core/logger/dev.go
@@ -12,6 +12,9 @@ import (
"time"
)
+// NewDevLogger returns a new logger of io.Writer which
+// formats its log message input and writes it
+// to the os.Stdout.
func NewDevLogger(omitTimeFor ...string) io.Writer {
mu := &sync.Mutex{} // for now and last log
lastLog := time.Now()
diff --git a/core/logger/logger.go b/core/logger/logger.go
index 0aacee98..5e2a4ff0 100644
--- a/core/logger/logger.go
+++ b/core/logger/logger.go
@@ -26,7 +26,7 @@ type stringWriter interface {
WriteString(string) (int, error)
}
-// Log sends a message to the defined io.Writer logger, it's
+// Log sends a message to the defined logger of io.Writer logger, it's
// just a help function for internal use but it can be used to a cusotom middleware too.
//
// See AttachLogger too.
diff --git a/core/logger/noop.go b/core/logger/noop.go
index 1a737aca..58333ffa 100644
--- a/core/logger/noop.go
+++ b/core/logger/noop.go
@@ -4,4 +4,6 @@
package logger
+// NoOpLogger returns a new, non-operational logger of io.Writer,
+// it does nothing any form of input.
var NoOpLogger = writerFunc(func([]byte) (int, error) { return -1, nil })
diff --git a/core/router/handler.go b/core/router/handler.go
index 60144009..086154ec 100644
--- a/core/router/handler.go
+++ b/core/router/handler.go
@@ -5,7 +5,6 @@
package router
import (
- "fmt"
"html"
"net/http"
"sort"
@@ -53,10 +52,6 @@ func (h *routerHandler) getTree(method, subdomain string) *tree {
}
func (h *routerHandler) addRoute(method, subdomain, path string, handlers context.Handlers) error {
- if len(path) == 0 || path[0] != '/' {
- return fmt.Errorf("router: path %q must begin with %q", path, "/")
- }
-
t := h.getTree(method, subdomain)
if t == nil {
diff --git a/core/router/macro/interpreter/lexer/lexer.go b/core/router/macro/interpreter/lexer/lexer.go
index ce313498..e57822f3 100644
--- a/core/router/macro/interpreter/lexer/lexer.go
+++ b/core/router/macro/interpreter/lexer/lexer.go
@@ -8,6 +8,7 @@ import (
"github.com/kataras/iris/core/router/macro/interpreter/token"
)
+// Lexer helps us to read/scan characters of a source and resolve their token types.
type Lexer struct {
input string
pos int // current pos in input, current char
@@ -15,6 +16,8 @@ type Lexer struct {
ch byte // current char under examination
}
+// New takes a source, series of chars, and returns
+// a new, ready to read from the first letter, lexer.
func New(src string) *Lexer {
l := &Lexer{
input: src,
@@ -35,11 +38,13 @@ func (l *Lexer) readChar() {
}
const (
+ // Begin is the symbol which lexer should scan forward to.
Begin = '{' // token.LBRACE
- End = '}' // token.RBRACE
+ // End is the symbol which lexer should stop scanning.
+ End = '}' // token.RBRACE
)
-func resolveTokenType(ch byte) token.TokenType {
+func resolveTokenType(ch byte) token.Type {
switch ch {
case Begin:
return token.LBRACE
@@ -71,6 +76,11 @@ func resolveTokenType(ch byte) token.TokenType {
}
+// NextToken returns the next token in the series of characters.
+// It can be a single symbol, a token type or a literal.
+// It's able to return an EOF token too.
+//
+// It moves the cursor forward.
func (l *Lexer) NextToken() (t token.Token) {
l.skipWhitespace()
typ := resolveTokenType(l.ch)
@@ -101,6 +111,13 @@ func (l *Lexer) NextToken() (t token.Token) {
return
}
+// NextDynamicToken doesn't cares about the grammar.
+// It reads numbers or any unknown symbol,
+// it's being used by parser to skip all characters
+// between parameter function's arguemnts inside parenthesis,
+// in order to allow custom regexp on the end-language too.
+//
+// It moves the cursor forward.
func (l *Lexer) NextDynamicToken() (t token.Token) {
// calculate anything, even spaces.
@@ -124,8 +141,11 @@ func (l *Lexer) readIdentifierFuncArgument() string {
return l.input[pos:l.pos]
}
-// useful when we want to peek but no continue, i.e empty param functions 'even()'
-func (l *Lexer) PeekNextTokenType() token.TokenType {
+// PeekNextTokenType returns only the token type
+// of the next character and it does not move forward the cursor.
+// It's being used by parser to recognise empty functions, i.e `even()`
+// as valid functions with zero input arguments.
+func (l *Lexer) PeekNextTokenType() token.Type {
if len(l.input)-1 > l.pos {
ch := l.input[l.pos]
return resolveTokenType(ch)
@@ -133,7 +153,7 @@ func (l *Lexer) PeekNextTokenType() token.TokenType {
return resolveTokenType(0) // EOF
}
-func (l *Lexer) newToken(tokenType token.TokenType, lit string) token.Token {
+func (l *Lexer) newToken(tokenType token.Type, lit string) token.Token {
t := token.Token{
Type: tokenType,
Literal: lit,
@@ -151,7 +171,7 @@ func (l *Lexer) newToken(tokenType token.TokenType, lit string) token.Token {
return t
}
-func (l *Lexer) newTokenRune(tokenType token.TokenType, ch byte) token.Token {
+func (l *Lexer) newTokenRune(tokenType token.Type, ch byte) token.Token {
return l.newToken(tokenType, string(ch))
}
diff --git a/core/router/macro/interpreter/lexer/lexer_test.go b/core/router/macro/interpreter/lexer/lexer_test.go
index dc1750a9..39aa709c 100644
--- a/core/router/macro/interpreter/lexer/lexer_test.go
+++ b/core/router/macro/interpreter/lexer/lexer_test.go
@@ -14,7 +14,7 @@ func TestNextToken(t *testing.T) {
input := `{id:int min(1) max(5) else 404}`
tests := []struct {
- expectedType token.TokenType
+ expectedType token.Type
expectedLiteral string
}{
{token.LBRACE, "{"}, // 0
diff --git a/core/router/macro/interpreter/token/token.go b/core/router/macro/interpreter/token/token.go
index a7d595e8..29c6b3f5 100644
--- a/core/router/macro/interpreter/token/token.go
+++ b/core/router/macro/interpreter/token/token.go
@@ -4,10 +4,12 @@
package token
-type TokenType int
+// Type is a specific type of int which describes the symbols.
+type Type int
+// Token describes the letter(s) or symbol, is a result of the lexer.
type Token struct {
- Type TokenType
+ Type Type
Literal string
Start int // including the first char
End int // including the last char
@@ -33,19 +35,21 @@ const (
COMMA
IDENT // string or keyword
// Keywords
- keywords_start
+ // keywords_start
ELSE // else
- keywords_end
+ // keywords_end
INT // 42
)
const eof rune = 0
-var keywords = map[string]TokenType{
+var keywords = map[string]Type{
"else": ELSE,
}
-func LookupIdent(ident string) TokenType {
+// LookupIdent receives a series of chars
+// and tries to resolves the token type.
+func LookupIdent(ident string) Type {
if tok, ok := keywords[ident]; ok {
return tok
}
diff --git a/internal/cmd/README.md b/internal/cmd/README.md
deleted file mode 100644
index a31807dc..00000000
--- a/internal/cmd/README.md
+++ /dev/null
@@ -1,14 +0,0 @@
-# Internal CLI
-
-This folder contains the internal Iris cli program. It's internal because
-it will contain generators for the website, maybe versioning for the github branches etc...
-So it's useless for the end-developers, but it will be a good place to learn how you can create your own
-cli and dynamic-generators programs.
-
-
-Click [here](https://github.com/iris-contrib/community-board/issues/2) to learn its future.
-
-> When I use the word "generator" I don't mean the go1.4+ generate feature.
-
-## Don't waste your time, it is not ready yet.
-
diff --git a/internal/cmd/gen/website/recipe/example/example.go b/internal/cmd/gen/website/recipe/example/example.go
deleted file mode 100644
index 0eb68b41..00000000
--- a/internal/cmd/gen/website/recipe/example/example.go
+++ /dev/null
@@ -1,11 +0,0 @@
-package example
-
-// Example defines the example link.
-type Example struct {
- Name string // i.e: Hello World
- DataSource string // i.e: https://raw.githubusercontent.com/iris-contrib/examples/master/hello-world.go
- Children []Example // if has children the data source is not a source file, it's just a folder, its the template's H2 tag.
- // needed for the raw templates, we can do a simple func but lets keep it simple, it's a small template file.
- HasChildren bool
- HasNotChildren bool
-}
diff --git a/internal/cmd/gen/website/recipe/example/parser.go b/internal/cmd/gen/website/recipe/example/parser.go
deleted file mode 100644
index 5404b6de..00000000
--- a/internal/cmd/gen/website/recipe/example/parser.go
+++ /dev/null
@@ -1,129 +0,0 @@
-package example
-
-import (
- "bytes"
- "io/ioutil"
- "net/http"
- "strings"
-
- "github.com/PuerkitoBio/goquery"
- "github.com/kataras/iris/core/errors"
- "github.com/microcosm-cc/bluemonday"
- "github.com/russross/blackfriday"
-)
-
-// Parse will try to parse and return all examples.
-// The input parameter "branch" is used to build
-// the raw..iris-contrib/examples/$branch/
-// but it should be the same with
-// the kataras/iris/$branch/ for consistency.
-func Parse(branch string) (examples []Example, err error) {
- var (
- contentsURL = "https://raw.githubusercontent.com/iris-contrib/examples/" + branch
- tableOfContents = "Table of contents"
- sanitizeMarkdown = true
- )
-
- // get the raw markdown
- readmeURL := contentsURL + "/README.md"
- res, err := http.Get(readmeURL)
- if err != nil {
- return nil, err
- }
- markdownContents, err := ioutil.ReadAll(res.Body)
- if err != nil {
- return nil, err
- }
-
- // convert it to html
- htmlContents := &bytes.Buffer{}
- htmlContentsFromMarkdown := blackfriday.MarkdownCommon(markdownContents)
-
- if len(htmlContentsFromMarkdown) == 0 {
- return nil, errors.New("empty html")
- }
-
- if sanitizeMarkdown {
- markdownContents = bluemonday.UGCPolicy().SanitizeBytes(markdownContents)
- }
-
- htmlContents.Write(htmlContentsFromMarkdown)
- // println("html contents: " + htmlContents.String())
- // get the document from the html
- readme, err := goquery.NewDocumentFromReader(htmlContents)
- if err != nil {
- return nil, err
- }
-
- // or with just one line (but may break if we add another h2,
- // so I will do it with the hard and un-readable way for now)
- // readme.Find("h2").First().NextAllFiltered("ul").Children().Text()
-
- // find the header of Table Of Contents, we will need it to take its
- // next ul, which should be the examples list.
- var tableOfContentsHeader *goquery.Selection
- readme.Find("h2").EachWithBreak(func(_ int, n *goquery.Selection) bool {
- if nodeContents := n.Text(); nodeContents == tableOfContents {
- tableOfContentsHeader = n
- return false // break
- }
- return true
- })
-
- if tableOfContentsHeader == nil {
- return nil, errors.New("table of contents not found using: " + tableOfContents)
- }
-
- // get the list of the examples
- tableOfContentsUL := tableOfContentsHeader.NextFiltered("ul")
- if tableOfContentsUL == nil {
- return nil, errors.New("table of contents list not found")
- }
-
- // iterate over categories example's ...
- tableOfContentsUL.Children().EachWithBreak(func(_ int, li *goquery.Selection) bool {
- exampleHrefLink := li.Children().First()
- if exampleHrefLink == nil {
- err = errors.New("example link href is nil, source: " + li.Text())
- return false // break on first failure
- }
-
- name := exampleHrefLink.Text()
-
- sourcelink, _ := li.Find("a").First().Attr("href")
- hasChildren := !strings.HasSuffix(sourcelink, ".go")
-
- example := Example{
- Name: name,
- DataSource: contentsURL + "/" + sourcelink,
- HasChildren: hasChildren,
- HasNotChildren: !hasChildren,
- }
-
- // search for sub examples
- if hasChildren {
- li.Find("ul").Children().EachWithBreak(func(_ int, liExample *goquery.Selection) bool {
- name := liExample.Text()
- liHref := liExample.Find("a").First()
- sourcelink, ok := liHref.Attr("href")
- if !ok {
- err = errors.New(name + "'s source couldn't be found")
- return false
- }
-
- subExample := Example{
- Name: name,
- DataSource: contentsURL + "/" + sourcelink,
- }
-
- example.Children = append(example.Children, subExample)
- return true
- })
-
- }
-
- examples = append(examples, example)
- return true
- })
- return examples, err
-}
diff --git a/internal/cmd/gen/website/recipe/recipe.go b/internal/cmd/gen/website/recipe/recipe.go
deleted file mode 100644
index 9f99ca4c..00000000
--- a/internal/cmd/gen/website/recipe/recipe.go
+++ /dev/null
@@ -1,30 +0,0 @@
-package recipe
-
-import (
- "github.com/kataras/iris/internal/cmd/gen/website/recipe/example"
-)
-
-type Recipe struct {
- Branch string // i.e "master", "v6"...
- Examples []example.Example
-}
-
-// NewRecipe accepts the "branch", i.e: "master", "v6", "v7"...
-// and returns a new Recipe pointer with its generated and parsed examples.
-func NewRecipe(branch string) (*Recipe, error) {
- if branch == "" {
- branch = "master"
- }
-
- examples, err := example.Parse(branch)
- if err != nil {
- return nil, err
- }
-
- r := &Recipe{
- Branch: branch,
- Examples: examples,
- }
-
- return r, nil
-}
diff --git a/internal/cmd/gen/website/recipe/recipe.html b/internal/cmd/gen/website/recipe/recipe.html
deleted file mode 100644
index 8256b577..00000000
--- a/internal/cmd/gen/website/recipe/recipe.html
+++ /dev/null
@@ -1,149 +0,0 @@
-
-
-
-