Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 16688] ファイルの概要

このコミットは、doc/godocs.jslib/godoc/package.html の2つのファイルを変更しています。これらはGo言語の公式ドキュメントサイト golang.org における、Goコードの例(Example)の表示と実行機能に関連するファイルです。

  • doc/godocs.js: golang.org のドキュメントページで利用されるJavaScriptファイルで、UIのインタラクションや動的なコンテンツの挙動を制御します。特に、トグル可能なセクションの表示/非表示や、Go Playgroundの初期化に関わっています。
  • lib/godoc/package.html: godoc ツールがパッケージドキュメントを生成する際に使用するHTMLテンプレートです。Goのパッケージドキュメントページ(例: golang.org/pkg/strings/)の構造とコンテンツを定義しており、Goコードの例を埋め込む部分が含まれます。

コミット

このコミットは、golang.org 上でGoのExampleコードに直接リンクした場合に、そのExampleが正しく表示されず、Go Playgroundで実行できない問題を修正します。具体的には、Exampleセクションが既に表示されている場合でも、Go Playgroundが適切にセットアップされるようにJavaScriptのロジックを調整しています。

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/493538adbfc5a580f9c5c92e2789769a7237e19a

元コミット内容

commit 493538adbfc5a580f9c5c92e2789769a7237e19a
Author: Andrew Gerrand <adg@golang.org>
Date:   Tue Jul 2 08:44:25 2013 +1000

    cmd/godoc: set up playground for examples that are already visible
    
    This fixes an issue where linking directly to an example makes it not
    runnable and visible only in a tiny window. To see the bug in action,
    visit this link: http://golang.org/pkg/strings/#example_Map
    
    R=golang-dev, r
    CC=golang-dev
    https://golang.org/cl/10679050

変更の背景

Go言語の公式ドキュメントサイト golang.org では、各パッケージのドキュメントページにGoコードのExampleが埋め込まれており、これらはGo Playgroundと連携してブラウザ上で直接実行できるようになっています。通常、これらのExampleは初期状態では折りたたまれており、ユーザーが「Example」セクションをクリックして展開すると、Go Playgroundが初期化され、コードが表示・実行可能になります。

