| @@ -5,6 +5,7 @@ | |||||
| package models | package models | ||||
| import ( | import ( | ||||
| "fmt" | |||||
| "path" | "path" | ||||
| "strings" | "strings" | ||||
| "time" | "time" | ||||
| @@ -22,12 +23,25 @@ type Commit struct { | |||||
| Message string | Message string | ||||
| } | } | ||||
| var ( | |||||
| ErrRepoFileNotLoaded = fmt.Errorf("repo file not loaded") | |||||
| ) | |||||
| type RepoFile struct { | type RepoFile struct { | ||||
| *git.TreeEntry | *git.TreeEntry | ||||
| Path string | Path string | ||||
| Message string | Message string | ||||
| Created time.Time | Created time.Time | ||||
| Size int64 | Size int64 | ||||
| Repo *git.Repository | |||||
| } | |||||
| func (file *RepoFile) LookupBlob() (*git.Blob, error) { | |||||
| if file.Repo == nil { | |||||
| return nil, ErrRepoFileNotLoaded | |||||
| } | |||||
| return file.Repo.LookupBlob(file.Id) | |||||
| } | } | ||||
| func GetBranches(userName, reposName string) ([]string, error) { | func GetBranches(userName, reposName string) ([]string, error) { | ||||
| @@ -80,6 +94,7 @@ func GetReposFiles(userName, reposName, branchName, rpath string) ([]*RepoFile, | |||||
| lastCommit.Message(), | lastCommit.Message(), | ||||
| lastCommit.Committer.When, | lastCommit.Committer.When, | ||||
| size, | size, | ||||
| repo, | |||||
| }) | }) | ||||
| case git.FileModeTree: | case git.FileModeTree: | ||||
| repodirs = append(repodirs, &RepoFile{ | repodirs = append(repodirs, &RepoFile{ | ||||
| @@ -88,6 +103,7 @@ func GetReposFiles(userName, reposName, branchName, rpath string) ([]*RepoFile, | |||||
| lastCommit.Message(), | lastCommit.Message(), | ||||
| lastCommit.Committer.When, | lastCommit.Committer.When, | ||||
| size, | size, | ||||
| repo, | |||||
| }) | }) | ||||
| } | } | ||||
| } | } | ||||
| @@ -0,0 +1,39 @@ | |||||
| // Copyright 2014 The Gogs Authors. All rights reserved. | |||||
| // Use of this source code is governed by a MIT-style | |||||
| // license that can be found in the LICENSE file. | |||||
| package base | |||||
| import ( | |||||
| "github.com/slene/blackfriday" | |||||
| ) | |||||
| func RenderMarkdown(rawBytes []byte) []byte { | |||||
| htmlFlags := 0 | |||||
| htmlFlags |= blackfriday.HTML_USE_XHTML | |||||
| // htmlFlags |= blackfriday.HTML_USE_SMARTYPANTS | |||||
| // htmlFlags |= blackfriday.HTML_SMARTYPANTS_FRACTIONS | |||||
| // htmlFlags |= blackfriday.HTML_SMARTYPANTS_LATEX_DASHES | |||||
| htmlFlags |= blackfriday.HTML_SKIP_HTML | |||||
| htmlFlags |= blackfriday.HTML_SKIP_STYLE | |||||
| htmlFlags |= blackfriday.HTML_SKIP_SCRIPT | |||||
| htmlFlags |= blackfriday.HTML_GITHUB_BLOCKCODE | |||||
| htmlFlags |= blackfriday.HTML_OMIT_CONTENTS | |||||
| htmlFlags |= blackfriday.HTML_COMPLETE_PAGE | |||||
| renderer := blackfriday.HtmlRenderer(htmlFlags, "", "") | |||||
| // set up the parser | |||||
| extensions := 0 | |||||
| extensions |= blackfriday.EXTENSION_NO_INTRA_EMPHASIS | |||||
| extensions |= blackfriday.EXTENSION_TABLES | |||||
| extensions |= blackfriday.EXTENSION_FENCED_CODE | |||||
| extensions |= blackfriday.EXTENSION_AUTOLINK | |||||
| extensions |= blackfriday.EXTENSION_STRIKETHROUGH | |||||
| extensions |= blackfriday.EXTENSION_HARD_LINE_BREAK | |||||
| extensions |= blackfriday.EXTENSION_SPACE_HEADERS | |||||
| extensions |= blackfriday.EXTENSION_NO_EMPTY_LINE_BEFORE_BLOCK | |||||
| body := blackfriday.Markdown(rawBytes, renderer, extensions) | |||||
| return body | |||||
| } | |||||
| @@ -8,9 +8,11 @@ import ( | |||||
| "strings" | "strings" | ||||
| "github.com/codegangsta/martini" | "github.com/codegangsta/martini" | ||||
| // "github.com/slene/blackfriday" | |||||
| "github.com/gogits/git" | |||||
| "github.com/gogits/gogs/models" | "github.com/gogits/gogs/models" | ||||
| "github.com/gogits/gogs/modules/base" | |||||
| "github.com/gogits/gogs/modules/middleware" | "github.com/gogits/gogs/modules/middleware" | ||||
| ) | ) | ||||
| @@ -43,12 +45,14 @@ func Single(ctx *middleware.Context, params martini.Params) { | |||||
| params["branchname"] = "master" | params["branchname"] = "master" | ||||
| } | } | ||||
| // Directory and file list. | |||||
| // Get tree path | |||||
| treename := params["_1"] | treename := params["_1"] | ||||
| // Directory and file list. | |||||
| files, err := models.GetReposFiles(params["username"], params["reponame"], | files, err := models.GetReposFiles(params["username"], params["reponame"], | ||||
| params["branchname"], treename) | params["branchname"], treename) | ||||
| if err != nil { | if err != nil { | ||||
| ctx.Handle(200, "repo.Single", err) | |||||
| ctx.Render.Error(404) | |||||
| return | return | ||||
| } | } | ||||
| ctx.Data["Username"] = params["username"] | ctx.Data["Username"] = params["username"] | ||||
| @@ -58,7 +62,7 @@ func Single(ctx *middleware.Context, params martini.Params) { | |||||
| // Branches. | // Branches. | ||||
| brs, err := models.GetBranches(params["username"], params["reponame"]) | brs, err := models.GetBranches(params["username"], params["reponame"]) | ||||
| if err != nil { | if err != nil { | ||||
| ctx.Handle(200, "repo.Single", err) | |||||
| ctx.Render.Error(404) | |||||
| return | return | ||||
| } | } | ||||
| ctx.Data["Branches"] = brs | ctx.Data["Branches"] = brs | ||||
| @@ -73,22 +77,41 @@ func Single(ctx *middleware.Context, params martini.Params) { | |||||
| } | } | ||||
| } | } | ||||
| // Latest commit. | |||||
| // Get latest commit according username and repo name | |||||
| commit, err := models.GetLastestCommit(params["username"], params["reponame"]) | commit, err := models.GetLastestCommit(params["username"], params["reponame"]) | ||||
| if err != nil { | if err != nil { | ||||
| ctx.Handle(200, "repo.Single", err) | |||||
| ctx.Render.Error(404) | |||||
| return | return | ||||
| } | } | ||||
| ctx.Data["LatestCommit"] = commit | ctx.Data["LatestCommit"] = commit | ||||
| // README. | |||||
| // for _, f := range files { | |||||
| // if f.Name == "README.md" { | |||||
| // ctx.Data["ReadmeName"] = "README.md" | |||||
| // ctx.Data["ReadmeContent"] = | |||||
| // break | |||||
| // } | |||||
| // } | |||||
| var readmeFile *models.RepoFile | |||||
| for _, f := range files { | |||||
| if !f.IsFile() { | |||||
| continue | |||||
| } | |||||
| if len(f.Name) < 6 { | |||||
| continue | |||||
| } | |||||
| if strings.ToLower(f.Name[:6]) == "readme" { | |||||
| readmeFile = f | |||||
| break | |||||
| } | |||||
| } | |||||
| if readmeFile != nil { | |||||
| // if file large than 1M not show it | |||||
| if readmeFile.Size > 1024*1024 || readmeFile.Filemode != git.FileModeBlob { | |||||
| ctx.Data["FileIsLarge"] = true | |||||
| } else if blob, err := readmeFile.LookupBlob(); err != nil { | |||||
| ctx.Data["FileIsLarge"] = true | |||||
| } else { | |||||
| ctx.Data["ReadmeContent"] = string(base.RenderMarkdown(blob.Contents())) | |||||
| } | |||||
| } | |||||
| ctx.Data["Paths"] = Paths | ctx.Data["Paths"] = Paths | ||||
| ctx.Data["Treenames"] = treenames | ctx.Data["Treenames"] = treenames | ||||
| @@ -87,9 +87,15 @@ | |||||
| <div class="panel-heading file-head"> | <div class="panel-heading file-head"> | ||||
| <i class="icon fa fa-book"></i> README.md | <i class="icon fa fa-book"></i> README.md | ||||
| </div> | </div> | ||||
| <div class="panel-body file-body markdown"> | |||||
| markdown content | |||||
| </div> | |||||
| {{if .FileIsLarge}} | |||||
| <div class="panel-footer"> | |||||
| Large file size 1000kb | |||||
| </div> | |||||
| {{else}} | |||||
| <div class="panel-body file-body markdown"> | |||||
| {{.ReadmeContent|str2html}} | |||||
| </div> | |||||
| {{end}} | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||