概要
PWAの投稿画面に、URLパラメータ(?text=)からテキストを受け取ってテキストエリアに自動入力する機能を追加した。
これにより、iOSのショートカットアプリなどから共有されたURLやテキストを、投稿画面へ直接連携できるようになった。
背景と目的
スマートフォンでYouTubeなどのアプリから「共有」を選んだとき、URLをコピーして投稿画面に貼り付ける手順が必要だった。 iOSのショートカットアプリを使えば、共有されたテキストをURLパラメータとして投稿画面に渡すことができる。
たとえば以下のようなURLで投稿画面を開くと、テキストエリアに共有テキストが自動で入力される:
https://example.com/admin/timeline/?text=共有されたテキスト
実装内容
クエリパラメータの取得
ブラウザ標準の URLSearchParams を使い、クエリ文字列から text キーの値を安全に取り出す。
URLSearchParams は自動的にURLデコードを行うため、日本語やURLエンコードされた文字列も正しく処理される。
// クエリ文字列を安全に解析する
const urlParams = new URLSearchParams(window.location.search);
// text パラメータの値を取得する
const sharedText = urlParams.get('text');
テキストエリアへの自動入力
取得した値が存在する場合のみ、テキストエリアの value に設定する。
入力後はテキストエリアの高さを内容に合わせて自動調整し、フォーカスを当てる。
// テキストエリアに値を設定する
composeText.value = safeText;
// 高さの自動調整を発火する
composeText.dispatchEvent(new Event('input'));
// すぐに編集できるようにフォーカスする
composeText.focus();
URL履歴のクリーンアップ
テキストを入力した後、history.replaceState でURLからクエリ文字列を削除する。
これにより、ページをリロードしたときに同じテキストが再入力されることを防ぐ。
// URLからクエリ文字列を除去する
window.history.replaceState({}, '', window.location.pathname);
セキュリティ上の考慮事項
入力長の制限
URLパラメータには任意の長さの文字列を渡せるため、1000文字の上限を設けた。 これにより、過大なテキストによるブラウザの負荷やUIの崩れを防止する。
const MAX_TEXT_LENGTH = 1000;
const safeText = sharedText.slice(0, MAX_TEXT_LENGTH);
XSSへの対策
取得した値は textarea の value プロパティに代入するだけであり、innerHTML や document.write は使用していない。
value プロパティへの代入はブラウザが文字列として扱うため、HTMLタグやスクリプトが実行されることはない。
URLSearchParamsの安全性
URLSearchParams はブラウザ標準APIであり、パラメータの解析とURLデコードを安全に行う。
手動で decodeURIComponent を使う場合と異なり、不正なエンコード文字列でも例外が発生しない。
まとめ
URLSearchParams によるパラメータ取得、value プロパティへの代入、history.replaceState によるURL整理という3つの処理を組み合わせた。
既存の投稿処理やUI要素には一切手を加えていないため、既存機能への影響はない。