downloads a hyperlink

downloads a hyperlink

[6] ハイパーリンクは、たどる (follow) ことによってリンク先navigate させたり、ダウンロードすることによってリンク先を保存したりできます。

仕様書

リンク元の表示

[75] a 要素は通常の CSS の規則に従い、 area 要素画像写像の処理規則に従い、 文書の一部として表示されます。

[76] link 要素は標準状態では表示されませんが、 通常の CSS の規則に従い、著者の指定によって表示させることができます。

利用者による指示

[77] 利用者エージェントは、活性化動作 (>>32) としてこれらのリンク元からハイパーリンクをたどる、 あるいはハイパーリンクのダウンロードを実行する手段を利用者に提供することになっています。

[73] 加えて、利用者エージェントは、 link 要素で作成されたハイパーリンクについて、 利用者ハイパーリンクをたどることを指示する方法を提供できます >>72

具体的な表示方法や指示方法は規定されていません。また提供の義務はありません。 link も参照。
[74] ハイパーリンクのダウンロードの手段の提供の可否には HTML Standard は言及していませんが、意図的なのかどうかは不明です。

[79] クリック等による活性化動作の他に、 文脈メニューからの動作の選択や、 他の閲覧文脈へのリンクドラッグダウンロードマネージャーや他のアプリケーションへのリンクドラッグなどでもハイパーリンクをたどる処理やハイパーリンクのダウンロードの処理を起動する必要がありそうですが、 それに関する明文規定は今のところなさそうです。 (流石にこれらがすべてクリックの特殊形で活性化動作としてカバーされるとみなすのは無理がありそうです。 しかしいずれも活性化動作と同じ挙動でうまく処理できそうです。)

[114] いずれにせよ、利用者エージェントは、リンクに関する一連の処理に対して、 次のような情報を保持したオブジェクトイベントを (内部的に) 用意して引き渡すことになります。

[140] 利用者エージェントから利用者に提示する選択肢には、普通何らかの制限があります。

[141] 例えば多くのデスクトッププラットフォーム視覚的利用者エージェントハイパーリンクDnDハイパーリンクをたどるために使う閲覧文脈を選択できますが、 入れ子閲覧文脈補助閲覧文脈への DnD は禁止するのが好ましそうです。

[142] javascript: URLハイパーリンク著者の指定以外の閲覧文脈で処理するのは好ましくなさそうです。

[145] ChromeDnD を制限していないようですが...

閲覧文脈の選択, 閲覧文脈の作成

利用者への事前情報の提示

[27] 普通、Webブラウザーは、実際に利用者ハイパーリンクをたどる前に、 (:hover:focus となった時点で) リンク先URL (>>47) を利用者へのヒントとして提示します。

[28] かつてはステータスバーに示すのが一般的でしたが、 ステータスバーが使われなくなってからは、 一時的にステータスバーの位置に表示する形態が普通となりました。

[31] tooltip として表示する実装もありました。

[29] 利用者エージェントによっては、 URL 全体ではなく、 一部を省略して表示することがあります。

[30] Firefoxハイパーリンク接尾辞も含めて表示しますが、 Chrome は含めずに表示します。

[37] ping 属性がある場合はその旨も併記するべき >>34 とされていますが、現行の利用者エージェントでそのように実装しているものはなさそうです。

ping も参照。

リンク先URL

[47] 要素要素イベントイベントのリンク先のURLは、 次のように決定したものです >>5, >>40

  1. [48] href を、要素href 属性値に設定します。
  2. [15] URL を、要素節点文書相対hrefURLの構文解析を適用した結果に設定します。
  3. [46] URL失敗でなければ、
    1. [23] URL の末尾に、要素イベントに関するハイパーリンク接尾辞 (>>52) を追加します。
  4. [50] URL を返します。

[51] つまり、 href 属性の値を文書基底URL に対して解決した結果がリンク先の URL となります。

[52] ただし ismap (サーバー側画像写像) を使っている時は、 その末尾に座標を付加した値となります。これが「ハイパーリンク接尾辞」です。 要素の「ハイパーリンク接尾辞」は、 イベントイベントについて、次のように決定したものです。

  1. [100]
    ... のすべてを満たすなら、 >>92
    1. [49] イベントが実際に指示装置から発せられたものなら、
      1. [105] x を、イベント対象左辺から指示位置までのCSS画素単位の距離に設定します。
      2. [110] xなら、x を、 0 に設定します。
      3. [106] y を、イベント対象上辺から指示位置までのCSS画素単位の距離に設定します。
      4. [111] yなら、y を、 0 に設定します。
    2. [107] それ以外なら、
      1. [108] x を、 0 に設定します。
      2. [109] y を、 0 に設定します。
    3. [112] ?x,y を連結した結果を返します。 xy は、それぞれASCII数字十進数で表したものとします。
  2. [104] それ以外の場合、空文字列を返します。

