Remove internal/cmd/gen, it has no use for the end-developer.

Former-commit-id: 12bead9d379c6644e391c482fe71b2e88263376c
This commit is contained in:
kataras 2017-06-11 23:58:34 +03:00
parent d031ad55b8
commit 74989ad0a1
19 changed files with 60 additions and 409 deletions

View File

@ -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.

View File

@ -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)
}
}

View File

@ -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()

View File

@ -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()

View File

@ -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.

View File

@ -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 })

View File

@ -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 {

View File

@ -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 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))
}

View File

@ -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

View File

@ -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
}

View File

@ -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.

View File

@ -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
}

View File

@ -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 <a href ...>...</a>
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
}

View File

@ -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
}

View File

@ -1,149 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Iris</title>
<meta charset="utf-8">
<meta name="description" content="Iris-go - The fastest backend web framework for Go.">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<meta property="og:type" content="article">
<meta property="og:title" content="Iris">
<meta property="og:description" content="Iris-go - The fastest backend web framework for Go.">
<meta property="og:image" content="http://iris-go.com/images/icon.svg">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Iris">
<meta name="twitter:description" content="Iris-go - The fastest backend web framework for Go.">
<meta name="twitter:image" content="http://iris-go.com/images/icon.svg">
<link rel="icon" href="/images/favicon.ico" type="image/x-icon">
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600|Roboto Mono' rel='stylesheet' type='text/css'>
<link href='//fonts.googleapis.com/css?family=Dosis:500&text=Iris' rel='stylesheet' type='text/css'>
<link href='/css/prism.css' rel='stylesheet' type='text/css'>
<link href='/css/terminal.css' rel='stylesheet' type='text/css'>
<!-- main page styles -->
<link rel="stylesheet" href="/css/page.css">
<!-- this needs to be loaded before guide's inline scripts -->
<script>
window.PAGE_TYPE = "Recipe"
</script>
<!-- ga -->
<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', 'UA-46045347-6', 'iris-go.com');
ga('send', 'pageview');
</script>
</head>
<body class="docs">
<div id="mobile-bar">
<a class="menu-button"></a>
<a class="logo" href="/"></a>
</div>
<div id="header">
<a id="logo" href="/">
<img src="/images/logo.png">
<span>IRIS</span>
</a>
<ul id="nav">
<li><a href="/{{.Branch}}/start/" class="nav-link">Start</a></li>
<li><a href="/{{.Branch}}/recipe/" class="nav-link current">Recipe</a></li>
<li><a href="/{{.Branch}}/blogs/" class="nav-link">Blogs</a></li>
<li><a target="_blank" href="https://kataras.rocket.chat/channel/iris" class="nav-link">Chat</a></li>
<li><a class="donate" style="color:#ff6666;" target="_blank" href="https://github.com/kataras/iris#buy-me-a-cup-of-coffee">Donate</a></li>
<!--
<li>
<form id="search-form">
<input type="text" id="search-query-nav"
class="search-query st-default-search-input"/>
</form>
</li>
-->
</ul>
</div>
<div id="main" class="fix-sidebar">
<div class="sidebar">
<ul class="main-menu">
<li><a href="/{{.Branch}}/start/" class="nav-link">Start</a></li>
<li><a href="/{{.Branch}}/recipe/" class="nav-link current">Recipe</a></li>
<li><a href="/{{.Branch}}/blogs/" class="nav-link">Blogs</a></li>
<li><a target="_blank" href="https://kataras.rocket.chat/channel/iris" class="nav-link">Chat</a></li>
<li><a target="_blank" class="donate" style="color:#ff6666;" href="https://github.com/kataras/iris#buy-me-a-cup-of-coffee">Donate</a></li>
</ul>
<div class="list">
<h2>
Recipe
</h2>
<ul class="menu-root">
<li>
<a href="/{{.Branch}}/recipe/index.html" class="sidebar-link current"></a>
</li>
</ul>
</div>
</div>
<div class="content Recipe with-sidebar ">
{{ range $key, $example := .Examples -}}
{{ if $example.HasChildren }}
<h2 id="{{$example.Name}}">
<a href="#{{$example.Name}}" class="headerlink" title="{{$example.Name}}"></a>
{{$example.Name}}
</h2>
{{ range $key, $child := $example.Children -}}
<h3 id="{{ $child.Name }}">
<a href="#{{ $child.Name }}" class="headerlink" title="{{ $child.Name }}"></a>
{{ $child.Name }}
</h3>
<pre data-src="{{ $child.DataSource }}" data-visible="true" class="line-numbers codepre"></pre>
{{- end }} {{- end }}
{{ if $example.HasNotChildren }}
<h2 id="{{ $example.Name }}">
<a href="#{{ $example.Name }}" class="headerlink" title="{{ $example.Name }}"></a>
{{ $example.Name }}
</h2>
<pre data-src="{{ $example.DataSource }}" data-visible="true" class="line-numbers codepre"></pre>
{{- end }}
{{- end }}
<div class="footer">
Contribute to the documentation?
<a target="_blank" href="https://github.com/iris-contrib/website/blob/gh-pages/{{.Branch}}/recipe/index.html" >
Edit this page on Github!
</a>
</div>
</div>
</div>
<script src="/js/smooth-scroll.min.js"></script>
<script async defer src="https://buttons.github.io/buttons.js"></script>
<!-- main custom script for sidebars, version selects etc. -->
<script src="/js/css.escape.js"></script>
<script src="/js/common.js"></script>
<script src="/js/prism.js"></script>
<!-- fastclick -->
<script src="//cdnjs.cloudflare.com/ajax/libs/fastclick/1.0.6/fastclick.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
FastClick.attach(document.body)
}, false)
</script>
</body>
</html>