しかし、このコミットが修正しようとしている問題は、特定のExampleに直接リンク(例: http://golang.org/pkg/strings/#example_Map のようにURLのフラグメント識別子 # を使ってExampleのIDを指定)した場合に発生していました。この直接リンクによってページがロードされると、ブラウザは指定されたExampleセクションまでスクロールしますが、そのセクションは「既に表示されている」と認識されるため、通常Exampleを展開する際にトリガーされるGo Playgroundの初期化ロジックが実行されませんでした。結果として、Exampleコードは小さなウィンドウに表示されるだけで、Go Playgroundの実行ボタンや出力領域が表示されず、コードを実行できない状態になっていました。

この問題はユーザーエクスペリエンスを著しく損なうものであり、Exampleへのディープリンクの有用性を低下させていました。

前提知識の解説

godoc

godoc はGo言語の公式ツールの一つで、Goのソースコードからドキュメントを生成し、HTTPサーバーとして提供する機能を持っています。golang.org のドキュメントサイトも、この godoc ツールによって生成されたコンテンツを基盤としています。godoc は、Goのソースコード内のコメントやExampleコードを解析し、整形されたHTMLドキュメントとして出力します。

Go Playground

Go Playgroundは、Go言語のコードをブラウザ上で記述、コンパイル、実行できるオンラインサービスです。golang.org のExampleコードは、このGo Playgroundの機能を利用して、ユーザーがブラウザ上で直接コードを試せるようになっています。Go Playgroundは、ユーザーが入力したコードをGoogleのサーバー上で安全に実行し、その結果をブラウザに返します。

HTMLのフラグメント識別子(#ハッシュ)

URLの末尾に # とそれに続く文字列(フラグメント識別子)がある場合、ブラウザはその識別子に対応するIDを持つHTML要素までページをスクロールします。例えば、http://example.com/page.html#section2 というURLは、page.html 内の id="section2" を持つ要素までスクロールします。この機能は、ページ内の特定の部分に直接リンクするために広く使われています。

jQueryの .toggle().click()

このコミットのコードでは、JavaScriptライブラリであるjQueryが使用されています。

  • .toggle(): 要素の表示/非表示を切り替えるメソッドです。
  • .click(): 要素がクリックされたときに実行されるイベントハンドラを設定するメソッドです。
  • .is(':visible'): 要素が現在表示されているかどうかを判定するセレクタです。
  • .find('.toggleButton').first().click(): 特定の要素(.toggle クラスを持つ要素)の中から、.toggleButton クラスを持つ最初の子要素を見つけ、その要素に対してプログラム的にクリックイベントを発生させます。

技術的詳細

このコミットの修正は、主に lib/godoc/package.html 内のJavaScriptロジックと、doc/godocs.js の小さな変更によって構成されています。

lib/godoc/package.html の変更

以前のバージョンでは、Go Playgroundのセットアップは、Exampleコードを含む div.play 要素の親である .toggle クラスを持つ要素がクリックされたときにのみ実行されるようになっていました。このロジックは以下のようでした。

// Old logic
$('div.play').each(function (i, el) {
    var built = false;
    $(el).closest('.toggle').click(function() {
        if (built) {
            return;
        }
        built = true;
        // Set up playground.
        // ... playground setup code ...
    });
});

このコミックでは、このロジックが以下のように変更されました。

  1. setup 関数への抽出: Go Playgroundの初期化ロジックが setup という名前の関数に抽出されました。これにより、コードの再利用性が向上し、異なる条件で同じセットアップ処理を呼び出すことが可能になりました。

    var setup = function() {
        var code = $('.code', el);
        playground({
            'codeEl':   code,
            // ... other playground options ...
        });
        // ... resize logic ...
    };
    
  2. 初期表示時のGo Playgroundセットアップ: ページロード時にExampleセクションが既に表示されている(つまり、直接リンクによって表示された)場合、setup() 関数を直ちに呼び出すように変更されました。これは $(el).is(':visible') を使って判定されます。

    if ($(el).is(':visible')) {
        setup();
        return; // 既にセットアップされたので、以降のクリックイベントハンドラは不要
    }
    
  3. クリックイベントハンドラの維持: Exampleが初期表示されていない(通常の状態)場合は、以前と同様に .toggle 要素がクリックされたときに setup() 関数が呼び出されるように、クリックイベントハンドラが設定されます。ただし、built フラグを使って、セットアップが一度だけ行われるように制御されています。

    var built = false;
    $(el).closest('.toggle').click(function() {
        if (!built) {
            setup();
            built = true;
        }
    });
    

この変更により、Exampleが直接リンクによって表示された場合でも、$(el).is(':visible') の条件が真となり、setup() 関数が即座に実行されるため、Go Playgroundが正しく初期化され、Exampleコードが実行可能になります。

doc/godocs.js の変更

doc/godocs.jstoggleHash() 関数も変更されています。この関数は、URLのハッシュ(フラグメント識別子)に基づいて、対応する要素の表示状態を調整する役割を担っています。

以前のコードでは、ハッシュに対応する要素が .toggle クラスを持っている場合、その要素に toggleVisible クラスを追加し、.toggle クラスを削除していました。

// Old logic
if (hash.is('.toggle')) {
    hash.addClass('toggleVisible').removeClass('toggle');
}

新しいコードでは、この部分が以下のように変更されました。

// New logic
if (hash.is('.toggle')) {
    hash.find('.toggleButton').first().click();
}

この変更は、直接リンクされたExampleセクションが toggle クラスを持つ場合、そのセクション内の最初の .toggleButton 要素に対してプログラム的にクリックイベントを発生させることを意味します。これにより、lib/godoc/package.html で定義されたクリックイベントハンドラがトリガーされ、Go Playgroundのセットアップロジックが実行されるようになります。これは、lib/godoc/package.html の変更と連携して、Exampleが直接リンクされた際にGo Playgroundが正しく初期化されることを保証します。

コアとなるコードの変更箇所

doc/godocs.js

--- a/doc/godocs.js
+++ b/doc/godocs.js
@@ -182,7 +182,7 @@ function fixFocus() {
 function toggleHash() {
     var hash = $(window.location.hash);\n     if (hash.is('.toggle')) {
-      hash.addClass('toggleVisible').removeClass('toggle');
+      hash.find('.toggleButton').first().click();
     }
 }

lib/godoc/package.html

--- a/lib/godoc/package.html
+++ b/lib/godoc/package.html
@@ -231,15 +231,8 @@ $(document).ready(function() {
 	'use strict';
 	// Set up playground when each element is toggled.
 	$('div.play').each(function (i, el) {
-\t\tvar built = false;
-\t\t$(el).closest('.toggle').click(function() {
-\t\t\t// Only set up playground once.
-\t\t\tif (built) {
-\t\t\t\treturn;
-\t\t\t}
-\t\t\tbuilt = true;
-\n-\t\t\t// Set up playground.
+\t\t// Set up playground for this example.
+\t\tvar setup = function() {
 \t\t\tvar code = $('.code', el);
 \t\t\tplayground({
 \t\t\t\t'codeEl':   code,
@@ -260,6 +253,22 @@ $(document).ready(function() {
 \t\t\tcode.on('keydown', resize);
 \t\t\tcode.on('keyup', resize);
 \t\t\tcode.keyup(); // resize now.
+\t\t};\n+\t\t
+\t\t// If example already visible, set up playground now.\n+\t\tif ($(el).is(':visible')) {
+\t\t\tsetup();
+\t\t\treturn;\n+\t\t}
+\n+\t\t// Otherwise, set up playground when example is expanded.\n+\t\tvar built = false;\n+\t\t$(el).closest('.toggle').click(function() {
+\t\t\t// Only set up once.\n+\t\t\tif (!built) {
+\t\t\t\tsetup();
+\t\t\t\tbuilt = true;\n+\t\t\t}
 \t\t});
 \t});
 });

コアとなるコードの解説

doc/godocs.js の変更

toggleHash() 関数内の変更は、URLのハッシュによって特定のExampleセクションに直接アクセスした場合の挙動を改善します。

  • hash.addClass('toggleVisible').removeClass('toggle'); から hash.find('.toggleButton').first().click();:
    • 以前のコードは、ハッシュで指定された要素(Exampleセクション)が .toggle クラスを持っている場合、その要素の表示状態を直接変更していました。しかし、これだけではGo Playgroundの初期化に必要なJavaScriptイベントがトリガーされませんでした。
    • 新しいコードでは、ハッシュで指定されたExampleセクション内の「トグルボタン」(通常はExampleの表示/非表示を切り替えるためのボタン)をプログラム的にクリックします。この「クリック」によって、lib/godoc/package.html で設定されているクリックイベントハンドラが発火し、Go Playgroundのセットアップロジックが実行されるようになります。これにより、直接リンクされたExampleでもGo Playgroundが正しく機能するようになります。

lib/godoc/package.html の変更

このファイルでは、各Example (div.play) のGo Playgroundセットアップロジックが大幅に改善されています。

  • Go Playgroundセットアップロジックの setup 関数への抽出:

    • 以前は、Go Playgroundの初期化コードがクリックイベントハンドラ内に直接記述されていました。
    • 新しいコードでは、この初期化ロジックが setup という独立した関数にまとめられました。これにより、コードの可読性が向上し、同じセットアップロジックを複数の場所から呼び出すことが容易になります。
  • if ($(el).is(':visible')) { setup(); return; } の追加:

    • これがこのコミットの最も重要な変更点です。ページがロードされた時点で、Exampleセクション (el) が既に表示されているかどうか (:visible) をチェックします。
    • もし表示されていれば(これはURLのハッシュによって直接リンクされた場合に発生します)、setup() 関数を直ちに呼び出してGo Playgroundを初期化します。
    • return; によって、このExampleに対する以降のクリックイベントハンドラの設定をスキップします。これは、既にセットアップが完了しているため、クリックイベントを待つ必要がないからです。
  • クリックイベントハンドラの変更:

    • Exampleが初期表示されていない場合(通常のドキュメント閲覧時)、以前と同様に .toggle 要素がクリックされたときに setup() 関数が呼び出されるようにイベントハンドラが設定されます。
    • if (!built) チェックは、setup() 関数が一度だけ実行されることを保証します。これにより、ユーザーがExampleセクションを複数回クリックしても、Go Playgroundが不必要に再初期化されるのを防ぎます。

これらの変更により、golang.org のExample機能は、直接リンクされた場合でも、ユーザーが手動で展開した場合でも、一貫してGo Playgroundが正しく機能するようになりました。

関連リンク

参考にした情報源リンク