[インデックス 10460] ファイルの概要
このコミットは、Go言語の標準ライブラリである html/template
パッケージのドキュメンテーションのフォーマットを修正するものです。具体的には、src/pkg/html/template/doc.go
ファイル内のコード例や表のインデントが調整され、godoc
ツールで表示される際の可読性と正確性が向上されています。
コミット
commit 6c864210fc726e2eb27a4ce3ec1ff47f8671378e
Author: Andrew Gerrand <adg@golang.org>
Date: Sat Nov 19 10:54:44 2011 +1100
html/template: fix documentation formatting
See http://weekly.golang.org/pkg/html/template/
R=golang-dev, r, rsc
CC=golang-dev
https://golang.org/cl/5413055
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/6c864210fc726e2eb27a4ce3ec1ff47f8671378e
元コミット内容
html/template: fix documentation formatting
このコミットは、html/template
パッケージのドキュメンテーションのフォーマットを修正することを目的としています。特に、godoc
ツールでドキュメントが正しくレンダリングされるように、インデントの調整が行われました。
変更の背景
Go言語では、ソースコード内のコメント、特にパッケージや関数の説明に書かれたコメントが、godoc
ツールによって自動的にドキュメンテーションとして生成されます。godoc
は、コメント内の特定のフォーマット(例えば、行頭のスペースやタブ)を解釈し、コード例や整形済みテキストとして表示する機能を持っています。
このコミットが行われた背景には、html/template
パッケージの doc.go
ファイルに含まれるコード例や表のインデントが、godoc
の期待するフォーマットと一致していなかったという問題があったと考えられます。インデントが不適切だと、godoc
で生成されるドキュメントにおいて、コードブロックが正しく整形されなかったり、表のレイアウトが崩れたりする可能性があります。
この修正は、ユーザーが html/template
パッケージのドキュメントを godoc
経由で参照した際に、より正確で読みやすい情報を提供することを目的としています。
前提知識の解説
Go言語のドキュメンテーションとgodoc
Go言語では、ソースコード自体がドキュメンテーションの主要な情報源となります。パッケージ、型、関数、変数などの宣言の直前に書かれたコメントは、godoc
というツールによって解析され、HTML形式のドキュメントとして生成されます。
godoc
の特徴は以下の通りです。
- 自動生成: ソースコードから自動的にドキュメントを生成するため、コードとドキュメントの乖離が少ない。
- コメントの解釈: コメント内の特定の書式(例:空行で区切られた段落、行頭のタブやスペースによるコードブロック)を解釈し、整形された出力を行う。
- コード例の表示:
Example
関数として記述されたコードは、自動的にドキュメントに組み込まれ、実行可能な例として表示される。 - クロスリファレンス: パッケージ内の他の要素や、インポートされた他のパッケージへのリンクが自動的に生成される。
特に、コード例や整形済みテキストをコメント内に記述する際には、行頭のインデントが重要になります。godoc
は、行頭にタブまたは複数のスペースがある行をコードブロックとして認識し、等幅フォントで表示します。この認識が正しく行われないと、コードが通常のテキストとして表示されてしまったり、インデントが崩れて読みにくくなったりします。
html/template
パッケージ
html/template
パッケージは、Go言語でHTML出力を生成するためのテンプレートエンジンです。Goには text/template
という汎用的なテンプレートパッケージもありますが、html/template
はそれに加えて、HTML特有のセキュリティ機能を提供します。
主なセキュリティ機能は以下の通りです。
- 自動エスケープ (Auto-escaping): テンプレートに渡されたデータがHTML出力に挿入される際、自動的にエスケープ処理が行われます。これにより、クロスサイトスクリプティング (XSS) などのインジェクション攻撃を防ぎます。例えば、ユーザー入力に
<script>
タグが含まれていても、それが<script>
のようにエスケープされるため、悪意のあるスクリプトが実行されるのを防ぎます。 - コンテキストアウェアネス (Context-awareness): テンプレートエンジンは、データがHTMLドキュメントのどのコンテキスト(例:HTML要素のテキストコンテンツ、属性値、URL、JavaScriptコード)に挿入されるかを認識し、そのコンテキストに応じた適切なエスケープ処理を適用します。これにより、より堅牢なセキュリティが実現されます。
この自動エスケープ機能は、Webアプリケーション開発において非常に重要であり、開発者が手動でエスケープ処理を行う手間を省きつつ、セキュリティリスクを低減します。
技術的詳細
このコミットの技術的詳細は、Go言語のドキュメンテーションツールである godoc
のレンダリング規則に深く関連しています。
godoc
は、Goのソースコード内のコメントを解析し、ドキュメントを生成します。特に、コメントブロック内でコード例や整形済みテキストを表現する場合、行頭のインデントが重要な意味を持ちます。
- コードブロックの認識:
godoc
は、コメント内の行が1つ以上のタブ文字、または連続するスペースでインデントされている場合、その行をコードブロックの一部として認識します。認識されたコードブロックは、通常、等幅フォントで表示され、整形された状態が保たれます。 - インデントの統一: Goの慣習として、コードはタブでインデントされることが推奨されています。ドキュメンテーション内のコード例も、この慣習に従ってタブでインデントされるべきです。このコミットでは、既存のコード例や表のインデントが、
godoc
が正しく解釈し、かつGoのコーディングスタイルに合致するように調整されています。具体的には、スペースによるインデントがタブによるインデントに、またはタブとスペースの組み合わせがより統一されたインデントに修正されています。
この修正は、コードの機能的な変更ではなく、ドキュメンテーションの「見た目」と「正確性」を向上させるためのものです。しかし、適切にフォーマットされたドキュメントは、ライブラリの利用者がコードを理解し、正しく使用するために不可欠であるため、非常に重要な改善と言えます。
コアとなるコードの変更箇所
変更は src/pkg/html/template/doc.go
ファイルのみで行われています。
diff --git a/src/pkg/html/template/doc.go b/src/pkg/html/template/doc.go
index 570567e876..fc0e382644 100644
--- a/src/pkg/html/template/doc.go
+++ b/src/pkg/html/template/doc.go
@@ -13,9 +13,9 @@ Introduction
This package wraps package template so you can use the standard template API
to parse and execute templates.
- set, err := new(template.Set).Parse(...)\n- // Error checking elided\n- err = set.Execute(out, "Foo", data)\n+ set, err := new(template.Set).Parse(...)\n+ // Error checking elided\n+ err = set.Execute(out, "Foo", data)\
If successful, set will now be injection-safe. Otherwise, err is an error
defined in the docs for ErrorCode.
@@ -29,25 +29,25 @@ trusted, while Execute's data parameter is not. More details are provided below.\
Example
- import "text/template"\n- ...\n- t, err := (&template.Set{}).Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)\n- err = t.Execute(out, "T", "<script>alert('you have been pwned')</script>")\n+ import "text/template"\n+ ...\n+ t, err := (&template.Set{}).Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)\n+ err = t.Execute(out, "T", "<script>alert('you have been pwned')</script>")\
produces
- Hello, <script>alert('you have been pwned')</script>!\n+ Hello, <script>alert('you have been pwned')</script>!\
but with contextual autoescaping,
- import "html/template"\n- ...\n- t, err := (&template.Set{}).Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)\n- err = t.Execute(out, "T", "<script>alert('you have been pwned')</script>")\n+ import "html/template"\n+ ...\n+ t, err := (&template.Set{}).Parse(`{{define "T"}}Hello, {{.}}!{{end}}`)\n+ err = t.Execute(out, "T", "<script>alert('you have been pwned')</script>")\
produces safe, escaped HTML output
- Hello, <script>alert('you have been pwned')</script>!\n+ Hello, <script>alert('you have been pwned')</script>!\
Contexts
@@ -80,36 +80,36 @@ Contexts
Assuming {{.}} is `O'Reilly: How are <i>you</i>?`, the table below shows
how {{.}} appears when used in the context to the left.
-Context {{.}} After\n-{{.}} O'Reilly: How are <i>you</i>?\n-<a title='{{.}}'> O'Reilly: How are you?\n-<a href="/{{.}}"> O'Reilly: How are %3ci%3eyou%3c/i%3e?\n-<a href="?q={{.}}"> O'Reilly%3a%20How%20are%3ci%3e...%3f\n-<a onx='f("{{.}}")'> O\x27Reilly: How are \x3ci\x3eyou...?\n-<a onx='f({{.}})'> "O\x27Reilly: How are \x3ci\x3eyou...?"\n-<a onx='pattern = /{{.}}/;'> O\x27Reilly: How are \x3ci\x3eyou...\x3f\n+ Context {{.}} After\n+ {{.}} O'Reilly: How are <i>you</i>?\n+ <a title='{{.}}'> O'Reilly: How are you?\n+ <a href="/{{.}}"> O'Reilly: How are %3ci%3eyou%3c/i%3e?\n+ <a href="?q={{.}}"> O'Reilly%3a%20How%20are%3ci%3e...%3f\n+ <a onx='f("{{.}}")'> O\x27Reilly: How are \x3ci\x3eyou...?\n+ <a onx='f({{.}})'> "O\x27Reilly: How are \x3ci\x3eyou...?"\n+ <a onx='pattern = /{{.}}/;'> O\x27Reilly: How are \x3ci\x3eyou...\x3f\
If used in an unsafe context, then the value might be filtered out:
-Context {{.}} After\n-<a href="{{.}}"> #ZgotmplZ\n+ Context {{.}} After\n+ <a href="{{.}}"> #ZgotmplZ\
since "O'Reilly:" is not an allowed protocol like "http:".
If {{.}} is the innocuous word, `left`, then it can appear more widely,
-Context {{.}} After\n-{{.}} left\n-<a title='{{.}}'> left\n-<a href='{{.}}'> left\n-<a href='/{{.}}'> left\n-<a href='?dir={{.}}'> left\n-<a style="border-{{.}}: 4px"> left\n-<a style="align: {{.}}"> left\n-<a style="background: '{{.}}'> left\n-<a style="background: url('{{.}}')> left\n-<style>p.{{.}} {color:red}</style> left\n+ Context {{.}} After\n+ {{.}} left\n+ <a title='{{.}}'> left\n+ <a href='{{.}}'> left\n+ <a href='/{{.}}'> left\n+ <a href='?dir={{.}}'> left\n+ <a style="border-{{.}}: 4px"> left\n+ <a style="align: {{.}}"> left\n+ <a style="background: '{{.}}'> left\n+ <a style="background: url('{{.}}')> left\n+ <style>p.{{.}} {color:red}</style> left
コアとなるコードの解説
このコミットの変更は、src/pkg/html/template/doc.go
ファイル内のコメントのインデント調整に集約されます。具体的には、行頭のスペースがタブ(またはタブに相当するスペース数)に置き換えられたり、インデントの深さが調整されたりしています。
Go言語のドキュメンテーションツールである godoc
は、コメント内のコード例や整形済みテキストを認識するために、行頭のインデントを重要な手がかりとします。通常、godoc
は行頭にタブ文字がある行をコードブロックとして解釈します。また、Goの標準的なコーディングスタイルでは、インデントにはタブを使用することが推奨されています。
この変更は、以下の目的で行われました。
godoc
での正確なレンダリング: 既存のインデントがgodoc
の期待するフォーマットと完全に一致していなかったため、ドキュメントが正しく整形されて表示されない可能性がありました。この修正により、コード例や表がgodoc
で等幅フォントで表示され、レイアウトが崩れることなく、意図した通りに整形されるようになります。- Goのコーディングスタイルへの準拠: Goコミュニティでは、コードのインデントにタブを使用することが一般的な慣習です。ドキュメンテーション内のコード例もこの慣習に従うことで、一貫性が保たれ、Go開発者にとってより自然な形でドキュメントを読めるようになります。
この修正は、html/template
パッケージの機能的な動作には影響を与えませんが、ドキュメンテーションの品質と可読性を大幅に向上させるものです。これにより、開発者が html/template
パッケージを学習し、使用する際の体験が改善されます。
関連リンク
- Go言語の公式ドキュメンテーション: https://golang.org/pkg/html/template/
- このコミットの変更リスト (Gerrit): https://golang.org/cl/5413055
参考にした情報源リンク
- Go言語のドキュメンテーションの書き方に関する公式ガイドライン: https://go.dev/blog/godoc (特に「Doc comments」セクション)
text/template
とhtml/template
の違いに関する解説: https://go.dev/blog/html-template