View File

@ -1,50 +0,0 @@
package main
import (
"os"
"text/template"
"github.com/kataras/iris/internal/cmd/gen/website/recipe/example"
)
const tmpl = `
{{ range $key, $example := . -}}
{{ if $example.HasChildren }}
<h2 id="{{$example.Name}}"><a href="#{{$example.Name}}" class="headerlink" title="{{$example.Name}}"></a>{{$example.Name}}</h2>
{{ range $key, $child := $example.Children -}}
<h3 id="{{ $child.Name }}">
<a href="#{{ $child.Name }}" class="headerlink" title="{{ $child.Name }}"></a>
{{ $child.Name }}
</h3>
<pre data-src="{{ $child.DataSource }}"
data-visible="true" class ="line-numbers codepre"></pre>
{{- end }}
{{- end }}
{{ if .HasNotChildren }}
<h2 id="{{ $example.Name }}">
<a href="#{{ $example.Name }}" class="headerlink" title="{{ $example.Name }}"></a>
{{ $example.Name }}
</h2>
<pre data-src="{{ $example.DataSource }}"
data-visible="true" class ="line-numbers codepre"></pre>
{{- end }}
{{- end }}
`
func main() {
// just for testing, the cli will be coded when I finish at least with this one command.
examples, err := example.Parse("master")
if err != nil {
println(err.Error())
return
}
text, err := template.New("").Parse(tmpl)
if err != nil {
println(err.Error())
}
if err := text.Execute(os.Stdout, examples); err != nil {
println("err in template : " + err.Error())
}
}

View File

@ -91,7 +91,7 @@ func New() *Application {
app := &Application{
config: &config,
logger: logger.NewDevLogger(),
logger: logger.NewDevLogger(banner),
APIBuilder: router.NewAPIBuilder(),
Router: router.NewRouter(),
}

View File

@ -19,7 +19,7 @@ type Config struct {
Path bool
}
// DefaultConfig returns an options which all properties are true except EnableColors
func DefaultConfigurationReadOnly() Config {
// DefaultConfiguration returns an options which all properties are true except EnableColors
func DefaultConfiguration() Config {
return Config{true, true, true, true}
}

View File

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package loger provides request logging via middleware. See _examples/beginner/request-logger
// Package logger provides request logging via middleware. See _examples/beginner/request-logger
package logger
import (
@ -58,7 +58,7 @@ func (l *requestLoggerMiddleware) ServeHTTP(ctx context.Context) {
//
// Receives an optional configuation.
func New(cfg ...Config) context.Handler {
c := DefaultConfigurationReadOnly()
c := DefaultConfiguration()
if len(cfg) > 0 {
c = cfg[0]
}