[インデックス 11874] ファイルの概要
このコミットは、Go言語のドキュメンテーションツールであるgodoc
において、パッケージのインデックスページにExample(サンプルコード)の一覧を表示し、それらのExampleへのリンク機能を追加するものです。これにより、ユーザーはパッケージのドキュメントを閲覧する際に、利用可能なExampleをより簡単に見つけ、アクセスできるようになります。
コミット
godoc
ツールが生成するドキュメントにおいて、パッケージのインデックスページにExampleの一覧を追加し、各Exampleへのリンクを有効にします。これにより、ユーザーはパッケージの機能を示すサンプルコードに素早くアクセスできるようになります。
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/5ab935f68a43a503b791e4513a6e76ee615929ff
元コミット内容
commit 5ab935f68a43a503b791e4513a6e76ee615929ff
Author: Andrew Gerrand <adg@golang.org>
Date: Tue Feb 14 14:52:00 2012 +1100
godoc: list examples in index
Fixes #2897.
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/5658047
変更の背景
この変更は、Go言語のIssue #2897「godoc
: list examples in index」を修正するために行われました。
Go言語のドキュメンテーションツールであるgodoc
は、Goのソースコードから自動的にドキュメントを生成する非常に便利なツールです。Goのパッケージには、その使い方を示すためにExample(サンプルコード)を含めることが推奨されており、godoc
はこれらのExampleも解析してドキュメントに表示します。
しかし、このコミットが適用される前は、godoc
が生成するパッケージのインデックスページ(パッケージの概要が表示されるページ)には、Exampleの一覧が直接表示されていませんでした。Exampleを見るためには、ユーザーはドキュメントをスクロールしてExampleセクションを探す必要がありました。これは、特にExampleが多いパッケージの場合、ユーザーエクスペリエンスを損なう可能性がありました。
Issue #2897は、この問題を解決し、ユーザーがパッケージのドキュメントにアクセスした際に、利用可能なExampleをすぐに認識し、クリック一つで該当のExampleセクションにジャンプできるようにすることを目的としていました。これにより、godoc
の利便性が向上し、Goのパッケージの理解がより容易になります。
前提知識の解説
godoc
godoc
は、Go言語のソースコードからドキュメンテーションを生成し、HTTPサーバーとして提供するツールです。Goのコードに記述されたコメントやExampleコードを解析し、整形されたHTMLドキュメントとして表示します。Goの標準ライブラリのドキュメントもgodoc
によって生成されており、pkg.go.dev
(旧golang.org/pkg
)で公開されています。
GoのExample
Go言語では、パッケージの利用方法を示すためのExampleコードを記述することができます。これらのExampleは、Example
というプレフィックスを持つ関数として定義され、_test.go
ファイル内に配置されます。godoc
はこれらのExampleを自動的に検出し、生成されるドキュメントに含めます。Exampleは単なるコードスニペットではなく、テストとしても機能し、go test
コマンドで実行してその出力が期待通りであるか検証することも可能です。
HTMLテンプレートとJavaScript
godoc
は、ドキュメントの表示にHTMLテンプレートを使用しています。これらのテンプレートは、Goのhtml/template
パッケージによって処理され、動的にコンテンツが生成されます。また、生成されたHTMLドキュメントには、ユーザーインターフェースのインタラクティブな要素(例: Exampleの表示/非表示切り替え)を制御するためのJavaScriptコードも含まれています。
技術的詳細
このコミットは、godoc
が生成するHTMLドキュメントの構造と、それを制御するJavaScriptコードに複数の変更を加えています。
-
doc/godocs.js
の変更:godocs_bindExampleToggles()
関数がgodocs_bindExamples()
にリネームされ、機能が拡張されました。godocs_bindExamples()
は、既存のExampleの表示/非表示を切り替える機能に加えて、新しく追加されるExampleへのリンク(.exampleLink
クラスを持つ要素)に対するクリックイベントハンドラgodocs_bindExampleLink()
をバインドするようになりました。godocs_bindExampleLink()
関数が追加されました。この関数は、Exampleへのリンクがクリックされた際に、対応するExample要素(id="example_{{.Name}}"
を持つdiv
要素)のクラスをexampleVisible
に変更し、Exampleが展開された状態で表示されるようにします。これは、URLのハッシュ(#example_ExampleName
)を利用して、特定のExampleに直接ジャンプする動作を模倣しています。
-
lib/godoc/example.html
の変更:- Exampleのルートとなる
div
要素にid="example_{{.Name}}"
が追加されました。これにより、JavaScriptから特定のExample要素をIDで参照できるようになり、Exampleへの直接リンクが可能になります。{{.Name}}
はExample関数の名前が埋め込まれるプレースホルダーです。
- Exampleのルートとなる
-
lib/godoc/package.html
の変更:- パッケージのインデックスページを生成するHTMLテンプレートに、新しいセクションが追加されました。
{{if $.Examples}}
ブロックが追加され、パッケージにExampleが存在する場合にのみ「Examples」という見出しとExampleの一覧が表示されるようになりました。{{range $.Examples}}
ループを使って、各Exampleの名前とそれに対応するリンクが生成されます。- 各Exampleへのリンクは
<a class="exampleLink" href="#example_{{.Name}}">{{.Name}}</a>
という形式で生成されます。exampleLink
クラスはgodocs.js
でイベントハンドラをバインドするために使用され、href="#example_{{.Name}}"
はページ内の対応するIDを持つ要素へのアンカーリンクとして機能します。
-
src/cmd/godoc/godoc.go
の変更:example_htmlFunc
関数において、ExampleのHTMLテンプレートに渡すデータ構造が変更されました。- 以前は
Code
とOutput
のみを渡していましたが、この変更によりName
フィールドも追加で渡されるようになりました。これにより、lib/godoc/example.html
テンプレート内でExampleの名前({{.Name}}
)をIDとして利用できるようになります。
これらの変更により、godoc
はパッケージのインデックスページにExampleの一覧を動的に生成し、ユーザーがクリックすることで該当のExampleセクションにスムーズに移動できる機能を提供します。
コアとなるコードの変更箇所
doc/godocs.js
--- a/doc/godocs.js
+++ b/doc/godocs.js
@@ -23,7 +23,7 @@ bindEvent(window, 'load', godocs_onload);
function godocs_onload() {
godocs_bindSearchEvents();
godocs_generateTOC();
- godocs_bindExampleToggles();
+ godocs_bindExamples();
}
function godocs_bindSearchEvents() {
@@ -158,11 +158,14 @@ function godocs_nodeToText(node) {
return text;
}
-function godocs_bindExampleToggles() {
+function godocs_bindExamples() {
var examples = document.getElementsByClassName("example");
for (var i = 0; i < examples.length; i++) {
- var eg = examples[i];
- godocs_bindExampleToggle(eg);
+ godocs_bindExampleToggle(examples[i]);
+ }
+ var links = document.getElementsByClassName("exampleLink");
+ for (var i = 0; i < links.length; i++) {
+ godocs_bindExampleLink(links[i]);
}
}
function godocs_bindExampleToggle(eg) {
@@ -177,3 +180,14 @@ function godocs_bindExampleToggle(eg) {
});
}
}
+function godocs_bindExampleLink(l) {
+ var prefix = "example_";
+ bindEvent(l, "click", function() {
+ var i = l.href.indexOf("#"+prefix);
+ if (i < 0)
+ return;
+ var id = prefix + l.href.slice(i+1+prefix.length);
+ var eg = document.getElementById(id);
+ eg.className = "exampleVisible";
+ });
+}
lib/godoc/example.html
--- a/lib/godoc/example.html
+++ b/lib/godoc/example.html
@@ -1,4 +1,4 @@
-<div class="example">\
+<div id="example_{{.Name}}" class="example">\
<div class="collapsed">\
<p class="exampleHeading">▹ Example</p>\
</div>
lib/godoc/package.html
--- a/lib/godoc/package.html
+++ b/lib/godoc/package.html
@@ -52,6 +52,15 @@
{{end}}
</dl>
+ {{if $.Examples}}
+ <h4>Examples</h4>
+ <dl>
+ {{range $.Examples}}
+ <dd><a class="exampleLink" href="#example_{{.Name}}">{{.Name}}</a></dd>
+ {{end}}
+ </dl>
+ {{end}}
+
{{with .Filenames}}
<h4>Package files</h4>
<p>
src/cmd/godoc/godoc.go
--- a/src/cmd/godoc/godoc.go
+++ b/src/cmd/godoc/godoc.go
@@ -522,8 +522,8 @@ func example_htmlFunc(funcName string, examples []*doc.Example, fset *token.File
code = code[2 : len(code)-2]
err := exampleHTML.Execute(&buf, struct {
-\t\t\tCode, Output string
-\t\t}{code, eg.Output})\
+\t\t\tName, Code, Output string
+\t\t}{name, code, eg.Output})\
if err != nil {
log.Print(err)
}
コアとなるコードの解説
このコミットの核となる変更は、godoc
が生成するHTMLドキュメントにExampleの一覧を動的に追加し、それらのExampleへのナビゲーションをJavaScriptで制御することです。
-
src/cmd/godoc/godoc.go
:example_htmlFunc
は、個々のExampleのHTMLを生成する際に使用される関数です。この変更により、ExampleのName
(Example関数の名前)がHTMLテンプレートに渡されるようになりました。これは、後述するlib/godoc/example.html
でExampleのdiv
要素に一意のIDを付与するために必要です。
-
lib/godoc/example.html
:- 各ExampleのHTMLブロックのルート
div
要素にid="example_{{.Name}}"
が追加されました。これにより、各ExampleがJavaScriptから一意に識別できるようになります。例えば、ExampleHello
というExampleがあれば、そのdiv
にはid="example_ExampleHello"
が付与されます。
- 各ExampleのHTMLブロックのルート
-
lib/godoc/package.html
:- このファイルはパッケージの概要ページを生成するテンプレートです。
{{if $.Examples}}
と{{range $.Examples}}
のGoテンプレート構文が導入されました。これは、パッケージにExampleが存在する場合にのみ、「Examples」という見出しと、その下に各Exampleへのリンクのリストを動的に生成することを意味します。- 各リンクは
<a class="exampleLink" href="#example_{{.Name}}">{{.Name}}</a>
という形式で生成されます。class="exampleLink"
: このクラスは、JavaScriptがこれらのリンクを識別し、クリックイベントをバインドするために使用されます。href="#example_{{.Name}}"
: これはHTMLのアンカーリンクであり、クリックされるとページ内の対応するIDを持つ要素(つまり、lib/godoc/example.html
で定義されたExampleのdiv
)にスクロールします。
-
doc/godocs.js
:godocs_bindExamples()
関数が、既存のExampleの表示/非表示切り替え機能に加えて、新しく追加された.exampleLink
クラスを持つ要素(Exampleへのリンク)に対するイベントリスナーをバインドするようになりました。godocs_bindExampleLink(l)
関数が追加されました。この関数は、Exampleへのリンクがクリックされたときに実行されます。- リンクの
href
属性からExampleのID(例:example_ExampleHello
)を抽出し、そのIDを持つ要素(eg
)を取得します。 - 取得したExample要素の
className
をexampleVisible
に設定します。これにより、Exampleが非表示の状態(collapsed
クラスが適用されている状態)から表示状態に切り替わります。
- リンクの
これらの変更が連携することで、godoc
はパッケージのインデックスページにExampleの一覧を表示し、ユーザーがそのリンクをクリックすると、JavaScriptが対応するExampleセクションを自動的に展開して表示する、というスムーズなユーザー体験を提供します。
関連リンク
- Go CL 5658047: https://golang.org/cl/5658047
参考にした情報源リンク
- Go Issue 2897:
godoc
: list examples in index: https://github.com/golang/go/issues/2897 - Go Example (Testing): https://go.dev/blog/examples
- Go Doc:
godoc
command: https://pkg.go.dev/cmd/godoc - Go Doc:
html/template
package: https://pkg.go.dev/html/template - HTML
id
attribute: https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/id - HTML
href
attribute (Anchor links): https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#attr-href - JavaScript
document.getElementById()
: https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById - JavaScript
Element.className
: https://developer.mozilla.org/en-US/docs/Web/API/Element/className