whatcanGOwrong
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 13 KiB |
@@ -0,0 +1,254 @@
|
||||
<!--{
|
||||
"Title": "Static analysis features of godoc"
|
||||
}-->
|
||||
|
||||
<style>
|
||||
span.err { 'font-size:120%; color:darkred; background-color: yellow; }
|
||||
img.ss { margin-left: 1in; } /* screenshot */
|
||||
img.dotted { border: thin dotted; }
|
||||
</style>
|
||||
|
||||
<!-- Images were grabbed from Chrome/Linux at 150% zoom, and are
|
||||
displayed at 66% of natural size. This allows users to zoom a
|
||||
little before seeing pixels. -->
|
||||
|
||||
<p>
|
||||
When invoked with the <code>-analysis</code> flag, godoc performs
|
||||
static analysis on the Go packages it indexes and displays the
|
||||
results in the source and package views. This document provides a
|
||||
brief tour of these features.
|
||||
</p>
|
||||
|
||||
<h2>Type analysis features</h2>
|
||||
<p>
|
||||
<code>godoc -analysis=type</code> performs static checking similar
|
||||
to that done by a compiler: it detects ill-formed programs, resolves
|
||||
each identifier to the entity it denotes, computes the type of each
|
||||
expression and the method set of each type, and determines which
|
||||
types are assignable to each interface type.
|
||||
|
||||
<b>Type analysis</b> is relatively quick, requiring about 10 seconds for
|
||||
the >200 packages of the standard library, for example.
|
||||
</p>
|
||||
|
||||
<h3>Compiler errors</h3>
|
||||
<p>
|
||||
If any source file contains a compilation error, the source view
|
||||
will highlight the errant location in red. Hovering over it
|
||||
displays the error message.
|
||||
</p>
|
||||
<img class="ss" width='811' src='error1.png'><br/>
|
||||
|
||||
<h3>Identifier resolution</h3>
|
||||
<p>
|
||||
In the source view, every referring identifier is annotated with
|
||||
information about the language entity it refers to: a package,
|
||||
constant, variable, type, function or statement label.
|
||||
|
||||
Hovering over the identifier reveals the entity's kind and type
|
||||
(e.g. <code>var x int</code> or <code>func f
|
||||
func(int) string</code>).
|
||||
</p>
|
||||
<img class="ss" width='652' src='ident-field.png'><br/>
|
||||
<br/>
|
||||
<img class="ss" width='652' src='ident-func.png'>
|
||||
<p>
|
||||
Clicking the link takes you to the entity's definition.
|
||||
</p>
|
||||
<img class="ss" width='652' src='ident-def.png'><br/>
|
||||
|
||||
<h3>Type information: size/alignment, method set, interfaces</h3>
|
||||
<p>
|
||||
Clicking on the identifier that defines a named type causes a panel
|
||||
to appear, displaying information about the named type, including
|
||||
its size and alignment in bytes, its
|
||||
<a href='https://golang.org/ref/spec#Method_sets'>method set</a>, and its
|
||||
<i>implements</i> relation: the set of types T that are assignable to
|
||||
or from this type U where at least one of T or U is an interface.
|
||||
|
||||
This example shows information about <code>net/rpc.methodType</code>.
|
||||
</p>
|
||||
<img class="ss" width='470' src='typeinfo-src.png'>
|
||||
<p>
|
||||
The method set includes not only the declared methods of the type,
|
||||
but also any methods "promoted" from anonymous fields of structs,
|
||||
such as <code>sync.Mutex</code> in this example.
|
||||
|
||||
In addition, the receiver type is displayed as <code>*T</code> or
|
||||
<code>T</code> depending on whether it requires the address or just
|
||||
a copy of the receiver value.
|
||||
</p>
|
||||
<p>
|
||||
The method set and <i>implements</i> relation are also available
|
||||
via the package view.
|
||||
</p>
|
||||
<img class="ss dotted" width='716' src='typeinfo-pkg.png'>
|
||||
|
||||
<h2>Pointer analysis features</h2>
|
||||
<p>
|
||||
<code>godoc -analysis=pointer</code> additionally performs a precise
|
||||
whole-program <b>pointer analysis</b>. In other words, it
|
||||
approximates the set of memory locations to which each
|
||||
reference—not just vars of kind <code>*T</code>, but also
|
||||
<code>[]T</code>, <code>func</code>, <code>map</code>,
|
||||
<code>chan</code>, and <code>interface</code>—may refer. This
|
||||
information reveals the possible destinations of each dynamic call
|
||||
(via a <code>func</code> variable or interface method), and the
|
||||
relationship between send and receive operations on the same
|
||||
channel.
|
||||
</p>
|
||||
<p>
|
||||
Compared to type analysis, pointer analysis requires more time and
|
||||
memory, and is impractical for code bases exceeding a million lines.
|
||||
</p>
|
||||
|
||||
<h3>Call graph navigation</h3>
|
||||
<p>
|
||||
When pointer analysis is complete, the source view annotates the
|
||||
code with <b>callers</b> and <b>callees</b> information: callers
|
||||
information is associated with the <code>func</code> keyword that
|
||||
declares a function, and callees information is associated with the
|
||||
open paren '<span style="color: dark-blue"><code>(</code></span>' of
|
||||
a function call.
|
||||
</p>
|
||||
<p>
|
||||
In this example, hovering over the declaration of the
|
||||
<code>rot13</code> function (defined in strings/strings_test.go)
|
||||
reveals that it is called in exactly one place.
|
||||
</p>
|
||||
<img class="ss" width='612' src='callers1.png'>
|
||||
<p>
|
||||
Clicking the link navigates to the sole caller. (If there were
|
||||
multiple callers, a list of choices would be displayed first.)
|
||||
</p>
|
||||
<img class="ss" width='680' src='callers2.png'>
|
||||
<p>
|
||||
Notice that hovering over this call reveals that there are 19
|
||||
possible callees at this site, of which our <code>rot13</code>
|
||||
function was just one: this is a dynamic call through a variable of
|
||||
type <code>func(rune) rune</code>.
|
||||
|
||||
Clicking on the call brings up the list of all 19 potential callees,
|
||||
shown truncated. Many of them are anonymous functions.
|
||||
</p>
|
||||
<img class="ss" width='564' src='call3.png'>
|
||||
<p>
|
||||
Pointer analysis gives a very precise approximation of the call
|
||||
graph compared to type-based techniques.
|
||||
|
||||
As a case in point, the next example shows the dynamic call inside
|
||||
the <code>testing</code> package responsible for calling all
|
||||
user-defined functions named <code>Example<i>XYZ</i></code>.
|
||||
</p>
|
||||
<img class="ss" width='361' src='call-eg.png'>
|
||||
<p>
|
||||
Recall that all such functions have type <code>func()</code>,
|
||||
i.e. no arguments and no results. A type-based approximation could
|
||||
only conclude that this call might dispatch to any function matching
|
||||
that type—and these are very numerous in most
|
||||
programs—but pointer analysis can track the flow of specific
|
||||
<code>func</code> values through the testing package.
|
||||
|
||||
As an indication of its precision, the result contains only
|
||||
functions whose name starts with <code>Example</code>.
|
||||
</p>
|
||||
|
||||
<h3>Intra-package call graph</h3>
|
||||
<p>
|
||||
The same call graph information is presented in a very different way
|
||||
in the package view. For each package, an interactive tree view
|
||||
allows exploration of the call graph as it relates to just that
|
||||
package; all functions from other packages are elided.
|
||||
|
||||
The roots of the tree are the external entry points of the package:
|
||||
not only its exported functions, but also any unexported or
|
||||
anonymous functions that are called (dynamically) from outside the
|
||||
package.
|
||||
</p>
|
||||
<p>
|
||||
This example shows the entry points of the
|
||||
<code>path/filepath</code> package, with the call graph for
|
||||
<code>Glob</code> expanded several levels
|
||||
</p>
|
||||
<img class="ss dotted" width='501' src='ipcg-pkg.png'>
|
||||
<p>
|
||||
Notice that the nodes for Glob and Join appear multiple times: the
|
||||
tree is a partial unrolling of a cyclic graph; the full unrolling
|
||||
is in general infinite.
|
||||
</p>
|
||||
<p>
|
||||
For each function documented in the package view, another
|
||||
interactive tree view allows exploration of the same graph starting
|
||||
at that function.
|
||||
|
||||
This is a portion of the internal graph of
|
||||
<code>net/http.ListenAndServe</code>.
|
||||
</p>
|
||||
<img class="ss dotted" width='455' src='ipcg-func.png'>
|
||||
|
||||
<h3>Channel peers (send ↔ receive)</h3>
|
||||
<p>
|
||||
Because concurrent Go programs use channels to pass not just values
|
||||
but also control between different goroutines, it is natural when
|
||||
reading Go code to want to navigate from a channel send to the
|
||||
corresponding receive so as to understand the sequence of events.
|
||||
</p>
|
||||
<p>
|
||||
Godoc annotates every channel operation—make, send, range,
|
||||
receive, close—with a link to a panel displaying information
|
||||
about other operations that might alias the same channel.
|
||||
</p>
|
||||
<p>
|
||||
This example, from the tests of <code>net/http</code>, shows a send
|
||||
operation on a <code>chan bool</code>.
|
||||
</p>
|
||||
<img class="ss" width='811' src='chan1.png'>
|
||||
<p>
|
||||
Clicking on the <code><-</code> send operator reveals that this
|
||||
channel is made at a unique location (line 332) and that there are
|
||||
three receive operations that might read this value.
|
||||
|
||||
It hardly needs pointing out that some channel element types are
|
||||
very widely used (e.g. struct{}, bool, int, interface{}) and that a
|
||||
typical Go program might contain dozens of receive operations on a
|
||||
value of type <code>chan bool</code>; yet the pointer analysis is
|
||||
able to distinguish operations on channels at a much finer precision
|
||||
than based on their type alone.
|
||||
</p>
|
||||
<p>
|
||||
Notice also that the send occurs in a different (anonymous) function
|
||||
from the outer one containing the <code>make</code> and the receive
|
||||
operations.
|
||||
</p>
|
||||
<p>
|
||||
Here's another example of send on a different <code>chan
|
||||
bool</code>, also in package <code>net/http</code>:
|
||||
</p>
|
||||
<img class="ss" width='774' src='chan2a.png'>
|
||||
<p>
|
||||
The analysis finds just one receive operation that might receive
|
||||
from this channel, in the test for this feature.
|
||||
</p>
|
||||
<img class="ss" width='737' src='chan2b.png'>
|
||||
|
||||
<h2>Known issues</h2>
|
||||
<p>
|
||||
All analysis results pertain to exactly
|
||||
one configuration (e.g. amd64 linux). Files that are conditionally
|
||||
compiled based on different platforms or build tags are not visible
|
||||
to the analysis.
|
||||
</p>
|
||||
<p>
|
||||
Files that <code>import "C"</code> require
|
||||
preprocessing by the cgo tool. The file offsets after preprocessing
|
||||
do not align with the unpreprocessed file, so markup is misaligned.
|
||||
</p>
|
||||
<p>
|
||||
Files are not periodically re-analyzed.
|
||||
If the files change underneath the running server, the displayed
|
||||
markup is misaligned.
|
||||
</p>
|
||||
<p>
|
||||
Additional issues are listed at
|
||||
<a href='https://go.googlesource.com/tools/+/master/godoc/analysis/README'>tools/godoc/analysis/README</a>.
|
||||
</p>
|
||||
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 16 KiB |
@@ -0,0 +1,15 @@
|
||||
<div class="toggle" style="display: none">
|
||||
<div class="collapsed">
|
||||
<p class="exampleHeading toggleButton">▹ <span class="text">Internal call graph</span></p>
|
||||
</div>
|
||||
<div class="expanded">
|
||||
<p class="exampleHeading toggleButton">▾ <span class="text">Internal call graph</span></p>
|
||||
<p>
|
||||
This viewer shows the portion of the internal call
|
||||
graph of this package that is reachable from this function.
|
||||
See the <a href='#pkg-callgraph'>package's call
|
||||
graph</a> for more information.
|
||||
</p>
|
||||
<ul style="margin-left: 0.5in" id="callgraph-{{.Index}}" class="treeview"></ul>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,31 @@
|
||||
<!--
|
||||
Copyright 2009 The Go Authors. All rights reserved.
|
||||
Use of this source code is governed by a BSD-style
|
||||
license that can be found in the LICENSE file.
|
||||
-->
|
||||
|
||||
<p>
|
||||
<table class="layout">
|
||||
<tr>
|
||||
<th align="left">File</th>
|
||||
<td width="25"> </td>
|
||||
<th align="right">Bytes</th>
|
||||
<td width="25"> </td>
|
||||
<th align="left">Modified</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="..">..</a></td>
|
||||
</tr>
|
||||
{{range .}}
|
||||
<tr>
|
||||
{{$name_html := fileInfoName . | html}}
|
||||
<td align="left"><a href="{{$name_html}}">{{$name_html}}</a></td>
|
||||
<td></td>
|
||||
<td align="right">{{html .Size}}</td>
|
||||
<td></td>
|
||||
<td align="left">{{fileInfoTime . | html}}</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
|
||||
</table>
|
||||
</p>
|
||||
@@ -0,0 +1,8 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package static exports a map of static file content that supports the godoc
|
||||
// user interface. The map should be used with the mapfs package, see
|
||||
// golang.org/x/tools/godoc/vfs/mapfs.
|
||||
package static // import "golang.org/x/tools/godoc/static"
|
||||
@@ -0,0 +1,9 @@
|
||||
<!--
|
||||
Copyright 2009 The Go Authors. All rights reserved.
|
||||
Use of this source code is governed by a BSD-style
|
||||
license that can be found in the LICENSE file.
|
||||
-->
|
||||
|
||||
<p>
|
||||
<span class="alert" style="font-size:120%">{{html .}}</span>
|
||||
</p>
|
||||
@@ -0,0 +1,28 @@
|
||||
<div id="example_{{.Name}}" class="toggle">
|
||||
<div class="collapsed">
|
||||
<p class="exampleHeading toggleButton">▹ <span class="text">Example{{example_suffix .Name}}</span></p>
|
||||
</div>
|
||||
<div class="expanded">
|
||||
<p class="exampleHeading toggleButton">▾ <span class="text">Example{{example_suffix .Name}}</span></p>
|
||||
{{with .Doc}}<p>{{html .}}</p>{{end}}
|
||||
{{$output := .Output}}
|
||||
{{with .Play}}
|
||||
<div class="play">
|
||||
<div class="input"><textarea class="code" spellcheck="false">{{html .}}</textarea></div>
|
||||
<div class="output"><pre>{{html $output}}</pre></div>
|
||||
<div class="buttons">
|
||||
<a class="run" title="Run this code [shift-enter]">Run</a>
|
||||
<a class="fmt" title="Format this code">Format</a>
|
||||
<a class="share" title="Share this code">Share</a>
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<p>Code:</p>
|
||||
<pre class="code">{{.Code}}</pre>
|
||||
{{with .Output}}
|
||||
<p>Output:</p>
|
||||
<pre class="output">{{html .}}</pre>
|
||||
{{end}}
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
|
After Width: | Height: | Size: 5.6 KiB |
@@ -0,0 +1,107 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package static
|
||||
|
||||
//go:generate go run makestatic.go
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/format"
|
||||
"os"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
var files = []string{
|
||||
"analysis/call3.png",
|
||||
"analysis/call-eg.png",
|
||||
"analysis/callers1.png",
|
||||
"analysis/callers2.png",
|
||||
"analysis/chan1.png",
|
||||
"analysis/chan2a.png",
|
||||
"analysis/chan2b.png",
|
||||
"analysis/error1.png",
|
||||
"analysis/help.html",
|
||||
"analysis/ident-def.png",
|
||||
"analysis/ident-field.png",
|
||||
"analysis/ident-func.png",
|
||||
"analysis/ipcg-func.png",
|
||||
"analysis/ipcg-pkg.png",
|
||||
"analysis/typeinfo-pkg.png",
|
||||
"analysis/typeinfo-src.png",
|
||||
"callgraph.html",
|
||||
"dirlist.html",
|
||||
"error.html",
|
||||
"example.html",
|
||||
"favicon.ico",
|
||||
"godoc.html",
|
||||
"godocs.js",
|
||||
"gopher/pkg.png",
|
||||
"images/minus.gif",
|
||||
"images/plus.gif",
|
||||
"images/treeview-black-line.gif",
|
||||
"images/treeview-black.gif",
|
||||
"images/treeview-default-line.gif",
|
||||
"images/treeview-default.gif",
|
||||
"images/treeview-gray-line.gif",
|
||||
"images/treeview-gray.gif",
|
||||
"implements.html",
|
||||
"jquery.js",
|
||||
"jquery.treeview.css",
|
||||
"jquery.treeview.edit.js",
|
||||
"jquery.treeview.js",
|
||||
"methodset.html",
|
||||
"package.html",
|
||||
"packageroot.html",
|
||||
"play.js",
|
||||
"playground.js",
|
||||
"search.html",
|
||||
"searchcode.html",
|
||||
"searchdoc.html",
|
||||
"searchtxt.html",
|
||||
"style.css",
|
||||
}
|
||||
|
||||
// Generate reads a set of files and returns a file buffer that declares
|
||||
// a map of string constants containing contents of the input files.
|
||||
func Generate() ([]byte, error) {
|
||||
buf := new(bytes.Buffer)
|
||||
fmt.Fprintf(buf, "%v\n\n%v\n\npackage static\n\n", license, warning)
|
||||
fmt.Fprintf(buf, "var Files = map[string]string{\n")
|
||||
for _, fn := range files {
|
||||
b, err := os.ReadFile(fn)
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
fmt.Fprintf(buf, "\t%q: ", fn)
|
||||
appendQuote(buf, b)
|
||||
fmt.Fprintf(buf, ",\n\n")
|
||||
}
|
||||
fmt.Fprintln(buf, "}")
|
||||
return format.Source(buf.Bytes())
|
||||
}
|
||||
|
||||
// appendQuote is like strconv.AppendQuote, but we avoid the latter
|
||||
// because it changes when Unicode evolves, breaking gen_test.go.
|
||||
func appendQuote(out *bytes.Buffer, data []byte) {
|
||||
out.WriteByte('"')
|
||||
for _, b := range data {
|
||||
if b == '\\' || b == '"' {
|
||||
out.WriteByte('\\')
|
||||
out.WriteByte(b)
|
||||
} else if b <= unicode.MaxASCII && unicode.IsPrint(rune(b)) && !unicode.IsSpace(rune(b)) {
|
||||
out.WriteByte(b)
|
||||
} else {
|
||||
fmt.Fprintf(out, "\\x%02x", b)
|
||||
}
|
||||
}
|
||||
out.WriteByte('"')
|
||||
}
|
||||
|
||||
const warning = `// Code generated by "makestatic"; DO NOT EDIT.`
|
||||
|
||||
const license = `// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.`
|
||||
@@ -0,0 +1,53 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package static
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"os"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"testing"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
func TestStaticIsUpToDate(t *testing.T) {
|
||||
if runtime.GOOS == "android" {
|
||||
t.Skip("files not available on android")
|
||||
}
|
||||
oldBuf, err := os.ReadFile("static.go")
|
||||
if err != nil {
|
||||
t.Errorf("error while reading static.go: %v\n", err)
|
||||
}
|
||||
|
||||
newBuf, err := Generate()
|
||||
if err != nil {
|
||||
t.Errorf("error while generating static.go: %v\n", err)
|
||||
}
|
||||
|
||||
if !bytes.Equal(oldBuf, newBuf) {
|
||||
t.Error(`static.go is stale. Run:
|
||||
$ go generate golang.org/x/tools/godoc/static
|
||||
$ git diff
|
||||
to see the differences.`)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// TestAppendQuote ensures that AppendQuote produces a valid literal.
|
||||
func TestAppendQuote(t *testing.T) {
|
||||
var in, out bytes.Buffer
|
||||
for r := rune(0); r < unicode.MaxRune; r++ {
|
||||
in.WriteRune(r)
|
||||
}
|
||||
appendQuote(&out, in.Bytes())
|
||||
in2, err := strconv.Unquote(out.String())
|
||||
if err != nil {
|
||||
t.Fatalf("AppendQuote produced invalid string literal: %v", err)
|
||||
}
|
||||
if got, want := in2, in.String(); got != want {
|
||||
t.Fatal("AppendQuote modified string") // no point printing got/want: huge
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="theme-color" content="#375EAB">
|
||||
{{with .Tabtitle}}
|
||||
<title>{{html .}} - Go Documentation Server</title>
|
||||
{{else}}
|
||||
<title>Go Documentation Server</title>
|
||||
{{end}}
|
||||
<link type="text/css" rel="stylesheet" href="/lib/godoc/style.css">
|
||||
{{if .TreeView}}
|
||||
<link rel="stylesheet" href="/lib/godoc/jquery.treeview.css">
|
||||
{{end}}
|
||||
<script>window.initFuncs = [];</script>
|
||||
<script src="/lib/godoc/jquery.js" defer></script>
|
||||
{{if .TreeView}}
|
||||
<script src="/lib/godoc/jquery.treeview.js" defer></script>
|
||||
<script src="/lib/godoc/jquery.treeview.edit.js" defer></script>
|
||||
{{end}}
|
||||
|
||||
{{if .Playground}}
|
||||
<script src="/lib/godoc/playground.js" defer></script>
|
||||
{{end}}
|
||||
{{with .Version}}<script>var goVersion = {{printf "%q" .}};</script>{{end}}
|
||||
<script src="/lib/godoc/godocs.js" defer></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id='lowframe' style="position: fixed; bottom: 0; left: 0; height: 0; width: 100%; border-top: thin solid grey; background-color: white; overflow: auto;">
|
||||
...
|
||||
</div><!-- #lowframe -->
|
||||
|
||||
<div id="topbar"{{if .Title}} class="wide"{{end}}><div class="container">
|
||||
<div class="top-heading" id="heading-wide"><a href="/pkg/">Go Documentation Server</a></div>
|
||||
<div class="top-heading" id="heading-narrow"><a href="/pkg/">GoDoc</a></div>
|
||||
<a href="#" id="menu-button"><span id="menu-button-arrow">▽</span></a>
|
||||
<form method="GET" action="/search">
|
||||
<div id="menu">
|
||||
{{if (and .Playground .Title)}}
|
||||
<a id="playgroundButton" href="https://play.golang.org/" title="Show Go Playground">Play</a>
|
||||
{{end}}
|
||||
<span class="search-box"><input type="search" id="search" name="q" placeholder="Search" aria-label="Search" required><button type="submit"><span><!-- magnifying glass: --><svg width="24" height="24" viewBox="0 0 24 24"><title>submit search</title><path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/><path d="M0 0h24v24H0z" fill="none"/></svg></span></button></span>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div></div>
|
||||
|
||||
{{if .Playground}}
|
||||
<div id="playground" class="play">
|
||||
<div class="input"><textarea class="code" spellcheck="false">package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
fmt.Println("Hello, 世界")
|
||||
}</textarea></div>
|
||||
<div class="output"></div>
|
||||
<div class="buttons">
|
||||
<a class="run" title="Run this code [shift-enter]">Run</a>
|
||||
<a class="fmt" title="Format this code">Format</a>
|
||||
<a class="share" title="Share this code">Share</a>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
<div id="page"{{if .Title}} class="wide"{{end}}>
|
||||
<div class="container">
|
||||
|
||||
{{if or .Title .SrcPath}}
|
||||
<h1>
|
||||
{{html .Title}}
|
||||
{{html .SrcPath | srcBreadcrumb}}
|
||||
</h1>
|
||||
{{end}}
|
||||
|
||||
{{with .Subtitle}}
|
||||
<h2>{{html .}}</h2>
|
||||
{{end}}
|
||||
|
||||
{{with .SrcPath}}
|
||||
<h2>
|
||||
Documentation: {{html . | srcToPkgLink}}
|
||||
</h2>
|
||||
{{end}}
|
||||
|
||||
{{/* The Table of Contents is automatically inserted in this <div>.
|
||||
Do not delete this <div>. */}}
|
||||
<div id="nav"></div>
|
||||
|
||||
{{/* Body is HTML-escaped elsewhere */}}
|
||||
{{printf "%s" .Body}}
|
||||
|
||||
<div id="footer">
|
||||
Build version {{html .Version}}.<br>
|
||||
Except as <a href="https://developers.google.com/site-policies#restrictions">noted</a>,
|
||||
the content of this page is licensed under the
|
||||
Creative Commons Attribution 3.0 License,
|
||||
and code is licensed under a <a href="/LICENSE">BSD license</a>.<br>
|
||||
<a href="https://golang.org/doc/tos.html">Terms of Service</a> |
|
||||
<a href="https://www.google.com/intl/en/policies/privacy/">Privacy Policy</a>
|
||||
</div>
|
||||
|
||||
</div><!-- .container -->
|
||||
</div><!-- #page -->
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,688 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/* A little code to ease navigation of these documents.
|
||||
*
|
||||
* On window load we:
|
||||
* + Generate a table of contents (generateTOC)
|
||||
* + Bind foldable sections (bindToggles)
|
||||
* + Bind links to foldable sections (bindToggleLinks)
|
||||
*/
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
// Mobile-friendly topbar menu
|
||||
$(function() {
|
||||
var menu = $('#menu');
|
||||
var menuButton = $('#menu-button');
|
||||
var menuButtonArrow = $('#menu-button-arrow');
|
||||
menuButton.click(function(event) {
|
||||
menu.toggleClass('menu-visible');
|
||||
menuButtonArrow.toggleClass('vertical-flip');
|
||||
event.preventDefault();
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
/* Generates a table of contents: looks for h2 and h3 elements and generates
|
||||
* links. "Decorates" the element with id=="nav" with this table of contents.
|
||||
*/
|
||||
function generateTOC() {
|
||||
if ($('#manual-nav').length > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// For search, we send the toc precomputed from server-side.
|
||||
// TODO: Ideally, this should always be precomputed for all pages, but then
|
||||
// we need to do HTML parsing on the server-side.
|
||||
if (location.pathname === '/search') {
|
||||
return;
|
||||
}
|
||||
|
||||
var nav = $('#nav');
|
||||
if (nav.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var toc_items = [];
|
||||
$(nav)
|
||||
.nextAll('h2, h3')
|
||||
.each(function() {
|
||||
var node = this;
|
||||
if (node.id == '') node.id = 'tmp_' + toc_items.length;
|
||||
var link = $('<a/>')
|
||||
.attr('href', '#' + node.id)
|
||||
.text($(node).text());
|
||||
var item;
|
||||
if ($(node).is('h2')) {
|
||||
item = $('<dt/>');
|
||||
} else {
|
||||
// h3
|
||||
item = $('<dd class="indent"/>');
|
||||
}
|
||||
item.append(link);
|
||||
toc_items.push(item);
|
||||
});
|
||||
if (toc_items.length <= 1) {
|
||||
return;
|
||||
}
|
||||
var dl1 = $('<dl/>');
|
||||
var dl2 = $('<dl/>');
|
||||
|
||||
var split_index = toc_items.length / 2 + 1;
|
||||
if (split_index < 8) {
|
||||
split_index = toc_items.length;
|
||||
}
|
||||
for (var i = 0; i < split_index; i++) {
|
||||
dl1.append(toc_items[i]);
|
||||
}
|
||||
for (; /* keep using i */ i < toc_items.length; i++) {
|
||||
dl2.append(toc_items[i]);
|
||||
}
|
||||
|
||||
var tocTable = $('<table class="unruled"/>').appendTo(nav);
|
||||
var tocBody = $('<tbody/>').appendTo(tocTable);
|
||||
var tocRow = $('<tr/>').appendTo(tocBody);
|
||||
|
||||
// 1st column
|
||||
$('<td class="first"/>')
|
||||
.appendTo(tocRow)
|
||||
.append(dl1);
|
||||
// 2nd column
|
||||
$('<td/>')
|
||||
.appendTo(tocRow)
|
||||
.append(dl2);
|
||||
}
|
||||
|
||||
function bindToggle(el) {
|
||||
$('.toggleButton', el).click(function() {
|
||||
if ($(this).closest('.toggle, .toggleVisible')[0] != el) {
|
||||
// Only trigger the closest toggle header.
|
||||
return;
|
||||
}
|
||||
|
||||
if ($(el).is('.toggle')) {
|
||||
$(el)
|
||||
.addClass('toggleVisible')
|
||||
.removeClass('toggle');
|
||||
} else {
|
||||
$(el)
|
||||
.addClass('toggle')
|
||||
.removeClass('toggleVisible');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function bindToggles(selector) {
|
||||
$(selector).each(function(i, el) {
|
||||
bindToggle(el);
|
||||
});
|
||||
}
|
||||
|
||||
function bindToggleLink(el, prefix) {
|
||||
$(el).click(function() {
|
||||
var href = $(el).attr('href');
|
||||
var i = href.indexOf('#' + prefix);
|
||||
if (i < 0) {
|
||||
return;
|
||||
}
|
||||
var id = '#' + prefix + href.slice(i + 1 + prefix.length);
|
||||
if ($(id).is('.toggle')) {
|
||||
$(id)
|
||||
.find('.toggleButton')
|
||||
.first()
|
||||
.click();
|
||||
}
|
||||
});
|
||||
}
|
||||
function bindToggleLinks(selector, prefix) {
|
||||
$(selector).each(function(i, el) {
|
||||
bindToggleLink(el, prefix);
|
||||
});
|
||||
}
|
||||
|
||||
function setupDropdownPlayground() {
|
||||
if (!$('#page').is('.wide')) {
|
||||
return; // don't show on front page
|
||||
}
|
||||
var button = $('#playgroundButton');
|
||||
var div = $('#playground');
|
||||
var setup = false;
|
||||
button.toggle(
|
||||
function() {
|
||||
button.addClass('active');
|
||||
div.show();
|
||||
if (setup) {
|
||||
return;
|
||||
}
|
||||
setup = true;
|
||||
playground({
|
||||
codeEl: $('.code', div),
|
||||
outputEl: $('.output', div),
|
||||
runEl: $('.run', div),
|
||||
fmtEl: $('.fmt', div),
|
||||
shareEl: $('.share', div),
|
||||
shareRedirect: '//play.golang.org/p/',
|
||||
});
|
||||
},
|
||||
function() {
|
||||
button.removeClass('active');
|
||||
div.hide();
|
||||
}
|
||||
);
|
||||
$('#menu').css('min-width', '+=60');
|
||||
|
||||
// Hide inline playground if we click somewhere on the page.
|
||||
// This is needed in mobile devices, where the "Play" button
|
||||
// is not clickable once the playground opens up.
|
||||
$('#page').click(function() {
|
||||
if (button.hasClass('active')) {
|
||||
button.click();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function setupInlinePlayground() {
|
||||
'use strict';
|
||||
// Set up playground when each element is toggled.
|
||||
$('div.play').each(function(i, el) {
|
||||
// Set up playground for this example.
|
||||
var setup = function() {
|
||||
var code = $('.code', el);
|
||||
playground({
|
||||
codeEl: code,
|
||||
outputEl: $('.output', el),
|
||||
runEl: $('.run', el),
|
||||
fmtEl: $('.fmt', el),
|
||||
shareEl: $('.share', el),
|
||||
shareRedirect: '//play.golang.org/p/',
|
||||
});
|
||||
|
||||
// Make the code textarea resize to fit content.
|
||||
var resize = function() {
|
||||
code.height(0);
|
||||
var h = code[0].scrollHeight;
|
||||
code.height(h + 20); // minimize bouncing.
|
||||
code.closest('.input').height(h);
|
||||
};
|
||||
code.on('keydown', resize);
|
||||
code.on('keyup', resize);
|
||||
code.keyup(); // resize now.
|
||||
};
|
||||
|
||||
// If example already visible, set up playground now.
|
||||
if ($(el).is(':visible')) {
|
||||
setup();
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, set up playground when example is expanded.
|
||||
var built = false;
|
||||
$(el)
|
||||
.closest('.toggle')
|
||||
.click(function() {
|
||||
// Only set up once.
|
||||
if (!built) {
|
||||
setup();
|
||||
built = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// fixFocus tries to put focus to div#page so that keyboard navigation works.
|
||||
function fixFocus() {
|
||||
var page = $('div#page');
|
||||
var topbar = $('div#topbar');
|
||||
page.css('outline', 0); // disable outline when focused
|
||||
page.attr('tabindex', -1); // and set tabindex so that it is focusable
|
||||
$(window)
|
||||
.resize(function(evt) {
|
||||
// only focus page when the topbar is at fixed position (that is, it's in
|
||||
// front of page, and keyboard event will go to the former by default.)
|
||||
// by focusing page, keyboard event will go to page so that up/down arrow,
|
||||
// space, etc. will work as expected.
|
||||
if (topbar.css('position') == 'fixed') page.focus();
|
||||
})
|
||||
.resize();
|
||||
}
|
||||
|
||||
function toggleHash() {
|
||||
var id = window.location.hash.substring(1);
|
||||
// Open all of the toggles for a particular hash.
|
||||
var els = $(
|
||||
document.getElementById(id),
|
||||
$('a[name]').filter(function() {
|
||||
return $(this).attr('name') == id;
|
||||
})
|
||||
);
|
||||
|
||||
while (els.length) {
|
||||
for (var i = 0; i < els.length; i++) {
|
||||
var el = $(els[i]);
|
||||
if (el.is('.toggle')) {
|
||||
el.find('.toggleButton')
|
||||
.first()
|
||||
.click();
|
||||
}
|
||||
}
|
||||
els = el.parent();
|
||||
}
|
||||
}
|
||||
|
||||
function personalizeInstallInstructions() {
|
||||
var prefix = '?download=';
|
||||
var s = window.location.search;
|
||||
if (s.indexOf(prefix) != 0) {
|
||||
// No 'download' query string; detect "test" instructions from User Agent.
|
||||
if (navigator.platform.indexOf('Win') != -1) {
|
||||
$('.testUnix').hide();
|
||||
$('.testWindows').show();
|
||||
} else {
|
||||
$('.testUnix').show();
|
||||
$('.testWindows').hide();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var filename = s.substr(prefix.length);
|
||||
var filenameRE = /^go1\.\d+(\.\d+)?([a-z0-9]+)?\.([a-z0-9]+)(-[a-z0-9]+)?(-osx10\.[68])?\.([a-z.]+)$/;
|
||||
var m = filenameRE.exec(filename);
|
||||
if (!m) {
|
||||
// Can't interpret file name; bail.
|
||||
return;
|
||||
}
|
||||
$('.downloadFilename').text(filename);
|
||||
$('.hideFromDownload').hide();
|
||||
|
||||
var os = m[3];
|
||||
var ext = m[6];
|
||||
if (ext != 'tar.gz') {
|
||||
$('#tarballInstructions').hide();
|
||||
}
|
||||
if (os != 'darwin' || ext != 'pkg') {
|
||||
$('#darwinPackageInstructions').hide();
|
||||
}
|
||||
if (os != 'windows') {
|
||||
$('#windowsInstructions').hide();
|
||||
$('.testUnix').show();
|
||||
$('.testWindows').hide();
|
||||
} else {
|
||||
if (ext != 'msi') {
|
||||
$('#windowsInstallerInstructions').hide();
|
||||
}
|
||||
if (ext != 'zip') {
|
||||
$('#windowsZipInstructions').hide();
|
||||
}
|
||||
$('.testUnix').hide();
|
||||
$('.testWindows').show();
|
||||
}
|
||||
|
||||
var download = 'https://dl.google.com/go/' + filename;
|
||||
|
||||
var message = $(
|
||||
'<p class="downloading">' +
|
||||
'Your download should begin shortly. ' +
|
||||
'If it does not, click <a>this link</a>.</p>'
|
||||
);
|
||||
message.find('a').attr('href', download);
|
||||
message.insertAfter('#nav');
|
||||
|
||||
window.location = download;
|
||||
}
|
||||
|
||||
function updateVersionTags() {
|
||||
var v = window.goVersion;
|
||||
if (/^go[0-9.]+$/.test(v)) {
|
||||
$('.versionTag')
|
||||
.empty()
|
||||
.text(v);
|
||||
$('.whereTag').hide();
|
||||
}
|
||||
}
|
||||
|
||||
function addPermalinks() {
|
||||
function addPermalink(source, parent) {
|
||||
var id = source.attr('id');
|
||||
if (id == '' || id.indexOf('tmp_') === 0) {
|
||||
// Auto-generated permalink.
|
||||
return;
|
||||
}
|
||||
if (parent.find('> .permalink').length) {
|
||||
// Already attached.
|
||||
return;
|
||||
}
|
||||
parent
|
||||
.append(' ')
|
||||
.append($("<a class='permalink'>¶</a>").attr('href', '#' + id));
|
||||
}
|
||||
|
||||
$('#page .container')
|
||||
.find('h2[id], h3[id]')
|
||||
.each(function() {
|
||||
var el = $(this);
|
||||
addPermalink(el, el);
|
||||
});
|
||||
|
||||
$('#page .container')
|
||||
.find('dl[id]')
|
||||
.each(function() {
|
||||
var el = $(this);
|
||||
// Add the anchor to the "dt" element.
|
||||
addPermalink(el, el.find('> dt').first());
|
||||
});
|
||||
}
|
||||
|
||||
$('.js-expandAll').click(function() {
|
||||
if ($(this).hasClass('collapsed')) {
|
||||
toggleExamples('toggle');
|
||||
$(this).text('(Collapse All)');
|
||||
} else {
|
||||
toggleExamples('toggleVisible');
|
||||
$(this).text('(Expand All)');
|
||||
}
|
||||
$(this).toggleClass('collapsed');
|
||||
});
|
||||
|
||||
function toggleExamples(className) {
|
||||
// We need to explicitly iterate through divs starting with "example_"
|
||||
// to avoid toggling Overview and Index collapsibles.
|
||||
$("[id^='example_']").each(function() {
|
||||
// Check for state and click it only if required.
|
||||
if ($(this).hasClass(className)) {
|
||||
$(this)
|
||||
.find('.toggleButton')
|
||||
.first()
|
||||
.click();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
generateTOC();
|
||||
addPermalinks();
|
||||
bindToggles('.toggle');
|
||||
bindToggles('.toggleVisible');
|
||||
bindToggleLinks('.exampleLink', 'example_');
|
||||
bindToggleLinks('.overviewLink', '');
|
||||
bindToggleLinks('.examplesLink', '');
|
||||
bindToggleLinks('.indexLink', '');
|
||||
setupDropdownPlayground();
|
||||
setupInlinePlayground();
|
||||
fixFocus();
|
||||
setupTypeInfo();
|
||||
setupCallgraphs();
|
||||
toggleHash();
|
||||
personalizeInstallInstructions();
|
||||
updateVersionTags();
|
||||
|
||||
// godoc.html defines window.initFuncs in the <head> tag, and root.html and
|
||||
// codewalk.js push their on-page-ready functions to the list.
|
||||
// We execute those functions here, to avoid loading jQuery until the page
|
||||
// content is loaded.
|
||||
for (var i = 0; i < window.initFuncs.length; i++) window.initFuncs[i]();
|
||||
});
|
||||
|
||||
// -- analysis ---------------------------------------------------------
|
||||
|
||||
// escapeHTML returns HTML for s, with metacharacters quoted.
|
||||
// It is safe for use in both elements and attributes
|
||||
// (unlike the "set innerText, read innerHTML" trick).
|
||||
function escapeHTML(s) {
|
||||
return s
|
||||
.replace(/&/g, '&')
|
||||
.replace(/\"/g, '"')
|
||||
.replace(/\'/g, ''')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>');
|
||||
}
|
||||
|
||||
// makeAnchor returns HTML for an <a> element, given an anchorJSON object.
|
||||
function makeAnchor(json) {
|
||||
var html = escapeHTML(json.Text);
|
||||
if (json.Href != '') {
|
||||
html = "<a href='" + escapeHTML(json.Href) + "'>" + html + '</a>';
|
||||
}
|
||||
return html;
|
||||
}
|
||||
|
||||
function showLowFrame(html) {
|
||||
var lowframe = document.getElementById('lowframe');
|
||||
lowframe.style.height = '200px';
|
||||
lowframe.innerHTML =
|
||||
"<p style='text-align: left;'>" +
|
||||
html +
|
||||
'</p>\n' +
|
||||
"<div onclick='hideLowFrame()' style='position: absolute; top: 0; right: 0; cursor: pointer;'>✘</div>";
|
||||
}
|
||||
|
||||
document.hideLowFrame = function() {
|
||||
var lowframe = document.getElementById('lowframe');
|
||||
lowframe.style.height = '0px';
|
||||
};
|
||||
|
||||
// onClickCallers is the onclick action for the 'func' tokens of a
|
||||
// function declaration.
|
||||
document.onClickCallers = function(index) {
|
||||
var data = document.ANALYSIS_DATA[index];
|
||||
if (data.Callers.length == 1 && data.Callers[0].Sites.length == 1) {
|
||||
document.location = data.Callers[0].Sites[0].Href; // jump to sole caller
|
||||
return;
|
||||
}
|
||||
|
||||
var html =
|
||||
'Callers of <code>' + escapeHTML(data.Callee) + '</code>:<br/>\n';
|
||||
for (var i = 0; i < data.Callers.length; i++) {
|
||||
var caller = data.Callers[i];
|
||||
html += '<code>' + escapeHTML(caller.Func) + '</code>';
|
||||
var sites = caller.Sites;
|
||||
if (sites != null && sites.length > 0) {
|
||||
html += ' at line ';
|
||||
for (var j = 0; j < sites.length; j++) {
|
||||
if (j > 0) {
|
||||
html += ', ';
|
||||
}
|
||||
html += '<code>' + makeAnchor(sites[j]) + '</code>';
|
||||
}
|
||||
}
|
||||
html += '<br/>\n';
|
||||
}
|
||||
showLowFrame(html);
|
||||
};
|
||||
|
||||
// onClickCallees is the onclick action for the '(' token of a function call.
|
||||
document.onClickCallees = function(index) {
|
||||
var data = document.ANALYSIS_DATA[index];
|
||||
if (data.Callees.length == 1) {
|
||||
document.location = data.Callees[0].Href; // jump to sole callee
|
||||
return;
|
||||
}
|
||||
|
||||
var html = 'Callees of this ' + escapeHTML(data.Descr) + ':<br/>\n';
|
||||
for (var i = 0; i < data.Callees.length; i++) {
|
||||
html += '<code>' + makeAnchor(data.Callees[i]) + '</code><br/>\n';
|
||||
}
|
||||
showLowFrame(html);
|
||||
};
|
||||
|
||||
// onClickTypeInfo is the onclick action for identifiers declaring a named type.
|
||||
document.onClickTypeInfo = function(index) {
|
||||
var data = document.ANALYSIS_DATA[index];
|
||||
var html =
|
||||
'Type <code>' +
|
||||
data.Name +
|
||||
'</code>: ' +
|
||||
' <small>(size=' +
|
||||
data.Size +
|
||||
', align=' +
|
||||
data.Align +
|
||||
')</small><br/>\n';
|
||||
html += implementsHTML(data);
|
||||
html += methodsetHTML(data);
|
||||
showLowFrame(html);
|
||||
};
|
||||
|
||||
// implementsHTML returns HTML for the implements relation of the
|
||||
// specified TypeInfoJSON value.
|
||||
function implementsHTML(info) {
|
||||
var html = '';
|
||||
if (info.ImplGroups != null) {
|
||||
for (var i = 0; i < info.ImplGroups.length; i++) {
|
||||
var group = info.ImplGroups[i];
|
||||
var x = '<code>' + escapeHTML(group.Descr) + '</code> ';
|
||||
for (var j = 0; j < group.Facts.length; j++) {
|
||||
var fact = group.Facts[j];
|
||||
var y = '<code>' + makeAnchor(fact.Other) + '</code>';
|
||||
if (fact.ByKind != null) {
|
||||
html += escapeHTML(fact.ByKind) + ' type ' + y + ' implements ' + x;
|
||||
} else {
|
||||
html += x + ' implements ' + y;
|
||||
}
|
||||
html += '<br/>\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
return html;
|
||||
}
|
||||
|
||||
// methodsetHTML returns HTML for the methodset of the specified
|
||||
// TypeInfoJSON value.
|
||||
function methodsetHTML(info) {
|
||||
var html = '';
|
||||
if (info.Methods != null) {
|
||||
for (var i = 0; i < info.Methods.length; i++) {
|
||||
html += '<code>' + makeAnchor(info.Methods[i]) + '</code><br/>\n';
|
||||
}
|
||||
}
|
||||
return html;
|
||||
}
|
||||
|
||||
// onClickComm is the onclick action for channel "make" and "<-"
|
||||
// send/receive tokens.
|
||||
document.onClickComm = function(index) {
|
||||
var ops = document.ANALYSIS_DATA[index].Ops;
|
||||
if (ops.length == 1) {
|
||||
document.location = ops[0].Op.Href; // jump to sole element
|
||||
return;
|
||||
}
|
||||
|
||||
var html = 'Operations on this channel:<br/>\n';
|
||||
for (var i = 0; i < ops.length; i++) {
|
||||
html +=
|
||||
makeAnchor(ops[i].Op) +
|
||||
' by <code>' +
|
||||
escapeHTML(ops[i].Fn) +
|
||||
'</code><br/>\n';
|
||||
}
|
||||
if (ops.length == 0) {
|
||||
html += '(none)<br/>\n';
|
||||
}
|
||||
showLowFrame(html);
|
||||
};
|
||||
|
||||
$(window).load(function() {
|
||||
// Scroll window so that first selection is visible.
|
||||
// (This means we don't need to emit id='L%d' spans for each line.)
|
||||
// TODO(adonovan): ideally, scroll it so that it's under the pointer,
|
||||
// but I don't know how to get the pointer y coordinate.
|
||||
var elts = document.getElementsByClassName('selection');
|
||||
if (elts.length > 0) {
|
||||
elts[0].scrollIntoView();
|
||||
}
|
||||
});
|
||||
|
||||
// setupTypeInfo populates the "Implements" and "Method set" toggle for
|
||||
// each type in the package doc.
|
||||
function setupTypeInfo() {
|
||||
for (var i in document.ANALYSIS_DATA) {
|
||||
var data = document.ANALYSIS_DATA[i];
|
||||
|
||||
var el = document.getElementById('implements-' + i);
|
||||
if (el != null) {
|
||||
// el != null => data is TypeInfoJSON.
|
||||
if (data.ImplGroups != null) {
|
||||
el.innerHTML = implementsHTML(data);
|
||||
el.parentNode.parentNode.style.display = 'block';
|
||||
}
|
||||
}
|
||||
|
||||
var el = document.getElementById('methodset-' + i);
|
||||
if (el != null) {
|
||||
// el != null => data is TypeInfoJSON.
|
||||
if (data.Methods != null) {
|
||||
el.innerHTML = methodsetHTML(data);
|
||||
el.parentNode.parentNode.style.display = 'block';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setupCallgraphs() {
|
||||
if (document.CALLGRAPH == null) {
|
||||
return;
|
||||
}
|
||||
document.getElementById('pkg-callgraph').style.display = 'block';
|
||||
|
||||
var treeviews = document.getElementsByClassName('treeview');
|
||||
for (var i = 0; i < treeviews.length; i++) {
|
||||
var tree = treeviews[i];
|
||||
if (tree.id == null || tree.id.indexOf('callgraph-') != 0) {
|
||||
continue;
|
||||
}
|
||||
var id = tree.id.substring('callgraph-'.length);
|
||||
$(tree).treeview({ collapsed: true, animated: 'fast' });
|
||||
document.cgAddChildren(tree, tree, [id]);
|
||||
tree.parentNode.parentNode.style.display = 'block';
|
||||
}
|
||||
}
|
||||
|
||||
document.cgAddChildren = function(tree, ul, indices) {
|
||||
if (indices != null) {
|
||||
for (var i = 0; i < indices.length; i++) {
|
||||
var li = cgAddChild(tree, ul, document.CALLGRAPH[indices[i]]);
|
||||
if (i == indices.length - 1) {
|
||||
$(li).addClass('last');
|
||||
}
|
||||
}
|
||||
}
|
||||
$(tree).treeview({ animated: 'fast', add: ul });
|
||||
};
|
||||
|
||||
// cgAddChild adds an <li> element for document.CALLGRAPH node cgn to
|
||||
// the parent <ul> element ul. tree is the tree's root <ul> element.
|
||||
function cgAddChild(tree, ul, cgn) {
|
||||
var li = document.createElement('li');
|
||||
ul.appendChild(li);
|
||||
li.className = 'closed';
|
||||
|
||||
var code = document.createElement('code');
|
||||
|
||||
if (cgn.Callees != null) {
|
||||
$(li).addClass('expandable');
|
||||
|
||||
// Event handlers and innerHTML updates don't play nicely together,
|
||||
// hence all this explicit DOM manipulation.
|
||||
var hitarea = document.createElement('div');
|
||||
hitarea.className = 'hitarea expandable-hitarea';
|
||||
li.appendChild(hitarea);
|
||||
|
||||
li.appendChild(code);
|
||||
|
||||
var childUL = document.createElement('ul');
|
||||
li.appendChild(childUL);
|
||||
childUL.setAttribute('style', 'display: none;');
|
||||
|
||||
var onClick = function() {
|
||||
document.cgAddChildren(tree, childUL, cgn.Callees);
|
||||
hitarea.removeEventListener('click', onClick);
|
||||
};
|
||||
hitarea.addEventListener('click', onClick);
|
||||
} else {
|
||||
li.appendChild(code);
|
||||
}
|
||||
code.innerHTML += ' ' + makeAnchor(cgn.Func);
|
||||
return li;
|
||||
}
|
||||
})();
|
||||
|
After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 58 B |
|
After Width: | Height: | Size: 61 B |
|
After Width: | Height: | Size: 1010 B |
|
After Width: | Height: | Size: 381 B |
|
After Width: | Height: | Size: 848 B |
|
After Width: | Height: | Size: 387 B |
|
After Width: | Height: | Size: 1010 B |
|
After Width: | Height: | Size: 394 B |
@@ -0,0 +1,9 @@
|
||||
<div class="toggle" style="display: none">
|
||||
<div class="collapsed">
|
||||
<p class="exampleHeading toggleButton">▹ <span class="text">Implements</span></p>
|
||||
</div>
|
||||
<div class="expanded">
|
||||
<p class="exampleHeading toggleButton">▾ <span class="text">Implements</span></p>
|
||||
<div style="margin-left: 1in" id='implements-{{.Index}}'>...</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,76 @@
|
||||
/* https://github.com/jzaefferer/jquery-treeview/blob/1.4.2/jquery.treeview.css */
|
||||
/* License: MIT. */
|
||||
.treeview, .treeview ul {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.treeview ul {
|
||||
background-color: white;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.treeview .hitarea {
|
||||
background: url(images/treeview-default.gif) -64px -25px no-repeat;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
margin-left: -16px;
|
||||
float: left;
|
||||
cursor: pointer;
|
||||
}
|
||||
/* fix for IE6 */
|
||||
* html .hitarea {
|
||||
display: inline;
|
||||
float:none;
|
||||
}
|
||||
|
||||
.treeview li {
|
||||
margin: 0;
|
||||
padding: 3px 0pt 3px 16px;
|
||||
}
|
||||
|
||||
.treeview a.selected {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
#treecontrol { margin: 1em 0; display: none; }
|
||||
|
||||
.treeview .hover { color: red; cursor: pointer; }
|
||||
|
||||
.treeview li { background: url(images/treeview-default-line.gif) 0 0 no-repeat; }
|
||||
.treeview li.collapsable, .treeview li.expandable { background-position: 0 -176px; }
|
||||
|
||||
.treeview .expandable-hitarea { background-position: -80px -3px; }
|
||||
|
||||
.treeview li.last { background-position: 0 -1766px }
|
||||
.treeview li.lastCollapsable, .treeview li.lastExpandable { background-image: url(images/treeview-default.gif); }
|
||||
.treeview li.lastCollapsable { background-position: 0 -111px }
|
||||
.treeview li.lastExpandable { background-position: -32px -67px }
|
||||
|
||||
.treeview div.lastCollapsable-hitarea, .treeview div.lastExpandable-hitarea { background-position: 0; }
|
||||
|
||||
.treeview-red li { background-image: url(images/treeview-red-line.gif); }
|
||||
.treeview-red .hitarea, .treeview-red li.lastCollapsable, .treeview-red li.lastExpandable { background-image: url(images/treeview-red.gif); }
|
||||
|
||||
.treeview-black li { background-image: url(images/treeview-black-line.gif); }
|
||||
.treeview-black .hitarea, .treeview-black li.lastCollapsable, .treeview-black li.lastExpandable { background-image: url(images/treeview-black.gif); }
|
||||
|
||||
.treeview-gray li { background-image: url(images/treeview-gray-line.gif); }
|
||||
.treeview-gray .hitarea, .treeview-gray li.lastCollapsable, .treeview-gray li.lastExpandable { background-image: url(images/treeview-gray.gif); }
|
||||
|
||||
.treeview-famfamfam li { background-image: url(images/treeview-famfamfam-line.gif); }
|
||||
.treeview-famfamfam .hitarea, .treeview-famfamfam li.lastCollapsable, .treeview-famfamfam li.lastExpandable { background-image: url(images/treeview-famfamfam.gif); }
|
||||
|
||||
.treeview .placeholder {
|
||||
background: url(images/ajax-loader.gif) 0 0 no-repeat;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.filetree li { padding: 3px 0 2px 16px; }
|
||||
.filetree span.folder, .filetree span.file { padding: 1px 0 1px 16px; display: block; }
|
||||
.filetree span.folder { background: url(images/folder.gif) 0 0 no-repeat; }
|
||||
.filetree li.expandable span.folder { background: url(images/folder-closed.gif) 0 0 no-repeat; }
|
||||
.filetree span.file { background: url(images/file.gif) 0 0 no-repeat; }
|
||||
@@ -0,0 +1,39 @@
|
||||
/* https://github.com/jzaefferer/jquery-treeview/blob/1.4.2/jquery.treeview.edit.js */
|
||||
/* License: MIT. */
|
||||
(function($) {
|
||||
var CLASSES = $.treeview.classes;
|
||||
var proxied = $.fn.treeview;
|
||||
$.fn.treeview = function(settings) {
|
||||
settings = $.extend({}, settings);
|
||||
if (settings.add) {
|
||||
return this.trigger("add", [settings.add]);
|
||||
}
|
||||
if (settings.remove) {
|
||||
return this.trigger("remove", [settings.remove]);
|
||||
}
|
||||
return proxied.apply(this, arguments).bind("add", function(event, branches) {
|
||||
$(branches).prev()
|
||||
.removeClass(CLASSES.last)
|
||||
.removeClass(CLASSES.lastCollapsable)
|
||||
.removeClass(CLASSES.lastExpandable)
|
||||
.find(">.hitarea")
|
||||
.removeClass(CLASSES.lastCollapsableHitarea)
|
||||
.removeClass(CLASSES.lastExpandableHitarea);
|
||||
$(branches).find("li").andSelf().prepareBranches(settings).applyClasses(settings, $(this).data("toggler"));
|
||||
}).bind("remove", function(event, branches) {
|
||||
var prev = $(branches).prev();
|
||||
var parent = $(branches).parent();
|
||||
$(branches).remove();
|
||||
prev.filter(":last-child").addClass(CLASSES.last)
|
||||
.filter("." + CLASSES.expandable).replaceClass(CLASSES.last, CLASSES.lastExpandable).end()
|
||||
.find(">.hitarea").replaceClass(CLASSES.expandableHitarea, CLASSES.lastExpandableHitarea).end()
|
||||
.filter("." + CLASSES.collapsable).replaceClass(CLASSES.last, CLASSES.lastCollapsable).end()
|
||||
.find(">.hitarea").replaceClass(CLASSES.collapsableHitarea, CLASSES.lastCollapsableHitarea);
|
||||
if (parent.is(":not(:has(>))") && parent[0] != this) {
|
||||
parent.parent().removeClass(CLASSES.collapsable).removeClass(CLASSES.expandable)
|
||||
parent.siblings(".hitarea").andSelf().remove();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
})(jQuery);
|
||||
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
* Treeview 1.4.2 - jQuery plugin to hide and show branches of a tree
|
||||
*
|
||||
* http://bassistance.de/jquery-plugins/jquery-plugin-treeview/
|
||||
*
|
||||
* Copyright Jörn Zaefferer
|
||||
* Released under the MIT license:
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
;(function($) {
|
||||
|
||||
// TODO rewrite as a widget, removing all the extra plugins
|
||||
$.extend($.fn, {
|
||||
swapClass: function(c1, c2) {
|
||||
var c1Elements = this.filter('.' + c1);
|
||||
this.filter('.' + c2).removeClass(c2).addClass(c1);
|
||||
c1Elements.removeClass(c1).addClass(c2);
|
||||
return this;
|
||||
},
|
||||
replaceClass: function(c1, c2) {
|
||||
return this.filter('.' + c1).removeClass(c1).addClass(c2).end();
|
||||
},
|
||||
hoverClass: function(className) {
|
||||
className = className || "hover";
|
||||
return this.hover(function() {
|
||||
$(this).addClass(className);
|
||||
}, function() {
|
||||
$(this).removeClass(className);
|
||||
});
|
||||
},
|
||||
heightToggle: function(animated, callback) {
|
||||
animated ?
|
||||
this.animate({ height: "toggle" }, animated, callback) :
|
||||
this.each(function(){
|
||||
jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ]();
|
||||
if(callback)
|
||||
callback.apply(this, arguments);
|
||||
});
|
||||
},
|
||||
heightHide: function(animated, callback) {
|
||||
if (animated) {
|
||||
this.animate({ height: "hide" }, animated, callback);
|
||||
} else {
|
||||
this.hide();
|
||||
if (callback)
|
||||
this.each(callback);
|
||||
}
|
||||
},
|
||||
prepareBranches: function(settings) {
|
||||
if (!settings.prerendered) {
|
||||
// mark last tree items
|
||||
this.filter(":last-child:not(ul)").addClass(CLASSES.last);
|
||||
// collapse whole tree, or only those marked as closed, anyway except those marked as open
|
||||
this.filter((settings.collapsed ? "" : "." + CLASSES.closed) + ":not(." + CLASSES.open + ")").find(">ul").hide();
|
||||
}
|
||||
// return all items with sublists
|
||||
return this.filter(":has(>ul)");
|
||||
},
|
||||
applyClasses: function(settings, toggler) {
|
||||
// TODO use event delegation
|
||||
this.filter(":has(>ul):not(:has(>a))").find(">span").unbind("click.treeview").bind("click.treeview", function(event) {
|
||||
// don't handle click events on children, eg. checkboxes
|
||||
if ( this == event.target )
|
||||
toggler.apply($(this).next());
|
||||
}).add( $("a", this) ).hoverClass();
|
||||
|
||||
if (!settings.prerendered) {
|
||||
// handle closed ones first
|
||||
this.filter(":has(>ul:hidden)")
|
||||
.addClass(CLASSES.expandable)
|
||||
.replaceClass(CLASSES.last, CLASSES.lastExpandable);
|
||||
|
||||
// handle open ones
|
||||
this.not(":has(>ul:hidden)")
|
||||
.addClass(CLASSES.collapsable)
|
||||
.replaceClass(CLASSES.last, CLASSES.lastCollapsable);
|
||||
|
||||
// create hitarea if not present
|
||||
var hitarea = this.find("div." + CLASSES.hitarea);
|
||||
if (!hitarea.length)
|
||||
hitarea = this.prepend("<div class=\"" + CLASSES.hitarea + "\"/>").find("div." + CLASSES.hitarea);
|
||||
hitarea.removeClass().addClass(CLASSES.hitarea).each(function() {
|
||||
var classes = "";
|
||||
$.each($(this).parent().attr("class").split(" "), function() {
|
||||
classes += this + "-hitarea ";
|
||||
});
|
||||
$(this).addClass( classes );
|
||||
})
|
||||
}
|
||||
|
||||
// apply event to hitarea
|
||||
this.find("div." + CLASSES.hitarea).click( toggler );
|
||||
},
|
||||
treeview: function(settings) {
|
||||
|
||||
settings = $.extend({
|
||||
cookieId: "treeview"
|
||||
}, settings);
|
||||
|
||||
if ( settings.toggle ) {
|
||||
var callback = settings.toggle;
|
||||
settings.toggle = function() {
|
||||
return callback.apply($(this).parent()[0], arguments);
|
||||
};
|
||||
}
|
||||
|
||||
// factory for treecontroller
|
||||
function treeController(tree, control) {
|
||||
// factory for click handlers
|
||||
function handler(filter) {
|
||||
return function() {
|
||||
// reuse toggle event handler, applying the elements to toggle
|
||||
// start searching for all hitareas
|
||||
toggler.apply( $("div." + CLASSES.hitarea, tree).filter(function() {
|
||||
// for plain toggle, no filter is provided, otherwise we need to check the parent element
|
||||
return filter ? $(this).parent("." + filter).length : true;
|
||||
}) );
|
||||
return false;
|
||||
};
|
||||
}
|
||||
// click on first element to collapse tree
|
||||
$("a:eq(0)", control).click( handler(CLASSES.collapsable) );
|
||||
// click on second to expand tree
|
||||
$("a:eq(1)", control).click( handler(CLASSES.expandable) );
|
||||
// click on third to toggle tree
|
||||
$("a:eq(2)", control).click( handler() );
|
||||
}
|
||||
|
||||
// handle toggle event
|
||||
function toggler() {
|
||||
$(this)
|
||||
.parent()
|
||||
// swap classes for hitarea
|
||||
.find(">.hitarea")
|
||||
.swapClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
|
||||
.swapClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea )
|
||||
.end()
|
||||
// swap classes for parent li
|
||||
.swapClass( CLASSES.collapsable, CLASSES.expandable )
|
||||
.swapClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
|
||||
// find child lists
|
||||
.find( ">ul" )
|
||||
// toggle them
|
||||
.heightToggle( settings.animated, settings.toggle );
|
||||
if ( settings.unique ) {
|
||||
$(this).parent()
|
||||
.siblings()
|
||||
// swap classes for hitarea
|
||||
.find(">.hitarea")
|
||||
.replaceClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
|
||||
.replaceClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea )
|
||||
.end()
|
||||
.replaceClass( CLASSES.collapsable, CLASSES.expandable )
|
||||
.replaceClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
|
||||
.find( ">ul" )
|
||||
.heightHide( settings.animated, settings.toggle );
|
||||
}
|
||||
}
|
||||
this.data("toggler", toggler);
|
||||
|
||||
function serialize() {
|
||||
function binary(arg) {
|
||||
return arg ? 1 : 0;
|
||||
}
|
||||
var data = [];
|
||||
branches.each(function(i, e) {
|
||||
data[i] = $(e).is(":has(>ul:visible)") ? 1 : 0;
|
||||
});
|
||||
$.cookie(settings.cookieId, data.join(""), settings.cookieOptions );
|
||||
}
|
||||
|
||||
function deserialize() {
|
||||
var stored = $.cookie(settings.cookieId);
|
||||
if ( stored ) {
|
||||
var data = stored.split("");
|
||||
branches.each(function(i, e) {
|
||||
$(e).find(">ul")[ parseInt(data[i]) ? "show" : "hide" ]();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// add treeview class to activate styles
|
||||
this.addClass("treeview");
|
||||
|
||||
// prepare branches and find all tree items with child lists
|
||||
var branches = this.find("li").prepareBranches(settings);
|
||||
|
||||
switch(settings.persist) {
|
||||
case "cookie":
|
||||
var toggleCallback = settings.toggle;
|
||||
settings.toggle = function() {
|
||||
serialize();
|
||||
if (toggleCallback) {
|
||||
toggleCallback.apply(this, arguments);
|
||||
}
|
||||
};
|
||||
deserialize();
|
||||
break;
|
||||
case "location":
|
||||
var current = this.find("a").filter(function() {
|
||||
return location.href.toLowerCase().indexOf(this.href.toLowerCase()) == 0;
|
||||
});
|
||||
if ( current.length ) {
|
||||
// TODO update the open/closed classes
|
||||
var items = current.addClass("selected").parents("ul, li").add( current.next() ).show();
|
||||
if (settings.prerendered) {
|
||||
// if prerendered is on, replicate the basic class swapping
|
||||
items.filter("li")
|
||||
.swapClass( CLASSES.collapsable, CLASSES.expandable )
|
||||
.swapClass( CLASSES.lastCollapsable, CLASSES.lastExpandable )
|
||||
.find(">.hitarea")
|
||||
.swapClass( CLASSES.collapsableHitarea, CLASSES.expandableHitarea )
|
||||
.swapClass( CLASSES.lastCollapsableHitarea, CLASSES.lastExpandableHitarea );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
branches.applyClasses(settings, toggler);
|
||||
|
||||
// if control option is set, create the treecontroller and show it
|
||||
if ( settings.control ) {
|
||||
treeController(this, settings.control);
|
||||
$(settings.control).show();
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
});
|
||||
|
||||
// classes used by the plugin
|
||||
// need to be styled via external stylesheet, see first example
|
||||
$.treeview = {};
|
||||
var CLASSES = ($.treeview.classes = {
|
||||
open: "open",
|
||||
closed: "closed",
|
||||
expandable: "expandable",
|
||||
expandableHitarea: "expandable-hitarea",
|
||||
lastExpandableHitarea: "lastExpandable-hitarea",
|
||||
collapsable: "collapsable",
|
||||
collapsableHitarea: "collapsable-hitarea",
|
||||
lastCollapsableHitarea: "lastCollapsable-hitarea",
|
||||
lastCollapsable: "lastCollapsable",
|
||||
lastExpandable: "lastExpandable",
|
||||
last: "last",
|
||||
hitarea: "hitarea"
|
||||
});
|
||||
|
||||
})(jQuery);
|
||||
@@ -0,0 +1,36 @@
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build ignore
|
||||
// +build ignore
|
||||
|
||||
// Command makestatic writes the generated file buffer to "static.go".
|
||||
// It is intended to be invoked via "go generate" (directive in "gen.go").
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"golang.org/x/tools/godoc/static"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if err := makestatic(); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func makestatic() error {
|
||||
buf, err := static.Generate()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error while generating static.go: %v\n", err)
|
||||
}
|
||||
err = os.WriteFile("static.go", buf, 0666)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error while writing static.go: %v\n", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<div class="toggle" style="display: none">
|
||||
<div class="collapsed">
|
||||
<p class="exampleHeading toggleButton">▹ <span class="text">Method set</span></p>
|
||||
</div>
|
||||
<div class="expanded">
|
||||
<p class="exampleHeading toggleButton">▾ <span class="text">Method set</span></p>
|
||||
<div style="margin-left: 1in" id='methodset-{{.Index}}'>...</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,292 @@
|
||||
<!--
|
||||
Copyright 2009 The Go Authors. All rights reserved.
|
||||
Use of this source code is governed by a BSD-style
|
||||
license that can be found in the LICENSE file.
|
||||
-->
|
||||
<!--
|
||||
Note: Static (i.e., not template-generated) href and id
|
||||
attributes start with "pkg-" to make it impossible for
|
||||
them to conflict with generated attributes (some of which
|
||||
correspond to Go identifiers).
|
||||
-->
|
||||
{{with .PDoc}}
|
||||
<script>
|
||||
document.ANALYSIS_DATA = {{$.AnalysisData}};
|
||||
document.CALLGRAPH = {{$.CallGraph}};
|
||||
</script>
|
||||
|
||||
{{if $.IsMain}}
|
||||
{{/* command documentation */}}
|
||||
{{comment_html $ .Doc}}
|
||||
{{else}}
|
||||
{{/* package documentation */}}
|
||||
<div id="short-nav">
|
||||
<dl>
|
||||
<dd><code>import "{{html .ImportPath}}"</code></dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dd><a href="#pkg-overview" class="overviewLink">Overview</a></dd>
|
||||
<dd><a href="#pkg-index" class="indexLink">Index</a></dd>
|
||||
{{if $.Examples}}
|
||||
<dd><a href="#pkg-examples" class="examplesLink">Examples</a></dd>
|
||||
{{end}}
|
||||
{{if $.Dirs}}
|
||||
<dd><a href="#pkg-subdirectories">Subdirectories</a></dd>
|
||||
{{end}}
|
||||
</dl>
|
||||
</div>
|
||||
<!-- The package's Name is printed as title by the top-level template -->
|
||||
<div id="pkg-overview" class="toggleVisible">
|
||||
<div class="collapsed">
|
||||
<h2 class="toggleButton" title="Click to show Overview section">Overview ▹</h2>
|
||||
</div>
|
||||
<div class="expanded">
|
||||
<h2 class="toggleButton" title="Click to hide Overview section">Overview ▾</h2>
|
||||
{{comment_html $ .Doc}}
|
||||
{{example_html $ ""}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="pkg-index" class="toggleVisible">
|
||||
<div class="collapsed">
|
||||
<h2 class="toggleButton" title="Click to show Index section">Index ▹</h2>
|
||||
</div>
|
||||
<div class="expanded">
|
||||
<h2 class="toggleButton" title="Click to hide Index section">Index ▾</h2>
|
||||
|
||||
<!-- Table of contents for API; must be named manual-nav to turn off auto nav. -->
|
||||
<div id="manual-nav">
|
||||
<dl>
|
||||
{{if .Consts}}
|
||||
<dd><a href="#pkg-constants">Constants</a></dd>
|
||||
{{end}}
|
||||
{{if .Vars}}
|
||||
<dd><a href="#pkg-variables">Variables</a></dd>
|
||||
{{end}}
|
||||
{{range .Funcs}}
|
||||
{{$name_html := html .Name}}
|
||||
<dd><a href="#{{$name_html}}">{{node_html $ .Decl false | sanitize}}</a></dd>
|
||||
{{end}}
|
||||
{{range .Types}}
|
||||
{{$tname_html := html .Name}}
|
||||
<dd><a href="#{{$tname_html}}">type {{$tname_html}}</a></dd>
|
||||
{{range .Funcs}}
|
||||
{{$name_html := html .Name}}
|
||||
<dd> <a href="#{{$name_html}}">{{node_html $ .Decl false | sanitize}}</a></dd>
|
||||
{{end}}
|
||||
{{range .Methods}}
|
||||
{{$name_html := html .Name}}
|
||||
<dd> <a href="#{{$tname_html}}.{{$name_html}}">{{node_html $ .Decl false | sanitize}}</a></dd>
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{if $.Notes}}
|
||||
{{range $marker, $item := $.Notes}}
|
||||
<dd><a href="#pkg-note-{{$marker}}">{{noteTitle $marker | html}}s</a></dd>
|
||||
{{end}}
|
||||
{{end}}
|
||||
</dl>
|
||||
</div><!-- #manual-nav -->
|
||||
|
||||
{{if $.Examples}}
|
||||
<div id="pkg-examples">
|
||||
<h3>Examples</h3>
|
||||
<div class="js-expandAll expandAll collapsed">(Expand All)</div>
|
||||
<dl>
|
||||
{{range $.Examples}}
|
||||
<dd><a class="exampleLink" href="#example_{{.Name}}">{{example_name .Name}}</a></dd>
|
||||
{{end}}
|
||||
</dl>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{with .Filenames}}
|
||||
<h3>Package files</h3>
|
||||
<p>
|
||||
<span style="font-size:90%">
|
||||
{{range .}}
|
||||
<a href="{{.|srcLink|html}}">{{.|filename|html}}</a>
|
||||
{{end}}
|
||||
</span>
|
||||
</p>
|
||||
{{end}}
|
||||
</div><!-- .expanded -->
|
||||
</div><!-- #pkg-index -->
|
||||
|
||||
{{if ne $.CallGraph "null"}}
|
||||
<div id="pkg-callgraph" class="toggle" style="display: none">
|
||||
<div class="collapsed">
|
||||
<h2 class="toggleButton" title="Click to show Internal Call Graph section">Internal call graph ▹</h2>
|
||||
</div> <!-- .expanded -->
|
||||
<div class="expanded">
|
||||
<h2 class="toggleButton" title="Click to hide Internal Call Graph section">Internal call graph ▾</h2>
|
||||
<p>
|
||||
In the call graph viewer below, each node
|
||||
is a function belonging to this package
|
||||
and its children are the functions it
|
||||
calls—perhaps dynamically.
|
||||
</p>
|
||||
<p>
|
||||
The root nodes are the entry points of the
|
||||
package: functions that may be called from
|
||||
outside the package.
|
||||
There may be non-exported or anonymous
|
||||
functions among them if they are called
|
||||
dynamically from another package.
|
||||
</p>
|
||||
<p>
|
||||
Click a node to visit that function's source code.
|
||||
From there you can visit its callers by
|
||||
clicking its declaring <code>func</code>
|
||||
token.
|
||||
</p>
|
||||
<p>
|
||||
Functions may be omitted if they were
|
||||
determined to be unreachable in the
|
||||
particular programs or tests that were
|
||||
analyzed.
|
||||
</p>
|
||||
<!-- Zero means show all package entry points. -->
|
||||
<ul style="margin-left: 0.5in" id="callgraph-0" class="treeview"></ul>
|
||||
</div>
|
||||
</div> <!-- #pkg-callgraph -->
|
||||
{{end}}
|
||||
|
||||
{{with .Consts}}
|
||||
<h2 id="pkg-constants">Constants</h2>
|
||||
{{range .}}
|
||||
{{comment_html $ .Doc}}
|
||||
<pre>{{node_html $ .Decl true}}</pre>
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{with .Vars}}
|
||||
<h2 id="pkg-variables">Variables</h2>
|
||||
{{range .}}
|
||||
{{comment_html $ .Doc}}
|
||||
<pre>{{node_html $ .Decl true}}</pre>
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{range .Funcs}}
|
||||
{{/* Name is a string - no need for FSet */}}
|
||||
{{$name_html := html .Name}}
|
||||
<h2 id="{{$name_html}}">func <a href="{{posLink_url $ .Decl}}">{{$name_html}}</a>
|
||||
<a class="permalink" href="#{{$name_html}}">¶</a>
|
||||
{{$since := since "func" "" .Name $.PDoc.ImportPath}}
|
||||
{{if $since}}<span title="Added in Go {{$since}}">{{$since}}</span>{{end}}
|
||||
</h2>
|
||||
<pre>{{node_html $ .Decl true}}</pre>
|
||||
{{comment_html $ .Doc}}
|
||||
{{example_html $ .Name}}
|
||||
{{callgraph_html $ "" .Name}}
|
||||
|
||||
{{end}}
|
||||
{{range .Types}}
|
||||
{{$tname := .Name}}
|
||||
{{$tname_html := html .Name}}
|
||||
<h2 id="{{$tname_html}}">type <a href="{{posLink_url $ .Decl}}">{{$tname_html}}</a>
|
||||
<a class="permalink" href="#{{$tname_html}}">¶</a>
|
||||
{{$since := since "type" "" .Name $.PDoc.ImportPath}}
|
||||
{{if $since}}<span title="Added in Go {{$since}}">{{$since}}</span>{{end}}
|
||||
</h2>
|
||||
{{comment_html $ .Doc}}
|
||||
<pre>{{node_html $ .Decl true}}</pre>
|
||||
|
||||
{{range .Consts}}
|
||||
{{comment_html $ .Doc}}
|
||||
<pre>{{node_html $ .Decl true}}</pre>
|
||||
{{end}}
|
||||
|
||||
{{range .Vars}}
|
||||
{{comment_html $ .Doc}}
|
||||
<pre>{{node_html $ .Decl true}}</pre>
|
||||
{{end}}
|
||||
|
||||
{{example_html $ $tname}}
|
||||
{{implements_html $ $tname}}
|
||||
{{methodset_html $ $tname}}
|
||||
|
||||
{{range .Funcs}}
|
||||
{{$name_html := html .Name}}
|
||||
<h3 id="{{$name_html}}">func <a href="{{posLink_url $ .Decl}}">{{$name_html}}</a>
|
||||
<a class="permalink" href="#{{$name_html}}">¶</a>
|
||||
{{$since := since "func" "" .Name $.PDoc.ImportPath}}
|
||||
{{if $since}}<span title="Added in Go {{$since}}">{{$since}}</span>{{end}}
|
||||
</h3>
|
||||
<pre>{{node_html $ .Decl true}}</pre>
|
||||
{{comment_html $ .Doc}}
|
||||
{{example_html $ .Name}}
|
||||
{{callgraph_html $ "" .Name}}
|
||||
{{end}}
|
||||
|
||||
{{range .Methods}}
|
||||
{{$name_html := html .Name}}
|
||||
<h3 id="{{$tname_html}}.{{$name_html}}">func ({{html .Recv}}) <a href="{{posLink_url $ .Decl}}">{{$name_html}}</a>
|
||||
<a class="permalink" href="#{{$tname_html}}.{{$name_html}}">¶</a>
|
||||
{{$since := since "method" .Recv .Name $.PDoc.ImportPath}}
|
||||
{{if $since}}<span title="Added in Go {{$since}}">{{$since}}</span>{{end}}
|
||||
</h3>
|
||||
<pre>{{node_html $ .Decl true}}</pre>
|
||||
{{comment_html $ .Doc}}
|
||||
{{$name := printf "%s_%s" $tname .Name}}
|
||||
{{example_html $ $name}}
|
||||
{{callgraph_html $ .Recv .Name}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{with $.Notes}}
|
||||
{{range $marker, $content := .}}
|
||||
<h2 id="pkg-note-{{$marker}}">{{noteTitle $marker | html}}s</h2>
|
||||
<ul style="list-style: none; padding: 0;">
|
||||
{{range .}}
|
||||
<li><a href="{{posLink_url $ .}}" style="float: left;">☞</a> {{comment_html $ .Body}}</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{with .PAst}}
|
||||
{{range $filename, $ast := .}}
|
||||
<a href="{{$filename|srcLink|html}}">{{$filename|filename|html}}</a>:<pre>{{node_html $ $ast false}}</pre>
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{with .Dirs}}
|
||||
{{/* DirList entries are numbers and strings - no need for FSet */}}
|
||||
{{if $.PDoc}}
|
||||
<h2 id="pkg-subdirectories">Subdirectories</h2>
|
||||
{{end}}
|
||||
<div class="pkg-dir">
|
||||
<table>
|
||||
<tr>
|
||||
<th class="pkg-name">Name</th>
|
||||
<th class="pkg-synopsis">Synopsis</th>
|
||||
</tr>
|
||||
|
||||
{{if not (or (eq $.Dirname "/src/cmd") $.DirFlat)}}
|
||||
<tr>
|
||||
<td colspan="2"><a href="..">..</a></td>
|
||||
</tr>
|
||||
{{end}}
|
||||
|
||||
{{range .List}}
|
||||
<tr>
|
||||
{{if $.DirFlat}}
|
||||
{{if .HasPkg}}
|
||||
<td class="pkg-name">
|
||||
<a href="{{html .Path}}/{{modeQueryString $.Mode | html}}">{{html .Path}}</a>
|
||||
</td>
|
||||
{{end}}
|
||||
{{else}}
|
||||
<td class="pkg-name" style="padding-left: {{multiply .Depth 20}}px;">
|
||||
<a href="{{html .Path}}/{{modeQueryString $.Mode | html}}">{{html .Name}}</a>
|
||||
</td>
|
||||
{{end}}
|
||||
<td class="pkg-synopsis">
|
||||
{{html .Synopsis}}
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</table>
|
||||
</div>
|
||||
{{end}}
|
||||
@@ -0,0 +1,150 @@
|
||||
<!--
|
||||
Copyright 2018 The Go Authors. All rights reserved.
|
||||
Use of this source code is governed by a BSD-style
|
||||
license that can be found in the LICENSE file.
|
||||
-->
|
||||
<!--
|
||||
Note: Static (i.e., not template-generated) href and id
|
||||
attributes start with "pkg-" to make it impossible for
|
||||
them to conflict with generated attributes (some of which
|
||||
correspond to Go identifiers).
|
||||
-->
|
||||
{{with .PAst}}
|
||||
{{range $filename, $ast := .}}
|
||||
<a href="{{$filename|srcLink|html}}">{{$filename|filename|html}}</a>:<pre>{{node_html $ $ast false}}</pre>
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{with .Dirs}}
|
||||
{{/* DirList entries are numbers and strings - no need for FSet */}}
|
||||
{{if $.PDoc}}
|
||||
<h2 id="pkg-subdirectories">Subdirectories</h2>
|
||||
{{end}}
|
||||
<div id="manual-nav">
|
||||
<img alt="" class="gopher" src="/lib/godoc/gopher/pkg.png"/>
|
||||
<dl>
|
||||
<dt><a href="#stdlib">Standard library</a></dt>
|
||||
{{if hasThirdParty .List }}
|
||||
<dt><a href="#thirdparty">Third party</a></dt>
|
||||
{{end}}
|
||||
<dt><a href="#other">Other packages</a></dt>
|
||||
<dd><a href="#subrepo">Sub-repositories</a></dd>
|
||||
<dd><a href="#community">Community</a></dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
||||
<div id="stdlib" class="toggleVisible">
|
||||
<div class="collapsed">
|
||||
<h2 class="toggleButton" title="Click to show Standard library section">Standard library ▹</h2>
|
||||
</div>
|
||||
<div class="expanded">
|
||||
<h2 class="toggleButton" title="Click to hide Standard library section">Standard library ▾</h2>
|
||||
<div class="pkg-dir">
|
||||
<table>
|
||||
<tr>
|
||||
<th class="pkg-name">Name</th>
|
||||
<th class="pkg-synopsis">Synopsis</th>
|
||||
</tr>
|
||||
|
||||
{{range .List}}
|
||||
<tr>
|
||||
{{if eq .RootType "GOROOT"}}
|
||||
{{if $.DirFlat}}
|
||||
{{if .HasPkg}}
|
||||
<td class="pkg-name">
|
||||
<a href="{{html .Path}}/{{modeQueryString $.Mode | html}}">{{html .Path}}</a>
|
||||
</td>
|
||||
{{end}}
|
||||
{{else}}
|
||||
<td class="pkg-name" style="padding-left: {{multiply .Depth 20}}px;">
|
||||
<a href="{{html .Path}}/{{modeQueryString $.Mode | html}}">{{html .Name}}</a>
|
||||
</td>
|
||||
{{end}}
|
||||
<td class="pkg-synopsis">
|
||||
{{html .Synopsis}}
|
||||
</td>
|
||||
{{end}}
|
||||
</tr>
|
||||
{{end}}
|
||||
</table>
|
||||
</div> <!-- .pkg-dir -->
|
||||
</div> <!-- .expanded -->
|
||||
</div> <!-- #stdlib .toggleVisible -->
|
||||
|
||||
{{if hasThirdParty .List }}
|
||||
<div id="thirdparty" class="toggleVisible">
|
||||
<div class="collapsed">
|
||||
<h2 class="toggleButton" title="Click to show Third party section">Third party ▹</h2>
|
||||
</div>
|
||||
<div class="expanded">
|
||||
<h2 class="toggleButton" title="Click to hide Third party section">Third party ▾</h2>
|
||||
<div class="pkg-dir">
|
||||
<table>
|
||||
<tr>
|
||||
<th class="pkg-name">Name</th>
|
||||
<th class="pkg-synopsis">Synopsis</th>
|
||||
</tr>
|
||||
|
||||
{{range .List}}
|
||||
<tr>
|
||||
{{if eq .RootType "GOPATH"}}
|
||||
{{if $.DirFlat}}
|
||||
{{if .HasPkg}}
|
||||
<td class="pkg-name">
|
||||
<a href="{{html .Path}}/{{modeQueryString $.Mode | html}}">{{html .Path}}</a>
|
||||
</td>
|
||||
{{end}}
|
||||
{{else}}
|
||||
<td class="pkg-name" style="padding-left: {{multiply .Depth 20}}px;">
|
||||
<a href="{{html .Path}}/{{modeQueryString $.Mode | html}}">{{html .Name}}</a>
|
||||
</td>
|
||||
{{end}}
|
||||
<td class="pkg-synopsis">
|
||||
{{html .Synopsis}}
|
||||
</td>
|
||||
{{end}}
|
||||
</tr>
|
||||
{{end}}
|
||||
</table>
|
||||
</div> <!-- .pkg-dir -->
|
||||
</div> <!-- .expanded -->
|
||||
</div> <!-- #stdlib .toggleVisible -->
|
||||
{{end}}
|
||||
|
||||
<h2 id="other">Other packages</h2>
|
||||
<h3 id="subrepo">Sub-repositories</h3>
|
||||
<p>
|
||||
These packages are part of the Go Project but outside the main Go tree.
|
||||
They are developed under looser <a href="https://golang.org/doc/go1compat">compatibility requirements</a> than the Go core.
|
||||
Install them with "<a href="/cmd/go/#hdr-Download_and_install_packages_and_dependencies">go get</a>".
|
||||
</p>
|
||||
<ul>
|
||||
<li><a href="//pkg.go.dev/golang.org/x/benchmarks">benchmarks</a> — benchmarks to measure Go as it is developed.</li>
|
||||
<li><a href="//pkg.go.dev/golang.org/x/blog">blog</a> — <a href="//blog.golang.org">blog.golang.org</a>'s implementation.</li>
|
||||
<li><a href="//pkg.go.dev/golang.org/x/build">build</a> — <a href="//build.golang.org">build.golang.org</a>'s implementation.</li>
|
||||
<li><a href="//pkg.go.dev/golang.org/x/crypto">crypto</a> — additional cryptography packages.</li>
|
||||
<li><a href="//pkg.go.dev/golang.org/x/debug">debug</a> — an experimental debugger for Go.</li>
|
||||
<li><a href="//pkg.go.dev/golang.org/x/image">image</a> — additional imaging packages.</li>
|
||||
<li><a href="//pkg.go.dev/golang.org/x/mobile">mobile</a> — experimental support for Go on mobile platforms.</li>
|
||||
<li><a href="//pkg.go.dev/golang.org/x/net">net</a> — additional networking packages.</li>
|
||||
<li><a href="//pkg.go.dev/golang.org/x/perf">perf</a> — packages and tools for performance measurement, storage, and analysis.</li>
|
||||
<li><a href="//pkg.go.dev/golang.org/x/pkgsite">pkgsite</a> — home of the pkg.go.dev website.</li>
|
||||
<li><a href="//pkg.go.dev/golang.org/x/review">review</a> — a tool for working with Gerrit code reviews.</li>
|
||||
<li><a href="//pkg.go.dev/golang.org/x/sync">sync</a> — additional concurrency primitives.</li>
|
||||
<li><a href="//pkg.go.dev/golang.org/x/sys">sys</a> — packages for making system calls.</li>
|
||||
<li><a href="//pkg.go.dev/golang.org/x/text">text</a> — packages for working with text.</li>
|
||||
<li><a href="//pkg.go.dev/golang.org/x/time">time</a> — additional time packages.</li>
|
||||
<li><a href="//pkg.go.dev/golang.org/x/tools">tools</a> — godoc, goimports, gorename, and other tools.</li>
|
||||
<li><a href="//pkg.go.dev/golang.org/x/tour">tour</a> — <a href="//tour.golang.org">tour.golang.org</a>'s implementation.</li>
|
||||
<li><a href="//pkg.go.dev/golang.org/x/exp">exp</a> — experimental and deprecated packages (handle with care; may change without warning).</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="community">Community</h3>
|
||||
<p>
|
||||
These services can help you find Open Source packages provided by the community.
|
||||
</p>
|
||||
<ul>
|
||||
<li><a href="//pkg.go.dev">Pkg.go.dev</a> - the Go package discovery site.</li>
|
||||
<li><a href="/wiki/Projects">Projects at the Go Wiki</a> - a curated list of Go projects.</li>
|
||||
</ul>
|
||||
{{end}}
|
||||
@@ -0,0 +1,114 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
function initPlayground(transport) {
|
||||
'use strict';
|
||||
|
||||
function text(node) {
|
||||
var s = '';
|
||||
for (var i = 0; i < node.childNodes.length; i++) {
|
||||
var n = node.childNodes[i];
|
||||
if (n.nodeType === 1) {
|
||||
if (n.tagName === 'BUTTON') continue;
|
||||
if (n.tagName === 'SPAN' && n.className === 'number') continue;
|
||||
if (n.tagName === 'DIV' || n.tagName === 'BR' || n.tagName === 'PRE') {
|
||||
s += '\n';
|
||||
}
|
||||
s += text(n);
|
||||
continue;
|
||||
}
|
||||
if (n.nodeType === 3) {
|
||||
s += n.nodeValue;
|
||||
}
|
||||
}
|
||||
return s.replace('\xA0', ' '); // replace non-breaking spaces
|
||||
}
|
||||
|
||||
// When presenter notes are enabled, the index passed
|
||||
// here will identify the playground to be synced
|
||||
function init(code, index) {
|
||||
var output = document.createElement('div');
|
||||
var outpre = document.createElement('pre');
|
||||
var running;
|
||||
|
||||
if ($ && $(output).resizable) {
|
||||
$(output).resizable({
|
||||
handles: 'n,w,nw',
|
||||
minHeight: 27,
|
||||
minWidth: 135,
|
||||
maxHeight: 608,
|
||||
maxWidth: 990,
|
||||
});
|
||||
}
|
||||
|
||||
function onKill() {
|
||||
if (running) running.Kill();
|
||||
if (window.notesEnabled) updatePlayStorage('onKill', index);
|
||||
}
|
||||
|
||||
function onRun(e) {
|
||||
var sk = e.shiftKey || localStorage.getItem('play-shiftKey') === 'true';
|
||||
if (running) running.Kill();
|
||||
output.style.display = 'block';
|
||||
outpre.textContent = '';
|
||||
run1.style.display = 'none';
|
||||
var options = { Race: sk };
|
||||
running = transport.Run(text(code), PlaygroundOutput(outpre), options);
|
||||
if (window.notesEnabled) updatePlayStorage('onRun', index, e);
|
||||
}
|
||||
|
||||
function onClose() {
|
||||
if (running) running.Kill();
|
||||
output.style.display = 'none';
|
||||
run1.style.display = 'inline-block';
|
||||
if (window.notesEnabled) updatePlayStorage('onClose', index);
|
||||
}
|
||||
|
||||
if (window.notesEnabled) {
|
||||
playgroundHandlers.onRun.push(onRun);
|
||||
playgroundHandlers.onClose.push(onClose);
|
||||
playgroundHandlers.onKill.push(onKill);
|
||||
}
|
||||
|
||||
var run1 = document.createElement('button');
|
||||
run1.textContent = 'Run';
|
||||
run1.className = 'run';
|
||||
run1.addEventListener('click', onRun, false);
|
||||
var run2 = document.createElement('button');
|
||||
run2.className = 'run';
|
||||
run2.textContent = 'Run';
|
||||
run2.addEventListener('click', onRun, false);
|
||||
var kill = document.createElement('button');
|
||||
kill.className = 'kill';
|
||||
kill.textContent = 'Kill';
|
||||
kill.addEventListener('click', onKill, false);
|
||||
var close = document.createElement('button');
|
||||
close.className = 'close';
|
||||
close.textContent = 'Close';
|
||||
close.addEventListener('click', onClose, false);
|
||||
|
||||
var button = document.createElement('div');
|
||||
button.classList.add('buttons');
|
||||
button.appendChild(run1);
|
||||
// Hack to simulate insertAfter
|
||||
code.parentNode.insertBefore(button, code.nextSibling);
|
||||
|
||||
var buttons = document.createElement('div');
|
||||
buttons.classList.add('buttons');
|
||||
buttons.appendChild(run2);
|
||||
buttons.appendChild(kill);
|
||||
buttons.appendChild(close);
|
||||
|
||||
output.classList.add('output');
|
||||
output.appendChild(buttons);
|
||||
output.appendChild(outpre);
|
||||
output.style.display = 'none';
|
||||
code.parentNode.insertBefore(output, button.nextSibling);
|
||||
}
|
||||
|
||||
var play = document.querySelectorAll('div.playground');
|
||||
for (var i = 0; i < play.length; i++) {
|
||||
init(play[i], i);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,593 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
/*
|
||||
In the absence of any formal way to specify interfaces in JavaScript,
|
||||
here's a skeleton implementation of a playground transport.
|
||||
|
||||
function Transport() {
|
||||
// Set up any transport state (eg, make a websocket connection).
|
||||
return {
|
||||
Run: function(body, output, options) {
|
||||
// Compile and run the program 'body' with 'options'.
|
||||
// Call the 'output' callback to display program output.
|
||||
return {
|
||||
Kill: function() {
|
||||
// Kill the running program.
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// The output callback is called multiple times, and each time it is
|
||||
// passed an object of this form.
|
||||
var write = {
|
||||
Kind: 'string', // 'start', 'stdout', 'stderr', 'end'
|
||||
Body: 'string' // content of write or end status message
|
||||
}
|
||||
|
||||
// The first call must be of Kind 'start' with no body.
|
||||
// Subsequent calls may be of Kind 'stdout' or 'stderr'
|
||||
// and must have a non-null Body string.
|
||||
// The final call should be of Kind 'end' with an optional
|
||||
// Body string, signifying a failure ("killed", for example).
|
||||
|
||||
// The output callback must be of this form.
|
||||
// See PlaygroundOutput (below) for an implementation.
|
||||
function outputCallback(write) {
|
||||
}
|
||||
*/
|
||||
|
||||
// HTTPTransport is the default transport.
|
||||
// enableVet enables running vet if a program was compiled and ran successfully.
|
||||
// If vet returned any errors, display them before the output of a program.
|
||||
function HTTPTransport(enableVet) {
|
||||
'use strict';
|
||||
|
||||
function playback(output, data) {
|
||||
// Backwards compatibility: default values do not affect the output.
|
||||
var events = data.Events || [];
|
||||
var errors = data.Errors || '';
|
||||
var status = data.Status || 0;
|
||||
var isTest = data.IsTest || false;
|
||||
var testsFailed = data.TestsFailed || 0;
|
||||
|
||||
var timeout;
|
||||
output({ Kind: 'start' });
|
||||
function next() {
|
||||
if (!events || events.length === 0) {
|
||||
if (isTest) {
|
||||
if (testsFailed > 0) {
|
||||
output({
|
||||
Kind: 'system',
|
||||
Body:
|
||||
'\n' +
|
||||
testsFailed +
|
||||
' test' +
|
||||
(testsFailed > 1 ? 's' : '') +
|
||||
' failed.',
|
||||
});
|
||||
} else {
|
||||
output({ Kind: 'system', Body: '\nAll tests passed.' });
|
||||
}
|
||||
} else {
|
||||
if (status > 0) {
|
||||
output({ Kind: 'end', Body: 'status ' + status + '.' });
|
||||
} else {
|
||||
if (errors !== '') {
|
||||
// errors are displayed only in the case of timeout.
|
||||
output({ Kind: 'end', Body: errors + '.' });
|
||||
} else {
|
||||
output({ Kind: 'end' });
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
var e = events.shift();
|
||||
if (e.Delay === 0) {
|
||||
output({ Kind: e.Kind, Body: e.Message });
|
||||
next();
|
||||
return;
|
||||
}
|
||||
timeout = setTimeout(function() {
|
||||
output({ Kind: e.Kind, Body: e.Message });
|
||||
next();
|
||||
}, e.Delay / 1000000);
|
||||
}
|
||||
next();
|
||||
return {
|
||||
Stop: function() {
|
||||
clearTimeout(timeout);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function error(output, msg) {
|
||||
output({ Kind: 'start' });
|
||||
output({ Kind: 'stderr', Body: msg });
|
||||
output({ Kind: 'end' });
|
||||
}
|
||||
|
||||
function buildFailed(output, msg) {
|
||||
output({ Kind: 'start' });
|
||||
output({ Kind: 'stderr', Body: msg });
|
||||
output({ Kind: 'system', Body: '\nGo build failed.' });
|
||||
}
|
||||
|
||||
var seq = 0;
|
||||
return {
|
||||
Run: function(body, output, options) {
|
||||
seq++;
|
||||
var cur = seq;
|
||||
var playing;
|
||||
$.ajax('/compile', {
|
||||
type: 'POST',
|
||||
data: { version: 2, body: body, withVet: enableVet },
|
||||
dataType: 'json',
|
||||
success: function(data) {
|
||||
if (seq != cur) return;
|
||||
if (!data) return;
|
||||
if (playing != null) playing.Stop();
|
||||
if (data.Errors) {
|
||||
if (data.Errors === 'process took too long') {
|
||||
// Playback the output that was captured before the timeout.
|
||||
playing = playback(output, data);
|
||||
} else {
|
||||
buildFailed(output, data.Errors);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!data.Events) {
|
||||
data.Events = [];
|
||||
}
|
||||
if (data.VetErrors) {
|
||||
// Inject errors from the vet as the first events in the output.
|
||||
data.Events.unshift({
|
||||
Message: 'Go vet exited.\n\n',
|
||||
Kind: 'system',
|
||||
Delay: 0,
|
||||
});
|
||||
data.Events.unshift({
|
||||
Message: data.VetErrors,
|
||||
Kind: 'stderr',
|
||||
Delay: 0,
|
||||
});
|
||||
}
|
||||
|
||||
if (!enableVet || data.VetOK || data.VetErrors) {
|
||||
playing = playback(output, data);
|
||||
return;
|
||||
}
|
||||
|
||||
// In case the server support doesn't support
|
||||
// compile+vet in same request signaled by the
|
||||
// 'withVet' parameter above, also try the old way.
|
||||
// TODO: remove this when it falls out of use.
|
||||
// It is 2019-05-13 now.
|
||||
$.ajax('/vet', {
|
||||
data: { body: body },
|
||||
type: 'POST',
|
||||
dataType: 'json',
|
||||
success: function(dataVet) {
|
||||
if (dataVet.Errors) {
|
||||
// inject errors from the vet as the first events in the output
|
||||
data.Events.unshift({
|
||||
Message: 'Go vet exited.\n\n',
|
||||
Kind: 'system',
|
||||
Delay: 0,
|
||||
});
|
||||
data.Events.unshift({
|
||||
Message: dataVet.Errors,
|
||||
Kind: 'stderr',
|
||||
Delay: 0,
|
||||
});
|
||||
}
|
||||
playing = playback(output, data);
|
||||
},
|
||||
error: function() {
|
||||
playing = playback(output, data);
|
||||
},
|
||||
});
|
||||
},
|
||||
error: function() {
|
||||
error(output, 'Error communicating with remote server.');
|
||||
},
|
||||
});
|
||||
return {
|
||||
Kill: function() {
|
||||
if (playing != null) playing.Stop();
|
||||
output({ Kind: 'end', Body: 'killed' });
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function SocketTransport() {
|
||||
'use strict';
|
||||
|
||||
var id = 0;
|
||||
var outputs = {};
|
||||
var started = {};
|
||||
var websocket;
|
||||
if (window.location.protocol == 'http:') {
|
||||
websocket = new WebSocket('ws://' + window.location.host + '/socket');
|
||||
} else if (window.location.protocol == 'https:') {
|
||||
websocket = new WebSocket('wss://' + window.location.host + '/socket');
|
||||
}
|
||||
|
||||
websocket.onclose = function() {
|
||||
console.log('websocket connection closed');
|
||||
};
|
||||
|
||||
websocket.onmessage = function(e) {
|
||||
var m = JSON.parse(e.data);
|
||||
var output = outputs[m.Id];
|
||||
if (output === null) return;
|
||||
if (!started[m.Id]) {
|
||||
output({ Kind: 'start' });
|
||||
started[m.Id] = true;
|
||||
}
|
||||
output({ Kind: m.Kind, Body: m.Body });
|
||||
};
|
||||
|
||||
function send(m) {
|
||||
websocket.send(JSON.stringify(m));
|
||||
}
|
||||
|
||||
return {
|
||||
Run: function(body, output, options) {
|
||||
var thisID = id + '';
|
||||
id++;
|
||||
outputs[thisID] = output;
|
||||
send({ Id: thisID, Kind: 'run', Body: body, Options: options });
|
||||
return {
|
||||
Kill: function() {
|
||||
send({ Id: thisID, Kind: 'kill' });
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function PlaygroundOutput(el) {
|
||||
'use strict';
|
||||
|
||||
return function(write) {
|
||||
if (write.Kind == 'start') {
|
||||
el.innerHTML = '';
|
||||
return;
|
||||
}
|
||||
|
||||
var cl = 'system';
|
||||
if (write.Kind == 'stdout' || write.Kind == 'stderr') cl = write.Kind;
|
||||
|
||||
var m = write.Body;
|
||||
if (write.Kind == 'end') {
|
||||
m = '\nProgram exited' + (m ? ': ' + m : '.');
|
||||
}
|
||||
|
||||
if (m.indexOf('IMAGE:') === 0) {
|
||||
// TODO(adg): buffer all writes before creating image
|
||||
var url = 'data:image/png;base64,' + m.substr(6);
|
||||
var img = document.createElement('img');
|
||||
img.src = url;
|
||||
el.appendChild(img);
|
||||
return;
|
||||
}
|
||||
|
||||
// ^L clears the screen.
|
||||
var s = m.split('\x0c');
|
||||
if (s.length > 1) {
|
||||
el.innerHTML = '';
|
||||
m = s.pop();
|
||||
}
|
||||
|
||||
m = m.replace(/&/g, '&');
|
||||
m = m.replace(/</g, '<');
|
||||
m = m.replace(/>/g, '>');
|
||||
|
||||
var needScroll = el.scrollTop + el.offsetHeight == el.scrollHeight;
|
||||
|
||||
var span = document.createElement('span');
|
||||
span.className = cl;
|
||||
span.innerHTML = m;
|
||||
el.appendChild(span);
|
||||
|
||||
if (needScroll) el.scrollTop = el.scrollHeight - el.offsetHeight;
|
||||
};
|
||||
}
|
||||
|
||||
(function() {
|
||||
function lineHighlight(error) {
|
||||
var regex = /prog.go:([0-9]+)/g;
|
||||
var r = regex.exec(error);
|
||||
while (r) {
|
||||
$('.lines div')
|
||||
.eq(r[1] - 1)
|
||||
.addClass('lineerror');
|
||||
r = regex.exec(error);
|
||||
}
|
||||
}
|
||||
function highlightOutput(wrappedOutput) {
|
||||
return function(write) {
|
||||
if (write.Body) lineHighlight(write.Body);
|
||||
wrappedOutput(write);
|
||||
};
|
||||
}
|
||||
function lineClear() {
|
||||
$('.lineerror').removeClass('lineerror');
|
||||
}
|
||||
|
||||
// opts is an object with these keys
|
||||
// codeEl - code editor element
|
||||
// outputEl - program output element
|
||||
// runEl - run button element
|
||||
// fmtEl - fmt button element (optional)
|
||||
// fmtImportEl - fmt "imports" checkbox element (optional)
|
||||
// shareEl - share button element (optional)
|
||||
// shareURLEl - share URL text input element (optional)
|
||||
// shareRedirect - base URL to redirect to on share (optional)
|
||||
// toysEl - toys select element (optional)
|
||||
// enableHistory - enable using HTML5 history API (optional)
|
||||
// transport - playground transport to use (default is HTTPTransport)
|
||||
// enableShortcuts - whether to enable shortcuts (Ctrl+S/Cmd+S to save) (default is false)
|
||||
// enableVet - enable running vet and displaying its errors
|
||||
function playground(opts) {
|
||||
var code = $(opts.codeEl);
|
||||
var transport = opts['transport'] || new HTTPTransport(opts['enableVet']);
|
||||
var running;
|
||||
|
||||
// autoindent helpers.
|
||||
function insertTabs(n) {
|
||||
// find the selection start and end
|
||||
var start = code[0].selectionStart;
|
||||
var end = code[0].selectionEnd;
|
||||
// split the textarea content into two, and insert n tabs
|
||||
var v = code[0].value;
|
||||
var u = v.substr(0, start);
|
||||
for (var i = 0; i < n; i++) {
|
||||
u += '\t';
|
||||
}
|
||||
u += v.substr(end);
|
||||
// set revised content
|
||||
code[0].value = u;
|
||||
// reset caret position after inserted tabs
|
||||
code[0].selectionStart = start + n;
|
||||
code[0].selectionEnd = start + n;
|
||||
}
|
||||
function autoindent(el) {
|
||||
var curpos = el.selectionStart;
|
||||
var tabs = 0;
|
||||
while (curpos > 0) {
|
||||
curpos--;
|
||||
if (el.value[curpos] == '\t') {
|
||||
tabs++;
|
||||
} else if (tabs > 0 || el.value[curpos] == '\n') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
setTimeout(function() {
|
||||
insertTabs(tabs);
|
||||
}, 1);
|
||||
}
|
||||
|
||||
// NOTE(cbro): e is a jQuery event, not a DOM event.
|
||||
function handleSaveShortcut(e) {
|
||||
if (e.isDefaultPrevented()) return false;
|
||||
if (!e.metaKey && !e.ctrlKey) return false;
|
||||
if (e.key != 'S' && e.key != 's') return false;
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
// Share and save
|
||||
share(function(url) {
|
||||
window.location.href = url + '.go?download=true';
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function keyHandler(e) {
|
||||
if (opts.enableShortcuts && handleSaveShortcut(e)) return;
|
||||
|
||||
if (e.keyCode == 9 && !e.ctrlKey) {
|
||||
// tab (but not ctrl-tab)
|
||||
insertTabs(1);
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
if (e.keyCode == 13) {
|
||||
// enter
|
||||
if (e.shiftKey) {
|
||||
// +shift
|
||||
run();
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
if (e.ctrlKey) {
|
||||
// +control
|
||||
fmt();
|
||||
e.preventDefault();
|
||||
} else {
|
||||
autoindent(e.target);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
code.unbind('keydown').bind('keydown', keyHandler);
|
||||
var outdiv = $(opts.outputEl).empty();
|
||||
var output = $('<pre/>').appendTo(outdiv);
|
||||
|
||||
function body() {
|
||||
return $(opts.codeEl).val();
|
||||
}
|
||||
function setBody(text) {
|
||||
$(opts.codeEl).val(text);
|
||||
}
|
||||
function origin(href) {
|
||||
return ('' + href)
|
||||
.split('/')
|
||||
.slice(0, 3)
|
||||
.join('/');
|
||||
}
|
||||
|
||||
var pushedEmpty = window.location.pathname == '/';
|
||||
function inputChanged() {
|
||||
if (pushedEmpty) {
|
||||
return;
|
||||
}
|
||||
pushedEmpty = true;
|
||||
$(opts.shareURLEl).hide();
|
||||
window.history.pushState(null, '', '/');
|
||||
}
|
||||
function popState(e) {
|
||||
if (e === null) {
|
||||
return;
|
||||
}
|
||||
if (e && e.state && e.state.code) {
|
||||
setBody(e.state.code);
|
||||
}
|
||||
}
|
||||
var rewriteHistory = false;
|
||||
if (
|
||||
window.history &&
|
||||
window.history.pushState &&
|
||||
window.addEventListener &&
|
||||
opts.enableHistory
|
||||
) {
|
||||
rewriteHistory = true;
|
||||
code[0].addEventListener('input', inputChanged);
|
||||
window.addEventListener('popstate', popState);
|
||||
}
|
||||
|
||||
function setError(error) {
|
||||
if (running) running.Kill();
|
||||
lineClear();
|
||||
lineHighlight(error);
|
||||
output
|
||||
.empty()
|
||||
.addClass('error')
|
||||
.text(error);
|
||||
}
|
||||
function loading() {
|
||||
lineClear();
|
||||
if (running) running.Kill();
|
||||
output.removeClass('error').text('Waiting for remote server...');
|
||||
}
|
||||
function run() {
|
||||
loading();
|
||||
running = transport.Run(
|
||||
body(),
|
||||
highlightOutput(PlaygroundOutput(output[0]))
|
||||
);
|
||||
}
|
||||
|
||||
function fmt() {
|
||||
loading();
|
||||
var data = { body: body() };
|
||||
if ($(opts.fmtImportEl).is(':checked')) {
|
||||
data['imports'] = 'true';
|
||||
}
|
||||
$.ajax('/fmt', {
|
||||
data: data,
|
||||
type: 'POST',
|
||||
dataType: 'json',
|
||||
success: function(data) {
|
||||
if (data.Error) {
|
||||
setError(data.Error);
|
||||
} else {
|
||||
setBody(data.Body);
|
||||
setError('');
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
var shareURL; // jQuery element to show the shared URL.
|
||||
var sharing = false; // true if there is a pending request.
|
||||
var shareCallbacks = [];
|
||||
function share(opt_callback) {
|
||||
if (opt_callback) shareCallbacks.push(opt_callback);
|
||||
|
||||
if (sharing) return;
|
||||
sharing = true;
|
||||
|
||||
var sharingData = body();
|
||||
$.ajax('https://play.golang.org/share', {
|
||||
processData: false,
|
||||
data: sharingData,
|
||||
type: 'POST',
|
||||
contentType: 'text/plain; charset=utf-8',
|
||||
complete: function(xhr) {
|
||||
sharing = false;
|
||||
if (xhr.status != 200) {
|
||||
alert('Server error; try again.');
|
||||
return;
|
||||
}
|
||||
if (opts.shareRedirect) {
|
||||
window.location = opts.shareRedirect + xhr.responseText;
|
||||
}
|
||||
var path = '/p/' + xhr.responseText;
|
||||
var url = origin(window.location) + path;
|
||||
|
||||
for (var i = 0; i < shareCallbacks.length; i++) {
|
||||
shareCallbacks[i](url);
|
||||
}
|
||||
shareCallbacks = [];
|
||||
|
||||
if (shareURL) {
|
||||
shareURL
|
||||
.show()
|
||||
.val(url)
|
||||
.focus()
|
||||
.select();
|
||||
|
||||
if (rewriteHistory) {
|
||||
var historyData = { code: sharingData };
|
||||
window.history.pushState(historyData, '', path);
|
||||
pushedEmpty = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
$(opts.runEl).click(run);
|
||||
$(opts.fmtEl).click(fmt);
|
||||
|
||||
if (
|
||||
opts.shareEl !== null &&
|
||||
(opts.shareURLEl !== null || opts.shareRedirect !== null)
|
||||
) {
|
||||
if (opts.shareURLEl) {
|
||||
shareURL = $(opts.shareURLEl).hide();
|
||||
}
|
||||
$(opts.shareEl).click(function() {
|
||||
share();
|
||||
});
|
||||
}
|
||||
|
||||
if (opts.toysEl !== null) {
|
||||
$(opts.toysEl).bind('change', function() {
|
||||
var toy = $(this).val();
|
||||
$.ajax('/doc/play/' + toy, {
|
||||
processData: false,
|
||||
type: 'GET',
|
||||
complete: function(xhr) {
|
||||
if (xhr.status != 200) {
|
||||
alert('Server error; try again.');
|
||||
return;
|
||||
}
|
||||
setBody(xhr.responseText);
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
window.playground = playground;
|
||||
})();
|
||||
@@ -0,0 +1,66 @@
|
||||
<!--
|
||||
Copyright 2009 The Go Authors. All rights reserved.
|
||||
Use of this source code is governed by a BSD-style
|
||||
license that can be found in the LICENSE file.
|
||||
-->
|
||||
|
||||
{{ $colCount := tocColCount .}}
|
||||
{{/* Generate the TOC */}}
|
||||
<nav class="search-nav" style="column-count: {{$colCount}}" role="navigation">
|
||||
{{range $key, $val := .Idents}}
|
||||
{{if $val}}
|
||||
<a href="#{{$key.Name}}">{{$key.Name}}</a>
|
||||
<br />
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{if not .Idents}}
|
||||
{{with .Pak}}
|
||||
<a href="#Packages">Package {{html $.Query}}</a>
|
||||
<br />
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{with .Hit}}
|
||||
{{with .Decls}}
|
||||
<a href="#Global">Package-level declarations</a>
|
||||
<br />
|
||||
{{range .}}
|
||||
{{$pkg_html := pkgLink .Pak.Path | html}}
|
||||
<a href="#Global_{{$pkg_html}}" class="indent">package {{html .Pak.Name}}</a>
|
||||
<br />
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{with .Others}}
|
||||
<a href="#Local">Local declarations and uses</a>
|
||||
<br />
|
||||
{{range .}}
|
||||
{{$pkg_html := pkgLink .Pak.Path | html}}
|
||||
<a href="#Local_{{$pkg_html}}" class="indent">package {{html .Pak.Name}}</a>
|
||||
<br />
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
{{with .Textual}}
|
||||
{{if $.Complete}}
|
||||
<a href="#Textual">{{html $.Found}} textual occurrences</a>
|
||||
{{else}}
|
||||
<a href="#Textual">More than {{html $.Found}} textual occurrences</a>
|
||||
{{end}}
|
||||
{{end}}
|
||||
</nav>
|
||||
|
||||
{{with .Alert}}
|
||||
<p>
|
||||
<span class="alert" style="font-size:120%">{{html .}}</span>
|
||||
</p>
|
||||
{{end}}
|
||||
{{with .Alt}}
|
||||
<p>
|
||||
<span class="alert" style="font-size:120%">Did you mean: </span>
|
||||
{{range .Alts}}
|
||||
<a href="search?q={{urlquery .}}" style="font-size:120%">{{html .}}</a>
|
||||
{{end}}
|
||||
</p>
|
||||
{{end}}
|
||||
@@ -0,0 +1,64 @@
|
||||
<!--
|
||||
Copyright 2009 The Go Authors. All rights reserved.
|
||||
Use of this source code is governed by a BSD-style
|
||||
license that can be found in the LICENSE file.
|
||||
-->
|
||||
{{$query_url := urlquery .Query}}
|
||||
{{if not .Idents}}
|
||||
{{with .Pak}}
|
||||
<h2 id="Packages">Package {{html $.Query}}</h2>
|
||||
<p>
|
||||
<table class="layout">
|
||||
{{range .}}
|
||||
{{$pkg_html := pkgLink .Pak.Path | html}}
|
||||
<tr><td><a href="/{{$pkg_html}}">{{$pkg_html}}</a></td></tr>
|
||||
{{end}}
|
||||
</table>
|
||||
</p>
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{with .Hit}}
|
||||
{{with .Decls}}
|
||||
<h2 id="Global">Package-level declarations</h2>
|
||||
{{range .}}
|
||||
{{$pkg_html := pkgLink .Pak.Path | html}}
|
||||
<h3 id="Global_{{$pkg_html}}">package <a href="/{{$pkg_html}}">{{html .Pak.Name}}</a></h3>
|
||||
{{range .Files}}
|
||||
{{$file := .File.Path}}
|
||||
{{range .Groups}}
|
||||
{{range .}}
|
||||
{{$line := infoLine .}}
|
||||
<a href="{{queryLink $file $query_url $line | html}}">{{$file}}:{{$line}}</a>
|
||||
{{infoSnippet_html .}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{with .Others}}
|
||||
<h2 id="Local">Local declarations and uses</h2>
|
||||
{{range .}}
|
||||
{{$pkg_html := pkgLink .Pak.Path | html}}
|
||||
<h3 id="Local_{{$pkg_html}}">package <a href="/{{$pkg_html}}">{{html .Pak.Name}}</a></h3>
|
||||
{{range .Files}}
|
||||
{{$file := .File.Path}}
|
||||
<a href="{{queryLink $file $query_url 0 | html}}">{{$file}}</a>
|
||||
<table class="layout">
|
||||
{{range .Groups}}
|
||||
<tr>
|
||||
<td width="25"></td>
|
||||
<th align="left" valign="top">{{index . 0 | infoKind_html}}</th>
|
||||
<td align="left" width="4"></td>
|
||||
<td>
|
||||
{{range .}}
|
||||
{{$line := infoLine .}}
|
||||
<a href="{{queryLink $file $query_url $line | html}}">{{$line}}</a>
|
||||
{{end}}
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</table>
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
@@ -0,0 +1,24 @@
|
||||
<!--
|
||||
Copyright 2009 The Go Authors. All rights reserved.
|
||||
Use of this source code is governed by a BSD-style
|
||||
license that can be found in the LICENSE file.
|
||||
-->
|
||||
{{range $key, $val := .Idents}}
|
||||
{{if $val}}
|
||||
<h2 id="{{$key.Name}}">{{$key.Name}}</h2>
|
||||
{{range $val}}
|
||||
{{$pkg_html := pkgLink .Path | html}}
|
||||
{{if eq "Packages" $key.Name}}
|
||||
<a href="/{{$pkg_html}}">{{html .Path}}</a>
|
||||
{{else}}
|
||||
{{$doc_html := docLink .Path .Name| html}}
|
||||
<a href="/{{$pkg_html}}">{{html .Package}}</a>.<a href="{{$doc_html}}">{{.Name}}</a>
|
||||
{{end}}
|
||||
{{if .Doc}}
|
||||
<p>{{comment_html $ .Doc}}</p>
|
||||
{{else}}
|
||||
<p><em>No documentation available</em></p>
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
{{end}}
|
||||
@@ -0,0 +1,42 @@
|
||||
<!--
|
||||
Copyright 2009 The Go Authors. All rights reserved.
|
||||
Use of this source code is governed by a BSD-style
|
||||
license that can be found in the LICENSE file.
|
||||
-->
|
||||
{{$query_url := urlquery .Query}}
|
||||
{{with .Textual}}
|
||||
{{if $.Complete}}
|
||||
<h2 id="Textual">{{html $.Found}} textual occurrences</h2>
|
||||
{{else}}
|
||||
<h2 id="Textual">More than {{html $.Found}} textual occurrences</h2>
|
||||
<p>
|
||||
<span class="alert" style="font-size:120%">Not all files or lines containing "{{html $.Query}}" are shown.</span>
|
||||
</p>
|
||||
{{end}}
|
||||
<p>
|
||||
<table class="layout">
|
||||
{{range .}}
|
||||
{{$file := .Filename}}
|
||||
<tr>
|
||||
<td align="left" valign="top">
|
||||
<a href="{{queryLink $file $query_url 0}}">{{$file}}</a>:
|
||||
</td>
|
||||
<td align="left" width="4"></td>
|
||||
<th align="left" valign="top">{{len .Lines}}</th>
|
||||
<td align="left" width="4"></td>
|
||||
<td align="left">
|
||||
{{range .Lines}}
|
||||
<a href="{{queryLink $file $query_url .}}">{{html .}}</a>
|
||||
{{end}}
|
||||
{{if not $.Complete}}
|
||||
...
|
||||
{{end}}
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
{{if not $.Complete}}
|
||||
<tr><td align="left">...</td></tr>
|
||||
{{end}}
|
||||
</table>
|
||||
</p>
|
||||
{{end}}
|
||||
@@ -0,0 +1,897 @@
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: Arial, sans-serif;
|
||||
background-color: #fff;
|
||||
line-height: 1.3;
|
||||
text-align: center;
|
||||
color: #222;
|
||||
}
|
||||
textarea {
|
||||
/* Inherit text color from body avoiding illegible text in the case where the
|
||||
* user has inverted the browsers custom text and background colors. */
|
||||
color: inherit;
|
||||
}
|
||||
pre,
|
||||
code {
|
||||
font-family: Menlo, monospace;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
pre {
|
||||
line-height: 1.4;
|
||||
overflow-x: auto;
|
||||
}
|
||||
pre .comment {
|
||||
color: #006600;
|
||||
}
|
||||
pre .highlight,
|
||||
pre .highlight-comment,
|
||||
pre .selection-highlight,
|
||||
pre .selection-highlight-comment {
|
||||
background: #ffff00;
|
||||
}
|
||||
pre .selection,
|
||||
pre .selection-comment {
|
||||
background: #ff9632;
|
||||
}
|
||||
pre .ln {
|
||||
color: #999;
|
||||
background: #efefef;
|
||||
}
|
||||
.ln {
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
|
||||
/* Ensure 8 characters in the document - which due to floating
|
||||
* point rendering issues, might have a width of less than 1 each - are 8
|
||||
* characters wide, so a tab in the 9th position indents properly. See
|
||||
* https://github.com/webcompat/web-bugs/issues/17530#issuecomment-402675091
|
||||
* for more information. */
|
||||
display: inline-block;
|
||||
width: 8ch;
|
||||
}
|
||||
|
||||
.search-nav {
|
||||
margin-left: 1.25rem;
|
||||
font-size: 0.875rem;
|
||||
column-gap: 1.25rem;
|
||||
column-fill: auto;
|
||||
column-width: 14rem;
|
||||
}
|
||||
|
||||
.search-nav .indent {
|
||||
margin-left: 1.25rem;
|
||||
}
|
||||
|
||||
a,
|
||||
.exampleHeading .text,
|
||||
.expandAll {
|
||||
color: #375eab;
|
||||
text-decoration: none;
|
||||
}
|
||||
a:hover,
|
||||
.exampleHeading .text:hover,
|
||||
.expandAll:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.article a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.article .title a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.permalink {
|
||||
display: none;
|
||||
}
|
||||
:hover > .permalink {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
p,
|
||||
li {
|
||||
max-width: 50rem;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
p,
|
||||
pre,
|
||||
ul,
|
||||
ol {
|
||||
margin: 1.25rem;
|
||||
}
|
||||
pre {
|
||||
background: #efefef;
|
||||
padding: 0.625rem;
|
||||
border-radius: 0.3125rem;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
.rootHeading {
|
||||
margin: 1.25rem 0 1.25rem;
|
||||
padding: 0;
|
||||
color: #375eab;
|
||||
font-weight: bold;
|
||||
}
|
||||
h1 {
|
||||
font-size: 1.75rem;
|
||||
line-height: 1;
|
||||
}
|
||||
h1 .text-muted {
|
||||
color: #777;
|
||||
}
|
||||
h2 {
|
||||
font-size: 1.25rem;
|
||||
background: #e0ebf5;
|
||||
padding: 0.5rem;
|
||||
line-height: 1.25;
|
||||
font-weight: normal;
|
||||
overflow: auto;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
h2 a {
|
||||
font-weight: bold;
|
||||
}
|
||||
h3 {
|
||||
font-size: 1.25rem;
|
||||
line-height: 1.25;
|
||||
overflow: auto;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
h3,
|
||||
h4 {
|
||||
margin: 1.25rem 0.3125rem;
|
||||
}
|
||||
h4 {
|
||||
font-size: 1rem;
|
||||
}
|
||||
.rootHeading {
|
||||
font-size: 1.25rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
h2 > span,
|
||||
h3 > span {
|
||||
float: right;
|
||||
margin: 0 25px 0 0;
|
||||
font-weight: normal;
|
||||
color: #5279c7;
|
||||
}
|
||||
|
||||
dl {
|
||||
margin: 1.25rem;
|
||||
}
|
||||
dd {
|
||||
margin: 0 0 0 1.25rem;
|
||||
}
|
||||
dl,
|
||||
dd {
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
div#nav table td {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
#pkg-index h3 {
|
||||
font-size: 1rem;
|
||||
}
|
||||
.pkg-dir {
|
||||
padding: 0 0.625rem;
|
||||
}
|
||||
.pkg-dir table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
.pkg-name {
|
||||
padding-right: 0.625rem;
|
||||
}
|
||||
.alert {
|
||||
color: #aa0000;
|
||||
}
|
||||
|
||||
.top-heading {
|
||||
float: left;
|
||||
padding: 1.313rem 0;
|
||||
font-size: 1.25rem;
|
||||
font-weight: normal;
|
||||
}
|
||||
.top-heading a {
|
||||
color: #222;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#pkg-examples h3 {
|
||||
float: left;
|
||||
}
|
||||
|
||||
#pkg-examples dl {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.expandAll {
|
||||
cursor: pointer;
|
||||
float: left;
|
||||
margin: 1.25rem 0;
|
||||
}
|
||||
|
||||
div#topbar {
|
||||
background: #e0ebf5;
|
||||
height: 4rem;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
div#page {
|
||||
width: 100%;
|
||||
}
|
||||
div#page > .container,
|
||||
div#topbar > .container {
|
||||
text-align: left;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
padding: 0 1.25rem;
|
||||
}
|
||||
div#topbar > .container,
|
||||
div#page > .container {
|
||||
max-width: 59.38rem;
|
||||
}
|
||||
div#page.wide > .container,
|
||||
div#topbar.wide > .container {
|
||||
max-width: none;
|
||||
}
|
||||
div#plusone {
|
||||
float: right;
|
||||
clear: right;
|
||||
margin-top: 0.3125rem;
|
||||
}
|
||||
|
||||
div#footer {
|
||||
text-align: center;
|
||||
color: #666;
|
||||
font-size: 0.875rem;
|
||||
margin: 2.5rem 0;
|
||||
}
|
||||
|
||||
div#menu > a,
|
||||
input#search,
|
||||
div#learn .buttons a,
|
||||
div.play .buttons a,
|
||||
div#blog .read a,
|
||||
#menu-button {
|
||||
padding: 0.625rem;
|
||||
|
||||
text-decoration: none;
|
||||
font-size: 1rem;
|
||||
border-radius: 0.3125rem;
|
||||
}
|
||||
div#playground .buttons a,
|
||||
div#menu > a,
|
||||
input#search,
|
||||
#menu-button {
|
||||
border: 0.0625rem solid #375eab;
|
||||
}
|
||||
div#playground .buttons a,
|
||||
div#menu > a,
|
||||
#menu-button {
|
||||
color: white;
|
||||
background: #375eab;
|
||||
}
|
||||
#playgroundButton.active {
|
||||
background: white;
|
||||
color: #375eab;
|
||||
}
|
||||
a#start,
|
||||
div#learn .buttons a,
|
||||
div.play .buttons a,
|
||||
div#blog .read a {
|
||||
color: #222;
|
||||
border: 0.0625rem solid #375eab;
|
||||
background: #e0ebf5;
|
||||
}
|
||||
.download {
|
||||
width: 9.375rem;
|
||||
}
|
||||
|
||||
div#menu {
|
||||
text-align: right;
|
||||
padding: 0.625rem;
|
||||
white-space: nowrap;
|
||||
max-height: 0;
|
||||
-moz-transition: max-height 0.25s linear;
|
||||
transition: max-height 0.25s linear;
|
||||
width: 100%;
|
||||
}
|
||||
div#menu.menu-visible {
|
||||
max-height: 31.25rem;
|
||||
}
|
||||
div#menu > a,
|
||||
#menu-button {
|
||||
margin: 0.625rem 0.125rem;
|
||||
padding: 0.625rem;
|
||||
}
|
||||
::-webkit-input-placeholder {
|
||||
color: #7f7f7f;
|
||||
opacity: 1;
|
||||
}
|
||||
::placeholder {
|
||||
color: #7f7f7f;
|
||||
opacity: 1;
|
||||
}
|
||||
#menu .search-box {
|
||||
display: inline-flex;
|
||||
width: 8.75rem;
|
||||
}
|
||||
input#search {
|
||||
background: white;
|
||||
color: #222;
|
||||
box-sizing: border-box;
|
||||
-webkit-appearance: none;
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
border-right: 0;
|
||||
margin-right: 0;
|
||||
flex-grow: 1;
|
||||
max-width: 100%;
|
||||
min-width: 5.625rem;
|
||||
}
|
||||
input#search:-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
input#search:-moz-ui-invalid {
|
||||
box-shadow: unset;
|
||||
}
|
||||
input#search + button {
|
||||
display: inline;
|
||||
font-size: 1em;
|
||||
background-color: #375eab;
|
||||
color: white;
|
||||
border: 0.0625rem solid #375eab;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0.3125rem;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0.3125rem;
|
||||
margin-left: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
input#search + button span {
|
||||
display: flex;
|
||||
}
|
||||
input#search + button svg {
|
||||
fill: white;
|
||||
}
|
||||
|
||||
#menu-button {
|
||||
display: none;
|
||||
position: absolute;
|
||||
right: 0.3125rem;
|
||||
top: 0;
|
||||
margin-right: 0.3125rem;
|
||||
}
|
||||
#menu-button-arrow {
|
||||
display: inline-block;
|
||||
}
|
||||
.vertical-flip {
|
||||
transform: rotate(-180deg);
|
||||
}
|
||||
|
||||
div.left {
|
||||
float: left;
|
||||
clear: left;
|
||||
margin-right: 2.5%;
|
||||
}
|
||||
div.right {
|
||||
float: right;
|
||||
clear: right;
|
||||
margin-left: 2.5%;
|
||||
}
|
||||
div.left,
|
||||
div.right {
|
||||
width: 45%;
|
||||
}
|
||||
|
||||
div#learn,
|
||||
div#about {
|
||||
padding-top: 1.25rem;
|
||||
}
|
||||
div#learn h2,
|
||||
div#about {
|
||||
margin: 0;
|
||||
}
|
||||
div#about {
|
||||
font-size: 1.25rem;
|
||||
margin: 0 auto 1.875rem;
|
||||
}
|
||||
a#start {
|
||||
display: block;
|
||||
padding: 0.625rem;
|
||||
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
border-radius: 0.3125rem;
|
||||
}
|
||||
a#start .big {
|
||||
display: block;
|
||||
font-weight: bold;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
a#start .desc {
|
||||
display: block;
|
||||
font-size: 0.875rem;
|
||||
font-weight: normal;
|
||||
margin-top: 0.3125rem;
|
||||
}
|
||||
|
||||
div#learn .popout {
|
||||
float: right;
|
||||
display: block;
|
||||
cursor: pointer;
|
||||
font-size: 0.75rem;
|
||||
background: url(/doc/share.png) no-repeat;
|
||||
background-position: right center;
|
||||
padding: 0.375rem 1.688rem;
|
||||
}
|
||||
div#learn pre,
|
||||
div#learn textarea {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-family: Menlo, monospace;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
div#learn .input {
|
||||
padding: 0.625rem;
|
||||
margin-top: 0.625rem;
|
||||
height: 9.375rem;
|
||||
|
||||
border-top-left-radius: 0.3125rem;
|
||||
border-top-right-radius: 0.3125rem;
|
||||
}
|
||||
div#learn .input textarea {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: none;
|
||||
outline: none;
|
||||
resize: none;
|
||||
}
|
||||
div#learn .output {
|
||||
border-top: none !important;
|
||||
|
||||
padding: 0.625rem;
|
||||
height: 3.688rem;
|
||||
overflow: auto;
|
||||
|
||||
border-bottom-right-radius: 0.3125rem;
|
||||
border-bottom-left-radius: 0.3125rem;
|
||||
}
|
||||
div#learn .output pre {
|
||||
padding: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
div#learn .input,
|
||||
div#learn .input textarea,
|
||||
div#learn .output,
|
||||
div#learn .output pre {
|
||||
background: #ffffd8;
|
||||
}
|
||||
div#learn .input,
|
||||
div#learn .output {
|
||||
border: 0.0625rem solid #375eab;
|
||||
}
|
||||
div#learn .buttons {
|
||||
float: right;
|
||||
padding: 1.25rem 0 0.625rem 0;
|
||||
text-align: right;
|
||||
}
|
||||
div#learn .buttons a {
|
||||
height: 1rem;
|
||||
margin-left: 0.3125rem;
|
||||
padding: 0.625rem;
|
||||
}
|
||||
div#learn .toys {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
div#learn .toys select {
|
||||
font-size: 0.875rem;
|
||||
border: 0.0625rem solid #375eab;
|
||||
margin: 0;
|
||||
}
|
||||
div#learn .output .exit {
|
||||
display: none;
|
||||
}
|
||||
|
||||
div#video {
|
||||
max-width: 100%;
|
||||
}
|
||||
div#blog,
|
||||
div#video {
|
||||
margin-top: 2.5rem;
|
||||
}
|
||||
div#blog > a,
|
||||
div#blog > div,
|
||||
div#blog > h2,
|
||||
div#video > a,
|
||||
div#video > div,
|
||||
div#video > h2 {
|
||||
margin-bottom: 0.625rem;
|
||||
}
|
||||
div#blog .title,
|
||||
div#video .title {
|
||||
display: block;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
div#blog .when {
|
||||
color: #666;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
div#blog .read {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
@supports (--c: 0) {
|
||||
[style*='--aspect-ratio-padding:'] {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
padding-top: var(--aspect-ratio-padding);
|
||||
}
|
||||
|
||||
[style*='--aspect-ratio-padding:'] > * {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.toggleButton {
|
||||
cursor: pointer;
|
||||
}
|
||||
.toggle > .collapsed {
|
||||
display: block;
|
||||
}
|
||||
.toggle > .expanded {
|
||||
display: none;
|
||||
}
|
||||
.toggleVisible > .collapsed {
|
||||
display: none;
|
||||
}
|
||||
.toggleVisible > .expanded {
|
||||
display: block;
|
||||
}
|
||||
|
||||
table.codetable {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
border-style: none;
|
||||
}
|
||||
table.codetable td {
|
||||
padding-right: 0.625rem;
|
||||
}
|
||||
hr {
|
||||
border-style: none;
|
||||
border-top: 0.0625rem solid black;
|
||||
}
|
||||
|
||||
img.gopher {
|
||||
float: right;
|
||||
margin-left: 0.625rem;
|
||||
margin-top: -2.5rem;
|
||||
margin-bottom: 0.625rem;
|
||||
z-index: -1;
|
||||
}
|
||||
h2 {
|
||||
clear: right;
|
||||
}
|
||||
|
||||
/* example and drop-down playground */
|
||||
div.play {
|
||||
padding: 0 1.25rem 2.5rem 1.25rem;
|
||||
}
|
||||
div.play pre,
|
||||
div.play textarea,
|
||||
div.play .lines {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
font-family: Menlo, monospace;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
div.play .input {
|
||||
padding: 0.625rem;
|
||||
margin-top: 0.625rem;
|
||||
|
||||
border-top-left-radius: 0.3125rem;
|
||||
border-top-right-radius: 0.3125rem;
|
||||
|
||||
overflow: hidden;
|
||||
}
|
||||
div.play .input textarea {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: none;
|
||||
outline: none;
|
||||
resize: none;
|
||||
|
||||
overflow: hidden;
|
||||
}
|
||||
div#playground .input textarea {
|
||||
overflow: auto;
|
||||
resize: auto;
|
||||
}
|
||||
div.play .output {
|
||||
border-top: none !important;
|
||||
|
||||
padding: 0.625rem;
|
||||
max-height: 12.5rem;
|
||||
overflow: auto;
|
||||
|
||||
border-bottom-right-radius: 0.3125rem;
|
||||
border-bottom-left-radius: 0.3125rem;
|
||||
}
|
||||
div.play .output pre {
|
||||
padding: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
div.play .input,
|
||||
div.play .input textarea,
|
||||
div.play .output,
|
||||
div.play .output pre {
|
||||
background: #ffffd8;
|
||||
}
|
||||
div.play .input,
|
||||
div.play .output {
|
||||
border: 0.0625rem solid #375eab;
|
||||
}
|
||||
div.play .buttons {
|
||||
float: right;
|
||||
padding: 1.25rem 0 0.625rem 0;
|
||||
text-align: right;
|
||||
}
|
||||
div.play .buttons a {
|
||||
height: 1rem;
|
||||
margin-left: 0.3125rem;
|
||||
padding: 0.625rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
.output .stderr {
|
||||
color: #933;
|
||||
}
|
||||
.output .system {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
/* drop-down playground */
|
||||
div#playground {
|
||||
/* start hidden; revealed by javascript */
|
||||
display: none;
|
||||
}
|
||||
div#playground {
|
||||
position: absolute;
|
||||
top: 3.938rem;
|
||||
right: 1.25rem;
|
||||
padding: 0 0.625rem 0.625rem 0.625rem;
|
||||
z-index: 1;
|
||||
text-align: left;
|
||||
background: #e0ebf5;
|
||||
|
||||
border: 0.0625rem solid #b0bbc5;
|
||||
border-top: none;
|
||||
|
||||
border-bottom-left-radius: 0.3125rem;
|
||||
border-bottom-right-radius: 0.3125rem;
|
||||
}
|
||||
div#playground .code {
|
||||
width: 32.5rem;
|
||||
height: 12.5rem;
|
||||
}
|
||||
div#playground .output {
|
||||
height: 6.25rem;
|
||||
}
|
||||
|
||||
/* Inline runnable snippets (play.js/initPlayground) */
|
||||
#content .code pre,
|
||||
#content .playground pre,
|
||||
#content .output pre {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: none;
|
||||
border: none;
|
||||
outline: 0 solid transparent;
|
||||
overflow: auto;
|
||||
}
|
||||
#content .playground .number,
|
||||
#content .code .number {
|
||||
color: #999;
|
||||
}
|
||||
#content .code,
|
||||
#content .playground,
|
||||
#content .output {
|
||||
width: auto;
|
||||
margin: 1.25rem;
|
||||
padding: 0.625rem;
|
||||
border-radius: 0.3125rem;
|
||||
}
|
||||
#content .code,
|
||||
#content .playground {
|
||||
background: #e9e9e9;
|
||||
}
|
||||
#content .output {
|
||||
background: #202020;
|
||||
}
|
||||
#content .output .stdout,
|
||||
#content .output pre {
|
||||
color: #e6e6e6;
|
||||
}
|
||||
#content .output .stderr,
|
||||
#content .output .error {
|
||||
color: rgb(244, 74, 63);
|
||||
}
|
||||
#content .output .system,
|
||||
#content .output .exit {
|
||||
color: rgb(255, 209, 77);
|
||||
}
|
||||
#content .buttons {
|
||||
position: relative;
|
||||
float: right;
|
||||
top: -3.125rem;
|
||||
right: 1.875rem;
|
||||
}
|
||||
#content .output .buttons {
|
||||
top: -3.75rem;
|
||||
right: 0;
|
||||
height: 0;
|
||||
}
|
||||
#content .buttons .kill {
|
||||
display: none;
|
||||
visibility: hidden;
|
||||
}
|
||||
a.error {
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
background-color: darkred;
|
||||
border-bottom-left-radius: 0.25rem;
|
||||
border-bottom-right-radius: 0.25rem;
|
||||
border-top-left-radius: 0.25rem;
|
||||
border-top-right-radius: 0.25rem;
|
||||
padding: 0.125rem 0.25rem 0.125rem 0.25rem; /* TRBL */
|
||||
}
|
||||
|
||||
#heading-narrow {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.downloading {
|
||||
background: #f9f9be;
|
||||
padding: 0.625rem;
|
||||
text-align: center;
|
||||
border-radius: 0.3125rem;
|
||||
}
|
||||
|
||||
@media (max-width: 58.125em) {
|
||||
#heading-wide {
|
||||
display: none;
|
||||
}
|
||||
#heading-narrow {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 47.5em) {
|
||||
.container .left,
|
||||
.container .right {
|
||||
width: auto;
|
||||
float: none;
|
||||
}
|
||||
|
||||
div#about {
|
||||
max-width: 31.25rem;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 43.75em) and (max-width: 62.5em) {
|
||||
div#menu > a {
|
||||
margin: 0.3125rem 0;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
input#search {
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 43.75em) {
|
||||
body {
|
||||
font-size: 0.9375rem;
|
||||
}
|
||||
|
||||
div#playground {
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
pre,
|
||||
code {
|
||||
font-size: 0.866rem;
|
||||
}
|
||||
|
||||
div#page > .container {
|
||||
padding: 0 0.625rem;
|
||||
}
|
||||
|
||||
div#topbar {
|
||||
height: auto;
|
||||
padding: 0.625rem;
|
||||
}
|
||||
|
||||
div#topbar > .container {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#heading-wide {
|
||||
display: block;
|
||||
}
|
||||
#heading-narrow {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.top-heading {
|
||||
float: none;
|
||||
display: inline-block;
|
||||
padding: 0.75rem;
|
||||
}
|
||||
|
||||
div#menu {
|
||||
padding: 0;
|
||||
min-width: 0;
|
||||
text-align: left;
|
||||
float: left;
|
||||
}
|
||||
|
||||
div#menu > a {
|
||||
display: block;
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
#menu .search-box {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#menu-button {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
p,
|
||||
pre,
|
||||
ul,
|
||||
ol {
|
||||
margin: 0.625rem;
|
||||
}
|
||||
|
||||
.pkg-synopsis {
|
||||
display: none;
|
||||
}
|
||||
|
||||
img.gopher {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 30em) {
|
||||
#heading-wide {
|
||||
display: none;
|
||||
}
|
||||
#heading-narrow {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
@media print {
|
||||
pre {
|
||||
background: #fff;
|
||||
border: 0.0625rem solid #bbb;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
}
|
||||