[99] ここで、イベントは、活性化動作によってハイパーリンクをたどる場合には、 その click イベントです >>92利用者インターフェイスへの表示の場合は、 mousemove など適当なイベントです。

[113] 画像の実際のサイズではなく、表示上のサイズから座標が決まります。

[115] 座標の値は、最短の十進数表記とするべきと思われますが、なぜか明記されていません。

[24] URL素片識別子が含まれる場合、ハイパーリンク接尾辞はその後に追加されるので、 サーバーには送信されないことになります。おかしな動作ですが、 HTML StandardChromeFirefox とも共通しています。

活性化動作

[32] a, area, link要素活性化動作として、ハイパーリンクの処理が規定されています。

[33] SVGa 要素や、かつて実装されていた頃の XLink 単純リンクもほぼ同様に処理されるべきものと思われますが、明文規定はありません。

[84] 要素要素活性化動作は、 イベントについて、 次のようにしなければなりません

  1. [148] 要素navigateできない場合、
    1. [149] ここで停止します。
  2. [93] 動作を、要素イベントから判断した動作 (>>38) に設定します。
  3. [94] 動作が「たどる」なら、
    1. [91] 要素についてハイパーリンクをたどる処理を実行します >>72, >>92, >>98イベントを引き渡します。
  4. [95] 動作が「ダウンロード」なら、
    1. [96] 要素についてハイパーリンクをダウンロードします >>92, >>98イベントを引き渡します。

[150] 要素navigateできない (cannot navigate) とは、 つぎのいずれかであることをいいます HTML Standard

[89] 後方互換性のため、 a 要素のみ特例が設けられています。
[90] ハイパーリンクをたどる操作の他に、フォームの提出からも参照されます。

[38] 要素イベントからハイパーリンクを 「たどる」か「ダウンロード」かを、次のようにして決定します。

  1. [83] 要素link 要素なら、「たどる」を返し、ここで停止します >>72
  2. [81] イベント利用者がどちらかを示している時は、それを返し、ここで停止します >>80
  3. [85] 要素download 属性があれば、
    1. [86] 「ダウンロード」を返すべきです >>80
  4. [87] 「たどる」を返すべきです >>80

[88] 利用者の指示は、文脈メニューから「開く」と「ダウンロード」 のいずれかを選ぶ形で行われるかもしれませんし、 操作時点の CtrlShift などの押下状態によって決められるかもしれません。 どのように指示させるか (そもそも指示の手段を提供するか) は、 利用者エージェントに委ねられています。 MUST でなく SHOULD となっているのも、 利用者エージェントの個別の事情に関する事項だからと思われます。

[82] link 要素については、なぜか「たどる」 しか選択肢が用意されていません。
[39] 「たどる」が選ばれたとしても、 navigate が最終的にダウンロードとなることもあります。 navigate 参照。
[126] HTML Standard活性化動作でのポップアップ検査 (>>59, >>122) と実際の動作 (>>93) とで「たどる」と「ダウンロード」との分岐条件がなぜか微妙に違っているのですが、 どちらも同条件で分岐するべきと思われます。 更にエラーとする条件が要素target 属性があるかどうかとされていますが、それ以外 (<base target> がある場合) も同じようにエラーとするべきように思われます。

[131] 要素の提案ファイル名は、次のようにして決定した値です >>40

  1. [132] 要素link 要素なら、
    1. [133] null を返します。
  2. [134] それ以外なら、
    1. [135] ファイル名を、 要素download 属性値に設定します。
    2. [136] ファイル名空文字列なら、
      1. [137] null を返します。
    3. [138] それ以外なら、
      1. [139] ファイル名を返します。

[163] 超漢字の標準のWebブラウザーBBBは、 ハイパーリンククリックで辿る動作 (既定値) の他に、 ダブルクリックで辿るオプションを提供していました。 これは「仮身をウィンドウに開く動作」に合わせたものでした。 >>162

[164] 超漢字BTRON文書形式である TAD は一種のハイパーテキストで、 仮身はそれに於いてハイパーリンクに近い概念でした。
[165] 逆パターンですが、 IE4 の統合以後の Windows エクスプローラアイコンダブルクリックで開くかわりにクリックで開くオプションを提供したのと似ています。

ハイパーリンクをたどる

