mirror of
https://github.com/golang/go
synced 2024-11-18 14:04:45 -07:00
godoc: Add URLForSrcQuery option to godoc.Presentation.
This allows the creation of URLs to lines of source code with a query term highlighted without assuming godoc source code URL parameters. Needed for interfacing with other source code viewing servers. R=bradfitz CC=golang-dev https://golang.org/cl/34200043
This commit is contained in:
parent
df34f98521
commit
ff7cfafc58
@ -22,6 +22,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
pathpkg "path"
|
pathpkg "path"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
"time"
|
"time"
|
||||||
@ -80,6 +81,7 @@ func (p *Presentation) initFuncMap() {
|
|||||||
"srcLink": srcLinkFunc,
|
"srcLink": srcLinkFunc,
|
||||||
"posLink_url": newPosLink_urlFunc(srcPosLinkFunc),
|
"posLink_url": newPosLink_urlFunc(srcPosLinkFunc),
|
||||||
"docLink": docLinkFunc,
|
"docLink": docLinkFunc,
|
||||||
|
"queryLink": queryLinkFunc,
|
||||||
|
|
||||||
// formatting of Examples
|
// formatting of Examples
|
||||||
"example_html": p.example_htmlFunc,
|
"example_html": p.example_htmlFunc,
|
||||||
@ -96,6 +98,9 @@ func (p *Presentation) initFuncMap() {
|
|||||||
if p.URLForSrcPos != nil {
|
if p.URLForSrcPos != nil {
|
||||||
p.funcMap["posLink_url"] = newPosLink_urlFunc(p.URLForSrcPos)
|
p.funcMap["posLink_url"] = newPosLink_urlFunc(p.URLForSrcPos)
|
||||||
}
|
}
|
||||||
|
if p.URLForSrcQuery != nil {
|
||||||
|
p.funcMap["queryLink"] = p.URLForSrcQuery
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func filenameFunc(path string) string {
|
func filenameFunc(path string) string {
|
||||||
@ -298,6 +303,19 @@ func srcLinkFunc(s string) string {
|
|||||||
return pathpkg.Clean("/" + s)
|
return pathpkg.Clean("/" + s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// queryLinkFunc returns a URL for a line in a source file with a highlighted
|
||||||
|
// query term.
|
||||||
|
// s is expected to be a path to a source file.
|
||||||
|
// query is expected to be a string that has already been appropriately escaped
|
||||||
|
// for use in a URL query.
|
||||||
|
func queryLinkFunc(s, query string, line int) string {
|
||||||
|
url := pathpkg.Clean("/"+s) + "?h=" + query
|
||||||
|
if line > 0 {
|
||||||
|
url += "#L" + strconv.Itoa(line)
|
||||||
|
}
|
||||||
|
return url
|
||||||
|
}
|
||||||
|
|
||||||
func docLinkFunc(s string, ident string) string {
|
func docLinkFunc(s string, ident string) string {
|
||||||
s = strings.TrimPrefix(s, "/src")
|
s = strings.TrimPrefix(s, "/src")
|
||||||
return pathpkg.Clean("/"+s) + "/#" + ident
|
return pathpkg.Clean("/"+s) + "/#" + ident
|
||||||
|
90
godoc/godoc_test.go
Normal file
90
godoc/godoc_test.go
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
// 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 godoc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestPkgLinkFunc(t *testing.T) {
|
||||||
|
for _, tc := range []struct {
|
||||||
|
path string
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{"/src/pkg/fmt", "pkg/fmt"},
|
||||||
|
{"/fmt", "pkg/fmt"},
|
||||||
|
} {
|
||||||
|
if got, want := pkgLinkFunc(tc.path), tc.want; got != want {
|
||||||
|
t.Errorf("pkgLinkFunc(%v) = %v; want %v", tc.path, got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSrcPosLinkFunc(t *testing.T) {
|
||||||
|
for _, tc := range []struct {
|
||||||
|
src string
|
||||||
|
line int
|
||||||
|
low int
|
||||||
|
high int
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{"/src/pkg/fmt/print.go", 42, 30, 50, "/src/pkg/fmt/print.go?s=30:50#L32"},
|
||||||
|
{"/src/pkg/fmt/print.go", 2, 1, 5, "/src/pkg/fmt/print.go?s=1:5#L1"},
|
||||||
|
{"/src/pkg/fmt/print.go", 2, 0, 0, "/src/pkg/fmt/print.go#L2"},
|
||||||
|
{"/src/pkg/fmt/print.go", 0, 0, 0, "/src/pkg/fmt/print.go"},
|
||||||
|
{"/src/pkg/fmt/print.go", 0, 1, 5, "/src/pkg/fmt/print.go?s=1:5#L1"},
|
||||||
|
} {
|
||||||
|
if got, want := srcPosLinkFunc(tc.src, tc.line, tc.low, tc.high), tc.want; got != want {
|
||||||
|
t.Errorf("srcLinkFunc(%v, %v, %v, %v) = %v; want %v", tc.src, tc.line, tc.low, tc.high, got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSrcLinkFunc(t *testing.T) {
|
||||||
|
for _, tc := range []struct {
|
||||||
|
src string
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{"/src/pkg/fmt/print.go", "/src/pkg/fmt/print.go"},
|
||||||
|
{"src/pkg/fmt/print.go", "/src/pkg/fmt/print.go"},
|
||||||
|
} {
|
||||||
|
if got, want := srcLinkFunc(tc.src), tc.want; got != want {
|
||||||
|
t.Errorf("srcLinkFunc(%v) = %v; want %v", tc.src, got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestQueryLinkFunc(t *testing.T) {
|
||||||
|
for _, tc := range []struct {
|
||||||
|
src string
|
||||||
|
query string
|
||||||
|
line int
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{"/src/pkg/fmt/print.go", "Sprintf", 33, "/src/pkg/fmt/print.go?h=Sprintf#L33"},
|
||||||
|
{"/src/pkg/fmt/print.go", "Sprintf", 0, "/src/pkg/fmt/print.go?h=Sprintf"},
|
||||||
|
{"src/pkg/fmt/print.go", "EOF", 33, "/src/pkg/fmt/print.go?h=EOF#L33"},
|
||||||
|
{"src/pkg/fmt/print.go", "a%3f+%26b", 1, "/src/pkg/fmt/print.go?h=a%3f+%26b#L1"},
|
||||||
|
} {
|
||||||
|
if got, want := queryLinkFunc(tc.src, tc.query, tc.line), tc.want; got != want {
|
||||||
|
t.Errorf("queryLinkFunc(%v, %v, %v) = %v; want %v", tc.src, tc.query, tc.line, got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDocLinkFunc(t *testing.T) {
|
||||||
|
for _, tc := range []struct {
|
||||||
|
src string
|
||||||
|
ident string
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{"/src/pkg/fmt", "Sprintf", "/pkg/fmt/#Sprintf"},
|
||||||
|
{"/src/pkg/fmt", "EOF", "/pkg/fmt/#EOF"},
|
||||||
|
} {
|
||||||
|
if got, want := docLinkFunc(tc.src, tc.ident), tc.want; got != want {
|
||||||
|
t.Errorf("docLinkFunc(%v, %v) = %v; want %v", tc.src, tc.ident, got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -67,6 +67,15 @@ type Presentation struct {
|
|||||||
// The source file argument has the form /src/pkg/<path>/<filename>.
|
// The source file argument has the form /src/pkg/<path>/<filename>.
|
||||||
URLForSrcPos func(src string, line, low, high int) string
|
URLForSrcPos func(src string, line, low, high int) string
|
||||||
|
|
||||||
|
// URLForSrcQuery optionally specifies a function to create a URL given a
|
||||||
|
// source file, a query string, and a line from the source file (1-based).
|
||||||
|
// The source file argument has the form /src/pkg/<path>/<filename>.
|
||||||
|
// The query argument will be escaped for the purposes of embedding in a URL
|
||||||
|
// query parameter.
|
||||||
|
// Ideally, the returned URL will be for the specified line of the file with
|
||||||
|
// the query string highlighted.
|
||||||
|
URLForSrcQuery func(src, query string, line int) string
|
||||||
|
|
||||||
initFuncMapOnce sync.Once
|
initFuncMapOnce sync.Once
|
||||||
funcMap template.FuncMap
|
funcMap template.FuncMap
|
||||||
templateFuncs template.FuncMap
|
templateFuncs template.FuncMap
|
||||||
|
@ -50,10 +50,11 @@
|
|||||||
{{$pkg_html := pkgLink .Pak.Path | html}}
|
{{$pkg_html := pkgLink .Pak.Path | html}}
|
||||||
<h3 id="Global_{{$pkg_html}}">package <a href="/{{$pkg_html}}">{{html .Pak.Name}}</a></h3>
|
<h3 id="Global_{{$pkg_html}}">package <a href="/{{$pkg_html}}">{{html .Pak.Name}}</a></h3>
|
||||||
{{range .Files}}
|
{{range .Files}}
|
||||||
{{$src_html := srcLink .File.Path | html}}
|
{{$file := .File.Path}}
|
||||||
{{range .Groups}}
|
{{range .Groups}}
|
||||||
{{range .}}
|
{{range .}}
|
||||||
<a href="{{$src_html}}?h={{$query_url}}#L{{infoLine .}}">{{$src_html}}:{{infoLine .}}</a>
|
{{$line := infoLine .}}
|
||||||
|
<a href="{{queryLink $file $query_url $line | html}}">{{$file}}:{{$line}}</a>
|
||||||
{{infoSnippet_html .}}
|
{{infoSnippet_html .}}
|
||||||
{{end}}
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
@ -66,8 +67,8 @@
|
|||||||
{{$pkg_html := pkgLink .Pak.Path | html}}
|
{{$pkg_html := pkgLink .Pak.Path | html}}
|
||||||
<h3 id="Local_{{$pkg_html}}">package <a href="/{{$pkg_html}}">{{html .Pak.Name}}</a></h3>
|
<h3 id="Local_{{$pkg_html}}">package <a href="/{{$pkg_html}}">{{html .Pak.Name}}</a></h3>
|
||||||
{{range .Files}}
|
{{range .Files}}
|
||||||
{{$src_html := srcLink .File.Path | html}}
|
{{$file := .File.Path}}
|
||||||
<a href="{{$src_html}}?h={{$query_url}}">{{$src_html}}</a>
|
<a href="{{queryLink $file $query_url 0 | html}}">{{$file}}</a>
|
||||||
<table class="layout">
|
<table class="layout">
|
||||||
{{range .Groups}}
|
{{range .Groups}}
|
||||||
<tr>
|
<tr>
|
||||||
@ -76,7 +77,8 @@
|
|||||||
<td align="left" width="4"></td>
|
<td align="left" width="4"></td>
|
||||||
<td>
|
<td>
|
||||||
{{range .}}
|
{{range .}}
|
||||||
<a href="{{$src_html}}?h={{$query_url}}#L{{infoLine .}}">{{infoLine .}}</a>
|
{{$line := infoLine .}}
|
||||||
|
<a href="{{queryLink $file $query_url $line | html}}">{{$line}}</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -98,17 +100,17 @@
|
|||||||
<p>
|
<p>
|
||||||
<table class="layout">
|
<table class="layout">
|
||||||
{{range .}}
|
{{range .}}
|
||||||
{{$src_html := srcLink .Filename | html}}
|
{{$file := .Filename}}
|
||||||
<tr>
|
<tr>
|
||||||
<td align="left" valign="top">
|
<td align="left" valign="top">
|
||||||
<a href="{{$src_html}}?h={{$query_url}}">{{$src_html}}</a>:
|
<a href="{{queryLink $file $query_url 0}}">{{$file}}</a>:
|
||||||
</td>
|
</td>
|
||||||
<td align="left" width="4"></td>
|
<td align="left" width="4"></td>
|
||||||
<th align="left" valign="top">{{len .Lines}}</th>
|
<th align="left" valign="top">{{len .Lines}}</th>
|
||||||
<td align="left" width="4"></td>
|
<td align="left" width="4"></td>
|
||||||
<td align="left">
|
<td align="left">
|
||||||
{{range .Lines}}
|
{{range .Lines}}
|
||||||
<a href="{{$src_html}}?h={{$query_url}}#L{{html .}}">{{html .}}</a>
|
<a href="{{queryLink $file $query_url .}}">{{html .}}</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if not $.Complete}}
|
{{if not $.Complete}}
|
||||||
...
|
...
|
||||||
|
@ -1413,10 +1413,11 @@ function PlaygroundOutput(el) {
|
|||||||
{{$pkg_html := pkgLink .Pak.Path | html}}
|
{{$pkg_html := pkgLink .Pak.Path | html}}
|
||||||
<h3 id="Global_{{$pkg_html}}">package <a href="/{{$pkg_html}}">{{html .Pak.Name}}</a></h3>
|
<h3 id="Global_{{$pkg_html}}">package <a href="/{{$pkg_html}}">{{html .Pak.Name}}</a></h3>
|
||||||
{{range .Files}}
|
{{range .Files}}
|
||||||
{{$src_html := srcLink .File.Path | html}}
|
{{$file := .File.Path}}
|
||||||
{{range .Groups}}
|
{{range .Groups}}
|
||||||
{{range .}}
|
{{range .}}
|
||||||
<a href="{{$src_html}}?h={{$query_url}}#L{{infoLine .}}">{{$src_html}}:{{infoLine .}}</a>
|
{{$line := infoLine .}}
|
||||||
|
<a href="{{queryLink $file $query_url $line | html}}">{{$file}}:{{$line}}</a>
|
||||||
{{infoSnippet_html .}}
|
{{infoSnippet_html .}}
|
||||||
{{end}}
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
@ -1429,8 +1430,8 @@ function PlaygroundOutput(el) {
|
|||||||
{{$pkg_html := pkgLink .Pak.Path | html}}
|
{{$pkg_html := pkgLink .Pak.Path | html}}
|
||||||
<h3 id="Local_{{$pkg_html}}">package <a href="/{{$pkg_html}}">{{html .Pak.Name}}</a></h3>
|
<h3 id="Local_{{$pkg_html}}">package <a href="/{{$pkg_html}}">{{html .Pak.Name}}</a></h3>
|
||||||
{{range .Files}}
|
{{range .Files}}
|
||||||
{{$src_html := srcLink .File.Path | html}}
|
{{$file := .File.Path}}
|
||||||
<a href="{{$src_html}}?h={{$query_url}}">{{$src_html}}</a>
|
<a href="{{queryLink $file $query_url 0 | html}}">{{$file}}</a>
|
||||||
<table class="layout">
|
<table class="layout">
|
||||||
{{range .Groups}}
|
{{range .Groups}}
|
||||||
<tr>
|
<tr>
|
||||||
@ -1439,7 +1440,8 @@ function PlaygroundOutput(el) {
|
|||||||
<td align="left" width="4"></td>
|
<td align="left" width="4"></td>
|
||||||
<td>
|
<td>
|
||||||
{{range .}}
|
{{range .}}
|
||||||
<a href="{{$src_html}}?h={{$query_url}}#L{{infoLine .}}">{{infoLine .}}</a>
|
{{$line := infoLine .}}
|
||||||
|
<a href="{{queryLink $file $query_url $line | html}}">{{$line}}</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -1461,17 +1463,17 @@ function PlaygroundOutput(el) {
|
|||||||
<p>
|
<p>
|
||||||
<table class="layout">
|
<table class="layout">
|
||||||
{{range .}}
|
{{range .}}
|
||||||
{{$src_html := srcLink .Filename | html}}
|
{{$file := .Filename}}
|
||||||
<tr>
|
<tr>
|
||||||
<td align="left" valign="top">
|
<td align="left" valign="top">
|
||||||
<a href="{{$src_html}}?h={{$query_url}}">{{$src_html}}</a>:
|
<a href="{{queryLink $file $query_url 0}}">{{$file}}</a>:
|
||||||
</td>
|
</td>
|
||||||
<td align="left" width="4"></td>
|
<td align="left" width="4"></td>
|
||||||
<th align="left" valign="top">{{len .Lines}}</th>
|
<th align="left" valign="top">{{len .Lines}}</th>
|
||||||
<td align="left" width="4"></td>
|
<td align="left" width="4"></td>
|
||||||
<td align="left">
|
<td align="left">
|
||||||
{{range .Lines}}
|
{{range .Lines}}
|
||||||
<a href="{{$src_html}}?h={{$query_url}}#L{{html .}}">{{html .}}</a>
|
<a href="{{queryLink $file $query_url .}}">{{html .}}</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if not $.Complete}}
|
{{if not $.Complete}}
|
||||||
...
|
...
|
||||||
|
Loading…
Reference in New Issue
Block a user