入力された<em>確認用</em>を画面へ表示するとき、タグとして実行したいのか、文字として見せたいのかを分けます。利用者が入れた文章をそのままHTMLへ連結すると、意図しない要素をページへ追加する可能性があります。
GASのHTMLテンプレートで文字を出す場合は、通常の出力タグ<?= ... ?>を使います。文脈に応じたエスケープが働き、文字をHTMLの一部として解釈させないための処理が入ります。以下は段落の中へ文章を表示する、狭い用途の例です。
通常の出力と強制出力の違い
公式のHTMLテンプレート資料は、<?= ... ?>をエスケープ付きの出力、<?!= ... ?>をエスケープしない出力として説明しています。表示がうまくいかないときに、記号を1つ足して強制出力へ変えると、扱う内容が変わります。
HTMLとして書いた自分の固定のタグと、利用者から来た文章を同じ扱いにしないことが大切です。今回のmessageは文章として表示する値なので、強制出力へ渡しません。
また、エスケープは「どのURLへ移動しても安全」という判断ではありません。入力値をリンク先やスクリプトの処理へ使う場合は、許可する値の検査も別に必要です。ここではHTMLの本文の段落だけに使います。
Code.gsで変数を渡す
練習用のApps ScriptプロジェクトにCode.gsとIndex.htmlを作ります。URLのmessageが文字列なら受け取り、それ以外は確認用の文章を使います。
function doGet(e) {
const value = e && e.parameter && e.parameter.message;
const message = typeof value === 'string' ? value : '確認用の文章';
const template = HtmlService.createTemplateFromFile('Index');
template.message = message;
return template.evaluate();
}
createHtmlOutputFromFileでそのまま読む場合と違い、テンプレートを作ってevaluateしています。変数名messageは次のHTML側でも同じ名前にします。値をJavaScriptで事前にHTML化して渡す処理は入れません。
Index.htmlの段落へ表示する
HTML側はmessageを段落の文字として出します。文字が入る場所を固定し、タグ名や属性名そのものを利用者の入力から作らない例です。
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<base target="_top">
<title>文字列の確認</title>
</head>
<body>
<p><?= message ?></p>
</body>
</html>
Webアプリのテスト用URLで、messageに<em>確認用</em>を指定した場合、その文字列が段落へ見えることを確認します。斜体のタグとして扱われる状態と、山括弧を含む文章として見える状態を区別してください。URLのパラメータへ入れる際は、記号を適切にURLエンコードします。
ページを開いた後の更新
テンプレート内の処理はページを返す前に実行されます。画面を開いた後で、同じ変数へ値を入れれば自動で段落が変わる仕組みではありません。表示の更新が必要なら、画面側の処理を別に作ります。
画面側で文章を入れる場合も、単なる文字ならtextContentを使う方法があります。入力をinnerHTMLへ渡すと、文字列をHTMLとして解析する別の操作になります。画面との通信はHTML Serviceのサイドバーから確認できます。
公開範囲と確認した範囲
URLのパラメータは履歴や共有したURLに残るため、個人情報を使うテストはしません。公開範囲と実行する利用者の設定も、文章のエスケープとは別に確認します。GASのWebアプリ化の設定を先に点検してください。
ローカルでは代用HtmlServiceで、ファイル名、messageの受け渡し、既定値、evaluateの呼び出しを確認し、掲載HTMLの出力タグも照合しました。Googleのテンプレートエンジンや実ブラウザでの表示は未実行です。エスケープの動作は公式資料を根拠にした説明で、代用テストだけで全画面の安全性を確認したという意味ではありません。