[7] 要素イベントについてハイパーリンクをたどる (follow a hyperlink) >>5 操作は、ハイパーリンクで指定された URL へと navigate するものです。多くのハイパーリンクの標準の操作は、 この「ハイパーリンクをたどる」操作となっています。

[41] 次のようにしなければなりません >>5

  1. [9] 始点を、要素節点文書閲覧文脈に設定します。
  2. [14] noopener を、 要素リンク型群noreferrer または noopener が含まれているか否かに設定します。
  3. [10] 対象置換有効利用者閲覧文脈を明示したを、 閲覧文脈の選択の結果に設定します。
    要素
    要素
    利用者指示
    イベント
    noopener
    noopener
  4. [59] 対象が何も選ばれなかった場合、
    1. [61] 入口設定群オブジェクトがあれば、
      1. [97] InvalidAccessError 例外投げます。 >>92, >>98
    2. [121] ここで停止します。 >>92, >>98
  5. [11] 置換有効で、 noopenerの場合、
    1. [13] 対象opener閲覧文脈disown します。
  6. [53] URL を、要素イベントにおけるリンク先のURL (>>47) に設定します。
  7. [16] URL失敗なら、
    1. [42] 失敗を報告します (>>18)。
  8. [17] それ以外なら、
    1. [25] タスクタスクキューに追加します。
      タスク
      処理
      1. [26] navigate します。
        新しい資源
        要求
        [157] 要求
        URL
        URL
        参照元
        要素リンク型群noreferrer が含まれれば no-referrer。それ以外なら client
        参照元ポリシー
        要素referrerpolicy 属性の状態
        navigate する閲覧文脈
        対象
        始点閲覧文脈
        始点
        置換有効
        置換有効
        新しい最上位閲覧文脈
        置換有効
        提案ファイル名
        要素の提案ファイル名 (>>131)
        利用者閲覧文脈を明示した
        利用者閲覧文脈を明示した
      タスク源
      DOM操作タスク源
    2. [54] 要素URLについて ping 属性の処理 (>>55) を実行します。

ハイパーリンクをダウンロード

[60] 要素イベントハイパーリンクをダウンロード (download a hyperlink) >>40 する操作は、ハイパーリンクで指定された URL についてダウンロードを実行するものです。

[62] 次のようにしなければなりません >>40

  1. [63] URL を、要素イベントにおけるリンク先のURL (>>47) に設定します。
  2. [64] URL失敗なら、
    1. [65] 失敗を報告します (>>18)。
  3. [66] それ以外なら、
    1. [68] 並列に
      1. [69] 要求fetch します。続きの処理は、ダウンロードとします。
        要求
        URL
        URL
        クライアント
        入口設定群オブジェクト
        initiator
        download
        終点
        空文字列
        Originヘッダー省略フラグ
        同期フラグ
        URL credentials利用フラグ
        参照元
        要素リンク型群noreferrer が含まれれば no-referrer。 それ以外なら client仕様書に明記なし
        参照元ポリシー
        要素referrerpolicy 属性の状態 仕様書に明記なし
        イベントを引き渡します。 提案ファイル名は、要素の提案ファイル名 (>>131) とします。
      2. [67] 要素URLについて ping 属性の処理 (>>55) を実行します。

[78] javascript: へのリンクなど、navigate ではうまく処理されても、 ダウンロードでは処理できない場合もあります。

[128] ダウンロードの処理で使う起源は、 要素節点文書起源と思われます。

[129] ダウンロードの処理は、イベントの情報の一部も参照することがあります。

失敗の報告

[18] ハイパーリンクをたどる、またはハイパーリンクをダウンロードする時に URLの解決で失敗したら、利用者エージェントは次のいずれかの動作を選べます >>5, >>40

[43] HTML Standard は、エラーページへの navigate (>>22) について、 ハイパーリンクをたどる際には新しいタスクハイパーリンクをダウンロードする際には同じタスクで実行しています。 この違いが意図的なものなのかどうかは不明です。
[45] 対象は、ハイパーリンクをたどる場合には、その過程で選択した閲覧文脈です。 ハイパーリンクのダウンロードの場合は、 (HTML Standard にはなぜか明記されていませんが) リンクが含まれる閲覧文脈とするのが適当そうです。

[44] 利用者の便宜や navigate の途中でのエラーとの動作の整合性を考慮すると、 ハイパーリンクをたどる場合にはエラーページに navigate して、 ハイパーリンクのダウンロードの場合には非モーダルダイアログなどでエラーを通知するのが良さそうに思えます。

[127] まったく何もしないのは、利用者を混乱させそうです。

ping 属性の処理

[56] ping も参照。

