Stable APIs for Go. https://go.code.as
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

243 lines
6.1 KiB

  1. package main
  2. import (
  3. "fmt"
  4. "html/template"
  5. "log"
  6. "net/http"
  7. "os"
  8. "sort"
  9. "strings"
  10. )
  11. const packageTemplateString = `<!DOCTYPE html>
  12. <html >
  13. <head>
  14. <meta charset="utf-8">
  15. <title>{{.Repo.PackageName}}.{{.Repo.MajorVersion}}{{.Repo.SubPath}} - {{.Repo.GopkgPath}}</title>
  16. <link href='//fonts.googleapis.com/css?family=Ubuntu+Mono|Ubuntu' rel='stylesheet' >
  17. <link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet" >
  18. <link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet" >
  19. <style>
  20. html,
  21. body {
  22. height: 100%;
  23. }
  24. @media (min-width: 1200px) {
  25. .container {
  26. width: 970px;
  27. }
  28. }
  29. body {
  30. font-family: 'Ubuntu', sans-serif;
  31. }
  32. pre {
  33. font-family: 'Ubuntu Mono', sans-serif;
  34. }
  35. .main {
  36. padding-top: 20px;
  37. }
  38. .getting-started div {
  39. padding-top: 12px;
  40. }
  41. .getting-started p {
  42. font-size: 1.3em;
  43. }
  44. .getting-started pre {
  45. font-size: 15px;
  46. }
  47. .versions {
  48. font-size: 1.3em;
  49. }
  50. .versions div {
  51. padding-top: 5px;
  52. }
  53. .versions a {
  54. font-weight: bold;
  55. }
  56. .versions a.current {
  57. color: black;
  58. font-decoration: none;
  59. }
  60. /* wrapper for page content to push down footer */
  61. #wrap {
  62. min-height: 100%;
  63. height: auto !important;
  64. height: 100%;
  65. /* negative indent footer by it's height */
  66. margin: 0 auto -40px;
  67. }
  68. /* footer styling */
  69. #footer {
  70. height: 40px;
  71. background-color: #eee;
  72. padding-top: 8px;
  73. text-align: center;
  74. }
  75. /* footer fixes for mobile devices */
  76. @media (max-width: 767px) {
  77. #footer {
  78. margin-left: -20px;
  79. margin-right: -20px;
  80. padding-left: 20px;
  81. padding-right: 20px;
  82. }
  83. }
  84. </style>
  85. </head>
  86. <body>
  87. <script type="text/javascript">
  88. // If there's a URL fragment, assume it's an attempt to read a specific documentation entry.
  89. if (window.location.hash.length > 1) {
  90. window.location = "http://godoc.org/{{.Repo.GopkgPath}}" + window.location.hash;
  91. }
  92. </script>
  93. <div id="wrap" >
  94. <div class="container" >
  95. <div class="row" >
  96. <div class="col-sm-12" >
  97. <div class="page-header">
  98. <h1>{{.Repo.GopkgPath}}</h1>
  99. </div>
  100. </div>
  101. </div>
  102. <div class="row" >
  103. <div class="col-sm-12" >
  104. <a class="btn btn-lg btn-info" href="https://{{.Repo.GitHubRoot}}/tree/{{if .Repo.AllVersions}}{{.FullVersion}}{{else}}master{{end}}{{.Repo.SubPath}}" ><i class="fa fa-github"></i> Source Code</a>
  105. <a class="btn btn-lg btn-info" href="http://godoc.org/{{.Repo.GopkgPath}}" ><i class="fa fa-info-circle"></i> API Documentation</a>
  106. </div>
  107. </div>
  108. <div class="row main" >
  109. <div class="col-sm-8 info" >
  110. <div class="getting-started" >
  111. <h2>Getting started</h2>
  112. <div>
  113. <p>To get the package, execute:</p>
  114. <pre>go get {{.Repo.GopkgPath}}</pre>
  115. </div>
  116. <div>
  117. <p>To import this package, add the following line to your code:</p>
  118. <pre>import "{{.Repo.GopkgPath}}"</pre>
  119. {{if .CleanPackageName}}<p>Refer to it as <i>{{.CleanPackageName}}</i>.{{end}}
  120. </div>
  121. <div>
  122. <p>For more details, see the API documentation.</p>
  123. </div>
  124. </div>
  125. </div>
  126. <div class="col-sm-3 col-sm-offset-1 versions" >
  127. <h2>Versions</h2>
  128. {{ if .LatestVersions }}
  129. {{ range .LatestVersions }}
  130. <div>
  131. <a href="//{{gopkgVersionRoot $.Repo .}}{{$.Repo.SubPath}}" {{if eq .Major $.Repo.MajorVersion.Major}}class="current"{{end}} >v{{.Major}}</a>
  132. &rarr;
  133. <span class="label label-default">{{.}}</span>
  134. </div>
  135. {{ end }}
  136. {{ else }}
  137. <div>
  138. <a href="//{{$.Repo.GopkgPath}}" class="current">v0</a>
  139. &rarr;
  140. <span class="label label-default">master</span>
  141. </div>
  142. {{ end }}
  143. </div>
  144. </div>
  145. </div>
  146. </div>
  147. <div id="footer">
  148. <div class="container">
  149. <div class="row">
  150. <div class="col-sm-12">
  151. <p class="text-muted credit"><a href="https://gopkg.in">gopkg.in<a></p>
  152. </div>
  153. </div>
  154. </div>
  155. </div>
  156. <!--<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>-->
  157. <!--<script src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>-->
  158. </body>
  159. </html>`
  160. var packageTemplate *template.Template
  161. func gopkgVersionRoot(repo *Repo, version Version) string {
  162. return repo.GopkgVersionRoot(version)
  163. }
  164. var packageFuncs = template.FuncMap{
  165. "gopkgVersionRoot": gopkgVersionRoot,
  166. }
  167. func init() {
  168. var err error
  169. packageTemplate, err = template.New("page").Funcs(packageFuncs).Parse(packageTemplateString)
  170. if err != nil {
  171. fmt.Fprintf(os.Stderr, "fatal: parsing package template failed: %s\n", err)
  172. os.Exit(1)
  173. }
  174. }
  175. type packageData struct {
  176. Repo *Repo
  177. LatestVersions VersionList // Contains only the latest version for each major
  178. FullVersion Version // Version that the major requested resolves to
  179. CleanPackageName string
  180. }
  181. func renderPackagePage(resp http.ResponseWriter, req *http.Request, repo *Repo) {
  182. data := &packageData{
  183. Repo: repo,
  184. }
  185. latestVersionsMap := make(map[int]Version)
  186. for _, v := range repo.AllVersions {
  187. v2, exists := latestVersionsMap[v.Major]
  188. if !exists || v2.Less(v) {
  189. latestVersionsMap[v.Major] = v
  190. }
  191. }
  192. data.FullVersion = latestVersionsMap[repo.MajorVersion.Major]
  193. data.LatestVersions = make(VersionList, 0, len(latestVersionsMap))
  194. for _, v := range latestVersionsMap {
  195. data.LatestVersions = append(data.LatestVersions, v)
  196. }
  197. sort.Sort(sort.Reverse(data.LatestVersions))
  198. data.CleanPackageName = repo.PackageName
  199. if strings.HasPrefix(data.CleanPackageName, "go-") {
  200. data.CleanPackageName = data.CleanPackageName[3:]
  201. }
  202. if strings.HasSuffix(data.CleanPackageName, "-go") {
  203. data.CleanPackageName = data.CleanPackageName[:len(data.CleanPackageName)-3]
  204. }
  205. for i, c := range data.CleanPackageName {
  206. if c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' {
  207. continue
  208. }
  209. if i > 0 && (c == '_' || c >= '0' && c <= '9') {
  210. continue
  211. }
  212. data.CleanPackageName = ""
  213. break
  214. }
  215. err := packageTemplate.Execute(resp, data)
  216. if err != nil {
  217. log.Printf("error executing tmplPackage: %s\n", err)
  218. }
  219. }