[55] ping 属性の処理とは、次のようにすることをいいます。

  1. [35] 要素a 要素または area 要素で、 ping 属性を持つなら、
    1. [36] ping 属性の処理を実行します。 >>34

[58] link 要素には、 ping 属性はありません。
[57] HTML Standardハイパーリンクをたどる処理の時にこれを行うことを求めていますが、 ハイパーリンクのダウンロードにはなぜか言及されていません。 Chrome は、ハイパーリンクのダウンロードでも ping の処理を行っているようです。

歴史

[1] Integrate Fetch into HTML · whatwg/html@7c5555a ( 版) https://github.com/whatwg/html/commit/7c5555a16f2920c02244c10756bb2f1a11e87a22

[2] Clarify the following/downloading hyperlink algorithms · whatwg/html@47e4aa0 ( 版) https://github.com/whatwg/html/commit/47e4aa05825df966848ca2c7773794576a130b88

[3] Add a 'noopener' <link rel> keyword and window feature · whatwg/html@2992ea9 ( 版) https://github.com/whatwg/html/commit/2992ea921bc75e44157451a37a807a8ce0b9a884

[4] Editorial: clarify follow a hyperlink algorithm · whatwg/html@d22a9f1 ( 版) https://github.com/whatwg/html/commit/d22a9f12e1cc13a77504fa6482b7ded6ba790b54

[70] Chrome では、ハイパーリンクをたどる場合、 pingハイパーリンクをたどる実行後に発生した fetchhref の順で fetch が行われます。 ハイパーリンクのダウンロードの場合、 hrefpingハイパーリンクのダウンロード実行後に発生した fetch の順で fetch が行われます。

[71] HTML Standard では ping をどの時点で fetch するべきなのか明確になっていません。

[144] Integrate referrerpolicy for a, area, iframe, and link elements (estark37著, ) https://github.com/whatwg/html/commit/2e955e66ae7f815efe09ccac6445cfbdcbf643ab

[146] Allow <a>/<area> with download="" to not require user activation (domenic著, ) https://github.com/whatwg/html/commit/5de03c7b38e7b33a49f0dcf2bcef29e8eb9a2205

[122] Revert part of "Allow <a>/<area> with download="" to not require user… (zcorpan著, ) https://github.com/whatwg/html/commit/b359209579d79a713af88ecf24b9be8fb6168adf

[8] Revamp the rules for choosing a browsing context (annevk著, ) https://github.com/whatwg/html/commit/5578a0495f826a56597288b7ba1f71163f17cdd6

[12] Make noopener stop the copying of session storage (mystor著, ) https://github.com/whatwg/html/commit/a68a1f712b641981d7367d78758596b21a04521c

[123] Editorial: centralize target attribute processing (annevk著, ) https://github.com/whatwg/html/commit/0b31844d6dcc7ef49b3815f4f709d4c0284378f1

[124] Deduplicate finding the correct target attribute · Issue #2619 · whatwg/html () https://github.com/whatwg/html/issues/2619

[125] Editorial: centralize target attribute processing by annevk · Pull Request #3007 · whatwg/html () https://github.com/whatwg/html/pull/3007

[147] Centralize checks for <a>, <area>, <form>, and <link> (annevk著, ) https://github.com/whatwg/html/commit/f3c354add894e1ac01e3732ff976aa9874a77b3f

[153] <a>, <area>, <link>, and <form> behavior · Issue #2615 · whatwg/html () https://github.com/whatwg/html/issues/2615

[154] Centralize checks for <a>, <area>, <form>, and <link> by annevk · Pull Request #2613 · whatwg/html () https://github.com/whatwg/html/pull/2613

[155] Editorial: "return, but continue" cleanup for downloads and Worker (annevk著, ) https://github.com/whatwg/html/commit/0217e1d4cb1ace836f6ef72a402b643aa879fbed

[156] Editorial: "return, but continue" cleanup for downloads and Worker by annevk · Pull Request #3397 · whatwg/html () https://github.com/whatwg/html/pull/3397

[158] Editorial: inline noreferrer processing model (annevk著, ) https://github.com/whatwg/html/commit/f47773d25a7b1a3a03c1047bbc4037d08639cf9b

[159] Support "noreferrer" for window.open() by annevk · Pull Request #4331 · whatwg/html () https://github.com/whatwg/html/pull/4331

[160] Make "triggered by user activation" match browser behavior · Issue #1903 · whatwg/html () https://github.com/whatwg/html/issues/1903

[161] Chrome は機嫌が悪いと(?) <a download> を普通にクリックしてるだけなのにダウンロードがブロックされました、 ってなっちゃうことあるんだよなあ、どうなってんだか。