1. はじめに
この節は非規範的です。
Custom Highlight API は、ハイライト疑似要素の概念(CSS 疑似要素 4 § 3 ハイライト疑似要素を参照)を拡張し、 ユーザーエージェントが定義する ::selection、::inactive-selection、 ::spelling-error、 および '::grammar-error' に限定されるのではなく、 Web 開発者が任意の Range オブジェクトのテキストをスタイル設定する方法を提供します。 これはさまざまなシナリオで有用であり、 独自の選択を実装したい編集フレームワーク、 仮想化された文書に対するページ内検索、 オンライン共同作業を表現するための複数選択、 スペルチェックフレームワークなどが含まれます。
Custom Highlight API は、基盤となる DOM 構造に影響を与えないハイライトを プログラムによって追加および削除する方法を提供し、 代わりに range オブジェクトに基づいてテキストにスタイルを適用します。 これらには ::highlight() 疑似要素を介してアクセスします。
One twoに黄色の背景色と青色の前景色を適用します。 これは、
Highlight を
HighlightRegistry
に追加することで行います
(これらはいずれも、この仕様で導入される新しい概念です)。
Highlight
には、境界点がテキスト One twoを囲む
Range
が含まれます。
< style > : root :: highlight ( example-highlight ) { background-color : yellow ; color : blue ; } </ style > < body >< span > One</ span >< span > two</ span >< span > three…</ span > < script > let r= new Range(); r. setStart( document. body, 0 ); r. setEnd( document. body, 2 ); CSS. highlights. set( "example-highlight" , new Highlight( r)); </ script >
結果は次のようになります。
2. モジュール間の相互作用
このモジュールは Infra Standard [INFRA] および WebIDL [WebIDL] に依存します。
この仕様では、CSS および DOM Standard [DOM] に関する一般的な知識があることを前提とし、 特に CSS Pseudo-Elements Module Level 4 [css-pseudo-4] で定義された、ハイライト疑似要素を扱うための仕組みを拡張します。 Selectors Level 4 [selectors-4] 仕様では、 疑似要素が一般にどのように機能するかを定義しています。
依存関係の完全な一覧については、参考文献を参照してください。
注: この草案は初期バージョンです。 成熟するにつれて、CSS-WG はこれを独立したモジュールとして維持するか、 [css-pseudo-4]、 またはそのモジュールの後のバージョンに統合することを選択する可能性があります。
3. カスタムハイライトのセットアップ
3.1. カスタムハイライトの作成
カスタムハイライトとは、 文書の一部を表す range の集合です。 これらは必ずしも要素ツリーに収まるとは限らず、 その入れ子構造に従うことなく任意に要素境界を横断できます。 これらは文書の該当部分の外観に影響を与えるために使用したり (§ 4 カスタムハイライトのスタイル設定を参照)、 それらに関連付けられたイベントを処理するために使用したりできます (§ 6 イベント処理を参照)。
カスタムハイライトは、
Highlight オブジェクト、すなわち setlike
オブジェクトによって表現され、その set entry は AbstractRange
オブジェクトです。Range は、コンストラクターに渡すか、
setlike オブジェクトの通常の API を使用して
その set entry を操作することにより、カスタム
ハイライトに追加できます。
注: range は カスタムハイライト内では
AbstractRange
オブジェクトであるため、
作者は Range
オブジェクトと StaticRange
オブジェクトのどちらを使用するか選択できます。
この選択とその影響の詳細については、§ 5.2 Range の更新と無効化を参照してください。
enum {HighlightType ,"highlight" ,"spelling-error" }; ["grammar-error" Exposed =Window ]interface Highlight {constructor (AbstractRange ...);initialRanges setlike <AbstractRange >;attribute long ;priority attribute HighlightType ; };type
priority
属性の詳細については、§ 4.2.5 重なり合うハイライトの優先度を参照してください。
type
属性の詳細については、§ 4.2.6 ハイライトの種類を参照してください。
Highlight(AbstractRange... initialRanges) コンストラクターが
呼び出されたとき、
次の手順を実行します。
- highlight を新しい
Highlightオブジェクトとします。 - highlight の
priorityを0に設定します。 - highlight の
typeをhighlightに設定します。 -
initialRangesの各 range について、 range を ECMAScript 値に変換した結果を rangeArg とし、 次に組み込み setlike add 関数の手順を、 highlight をthis値として、 rangeArg を引数として実行します。 - highlight を返します。
3.2. カスタムハイライトの登録
何らかの効果を持たせるためには、カスタムハイライトを登録してハイライトレジストリに入れる必要があります。
ハイライト
レジストリには、highlights
属性を介して CSS
名前空間からアクセスし、
現在のグローバルオブジェクトの関連付けられた Documentに対して登録されたすべてのカスタムハイライトを表します。
これは maplike であり、通常のメソッドを使用して更新できます。
その map entry は初期状態では空です。
カスタムハイライトが ハイライト レジストリ内にある場合、それは登録済みであるといいます。 後で削除された場合、登録済みではなくなります。
partial namespace CSS {readonly attribute HighlightRegistry ; }; [highlights Exposed =Window ]interface {HighlightRegistry maplike <DOMString ,Highlight >; };
set メソッドを呼び出します。これにより組み込み maplike set
関数の手順が、
コンテキストオブジェクトを this 値として、
渡されたカスタムハイライト名を
keyArg として、
渡されたハイライトを valueArg として実行されます。
カスタムハイライトが登録されるときに割り当てられるカスタム ハイライト名は、スタイル設定時にハイライトを識別するために使用されます (§ 4 カスタムハイライトのスタイル設定を参照)。
注: カスタムハイライトを登録するとき、 作者には、有効な CSS 識別子であるカスタムハイライト名を使用することが推奨されます。 有効な識別子ではない名前を使用すると、CSS を介したハイライトのスタイル設定が困難になり、 場合によっては不可能になることがあります。
注: カスタムハイライトを複数のカスタムハイライト名で登録することは可能です。 ただし、ハイライトのスタイル設定に複数の名前を使用すると、 ハイライトには複数の異なるスタイルセットが割り当てられ、 ペイント中に、それらのセット内で競合するスタイルの重なり順を制御する方法はありません。 これは作者にとって制約となり、分かりにくいペイント動作を引き起こす可能性があります (詳細な文脈については、以下の例を参照してください)。 したがって、作者には、スタイル設定時にハイライトごとに1つの名前だけを使用することが推奨されます。
< style > div :: highlight ( bar ) { color : red ; } div :: highlight ( foo ) { color : green ; } </ style > < body >< div > abc</ div > < script > let div= document. body. firstChild; let r= new Range(); r. setStart( div, 0 ); r. setEnd( div, 1 ); let h= new Highlight( r); CSS. highlights. set( 'foo' , h); CSS. highlights. set( 'bar' , h); </ script >
上記の例では、
同じカスタム
ハイライトオブジェクトが、foo および bar という名前で登録されています。
各スタイル規則は同じハイライトを対象とし、同じ詳細度を持つため、
作者はカスケード順で最後の規則が優先され、
ハイライトされた内容が緑色になることを期待するかもしれません。
しかし、各ハイライト名には独立したハイライトスタイルのセットがあり、
ハイライトは名前ごとに一度ペイントされます。
この場合、foo が bar より先に登録されたため、
ハイライトはまず foo の色(緑)でペイントされ、
次に bar の色(赤)でペイントされます。
その結果、ハイライトされた内容は赤色で表示されます。
4. カスタムハイライトのスタイル設定
4.1. カスタムハイライト疑似要素: ::highlight()
::highlight(<custom-highlight-name>) 疑似要素 (カスタムハイライト疑似要素とも呼ばれます)は、 包含されている、または部分的に 包含されている文書の部分を表します。これは、カスタムハイライト名 <custom-highlight-name> を持つ、存在する場合の登録済みのカスタムハイライトのすべてのrangeに対するものです。 <custom-highlight-name> は、有効な CSS <ident-token> でなければなりません。
4.2. 処理モデル
4.2.1. 適用可能なプロパティ
カスタムハイライト疑似要素は、 組み込みのハイライト疑似要素と同様に、 限られたプロパティのセットでのみスタイル設定できます。 完全な一覧については、CSS 疑似要素 4 § 3.2 ハイライトのスタイル設定を参照してください。
4.2.2. デフォルトスタイル
UA は、デフォルトの UA スタイルシートでカスタムハイライト疑似要素に対するスタイルを定義してはなりません。 カスタムハイライト疑似要素は、 その生成元要素のスタイルを継承します。
4.2.3. カスケードと継承
カスケードと継承について、 カスタムハイライト疑似要素は、 CSS 疑似要素 4 § 3.5 カスケードと要素ごとのハイライトスタイルで定義されるとおり、 組み込みのハイライト疑似要素と同一に処理されます。
4.2.4. ペイント
カスタム ハイライトのペイントも、 CSS 疑似要素 4 § 3.4 ハイライトの領域およびCSS 疑似要素 4 § 3.6 ハイライトのペイントで規定されるとおり、 組み込みのハイライト疑似要素と同一に処理されますが、 次の点を明確化します。
- 折り畳まれたrangeは レンダリングされません。
-
単一のカスタムハイライト内で
重なり合うrangeは、
重なり合う range の和集合を表す単一の range が
指定されたかのようにレンダリングされます。
次の例は、半透明の青い背景を持つ単一の ハイライトとしてレンダリングされ、 互いを透かして見ることのできる2つの重なり合うハイライトとしてはレンダリングされません。
< style > :: highlight ( sample ) { background-color : rgba( 0 , 0 , 255 , 0.3 ); } </ style > < body > Lorem Ipsum.< script > let textNode= document. body. firstChild; let r1= new Range(); r1. setStart( textNode, 1 ); r1. setEnd( textNode, 5 ); let r2= new Range(); r2. setStart( textNode, 3 ); r2. setEnd( textNode, 7 ); CSS. highlights. set( "sample" , new Highlight( r1, r2)); </ script > 言い換えると、次のレンダリングは正しいものです。
Lorem Ipsum.しかし、次のものは正しくありません。
Lorem Ipsum. - カスタムハイライトの ハイライトオーバーレイは、 CSS 疑似要素 4 § 3.6 ハイライトのペイントで説明される重なり順において、 組み込みのハイライト疑似要素のものより下に配置されます。
- 複数のカスタムハイライトのハイライトオーバーレイ間の相対的な重なり順は、 それらの優先度によって定義されます(§ 4.2.5 重なり合うハイライトの優先度を参照)。
4.2.5. 重なり合うハイライトの優先度
カスタムハイライトの
priority
属性は、
その優先度を定義します。
これは、ペイント処理中に対応するハイライトオーバーレイの重なり順を決定するために使用されます(§ 4.2.4
ペイントを参照)。
優先度が高いほど、
重なり順で上になります。
カスタムハイライトの priority
属性が明示的に設定されていない場合、
デフォルトの数値優先度は 0 になります。
2つ以上のカスタム ハイライトが同じ数値優先度を持つ場合、 最も最近登録されたものが より高い実効優先度を持ちます。
< style > : root :: highlight ( foo ) { color : blue ; background-color : yellow ; } : root :: highlight ( bar ) { background-color : orange ; } </ style > < body > Some text< script > let textNode= document. body. firstChild; let r1= new Range(); r1. setStart( textNode, 0 ); r1. setEnd( textNode, 6 ); let r2= new Range(); r2. setStart( textNode, 3 ); r2. setEnd( textNode, 9 ); let h1= new Highlight( r1); let h2= new Highlight( r2); CSS. highlights. set( "foo" , h1); CSS. highlights. set( "bar" , h2); </ script >
優先度が設定されていないため
(すなわち、h1 と h2 が同順位であるため)、
カスタムハイライトのスタイルは、ハイライトレジストリへの挿入順で重ねられます。
レンダリング結果では、"Som" は黄色の背景に青いテキスト、
"e t" はオレンジ色の背景に青いテキスト、
"ext" はオレンジ色の背景にデフォルトの色になります。
h1
と設定すると、h1 は h2 より上に重なるようになり、
その結果、"Some t" は黄色の背景に青色、
"ext" はオレンジ色の背景にデフォルトの色になります。
4.2.6. ハイライトの種類
カスタムハイライトの
type
属性は、ハイライトの意味論的な意味を指定するために作者によって使用されます。
これにより、支援技術はハイライトをユーザーに提示するときに
この意味を含めることができます。
カスタムハイライトの type
属性が明示的に設定されていない場合、
デフォルトの type は highlight
になります。
注: 作者には、カスタムハイライトの type
を spelling-error
に設定することが推奨されます。その カスタムハイライトが
スペルミスのある内容を強調するために使用される場合です。
作者には、カスタムハイライトの type
を grammar-error
に設定することが推奨されます。その カスタムハイライトが
文法的に正しくない内容を強調するために使用される場合です。
その他のすべてのユースケースでは、type
は highlight
のままにしておくのが最適です。
UA は、カスタム
ハイライトを支援技術から利用できるようにするべきです。
特定のプラットフォームアクセシビリティ API を使用してハイライトを公開するとき、
UA は、その type
属性で指定されるハイライトの意味論的な意味を、
そのアクセシビリティ API で可能な限り具体的に公開するべきです。
注: たとえば、
プラットフォームアクセシビリティ API がスペルミスと文法エラーを
それぞれ具体的に表現する能力を持つ場合、
UA はこれらの能力を使用して、spelling-error
および spelling-error
を持つハイライトの意味を伝えることが期待されます。
アクセシビリティ API がスペルミスを表現する能力だけを持つ場合、
UA は spelling-error
を持つハイライトと grammar-error
を持つハイライトの両方を、スペルミスの意味論を使用して伝えることが期待されます。
アクセシビリティ API がスペルミスも文法エラーも表現することをサポートしていない場合、
UA は実際の type
にかかわらず、すべてのハイライトを汎用的な highlight
として公開します。
注: この初期の種類のセットは、
Highlight API の一般的なユースケースになることが予想され、
現在のプラットフォームアクセシビリティ API に、その意味論を表現するための既存のサポートがある程度存在するため選択されました。
現在、アクセシビリティ API には、
Highlight API のその他の想定されるユースケースの具体的な意味論を表現する方法がありません。
アクセシビリティ API が Highlight API の追加の一般的なユースケースを表現するためのサポートを得るにつれて、
より多くの種類が後から HighlightType
に追加される可能性があります。
5. 変更への対応
5.1. 再ペイント
ハイライトレジストリ内のカスタム ハイライト、 または登録済みのカスタム ハイライト内のrangeの追加または削除は、 ユーザーエージェントにレンダリングを再評価させ、 適切な場合には再ペイントさせなければなりません。
ユーザーエージェントはまた、
作者による priority
の変更、
または登録済みのカスタムハイライトの
Rangeの
境界点の変更に応じて、
必要に応じてハイライトを再ペイントしなければなりません。
この再評価の タイミング(および同期性)はどのように規定するべきでしょうか? [Issue #4596]
5.2. Range の更新と無効化
作者は、Range
または StaticRange
のどちらかを使用してカスタム
ハイライトを構築できます。
結果として得られるカスタム ハイライトは文書の同じ部分を表し、 同一の方法でスタイル設定できます。 ただし、基盤となる文書が変更された場合の動作は異なります。
Rangeは
live rangeです。
ユーザーエージェントは、range と重なる、またはその境界における DOM の変更に応じて、
Rangeの
境界
点を調整し、
それに応じて再ペイントします。live rangeの境界
点は、作者によって変更することもできます。
一方、
ユーザーエージェントは DOM の変更に応じて StaticRangeの境界
点を調整してはならず、
作成後に作者がそれらを変更することもできません。
ユーザーエージェントは、live Rangeで
バックアップするのではなく、
実際の StaticRangeを
保存することが期待されます。
Range
オブジェクトを更新することには、
大きなパフォーマンスコストがあります。
DOM の変更を監視し、それに反応してカスタムハイライト内の range を調整または再作成する予定の作者には、
この高コストでありながら不要な手順を回避するため、StaticRangeを
使用することが強く推奨されます。
逆に、StaticRangeを使用する作者は、
古くなったrangeまたはカスタムハイライトを破棄し、新しいものを再作成することによって、
DOM の変更を監視し、それに対応するべきです。
文書のレンダリング方法を計算するとき、
その文書の window に関連付けられたハイライトレジストリ内の任意のrangeの開始ノードまたは終了
ノードが、
shadow-including rootがその文書ではない Nodeを
参照する場合、
ユーザーエージェントはその range を無視しなければなりません。
その文書の window に関連付けられたハイライトレジストリ内の
任意の StaticRangeが
有効でない場合、
ユーザーエージェントはその range を無視しなければなりません。
カスタム
ハイライト内の StaticRangeと
[css-contain-2] の相互作用には問題があるように見えます。
完全に containment された要素では、
その要素の子孫に対する DOM の変更が、
containment された要素の外部にある要素の無効化や再スタイル設定/再ペイントを
引き起こさないことが期待されます。
しかし、static range の一方の境界点が containment されたサブツリー内にあり、
もう一方の境界点がその外側にあり、
containment されたサブツリー内の DOM が変更されて、
内部の境界点が有効なノードを指さなくなった場合、
range 全体を無視するべきであり、
これは containment されたサブツリー外部のペイントに影響します。
これはスタイル containmentの弱点なのでしょうか、
それとも上記の無効化ロジックの弱点なのでしょうか、
あるいは別の何かなのでしょうか? [Issue #4598]
6. イベント処理
https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/master/highlight/events-explainer.md に基づくイベントに関する節は未定です
カスタム ハイライトには専用のイベント処理メカニズムを持たせるべきでしょうか、 それとも一般に疑似要素へ追加するべきでしょうか?
付録 A. プライバシーとセキュリティに関する 考慮事項
この節は非規範的です。
この仕様が新たなセキュリティまたはプライバシー上の懸念を導入するとは考えられていません。 これが正確でないと疑う人には、 CSS ワーキンググループまたは共同編集者に連絡することが推奨されます。
付録 C. 変更点
この節は非規範的です。
2020年12月8日付 ワーキングドラフト以降の変更点
さまざまな編集上の改善と軽微な調整に加えて、 主な変更点は次のとおりです。
-
HighlightsRegisterをHighlightRegistryに改名しました。 -
HighlightRegistryから 冗長なadd()メソッドを削除しました。 (Issue 6092 を参照) -
カスタムハイライトオーバーレイがネイティブハイライトオーバーレイより下に重なるようにしました。 (Issue 4595 を参照)
-
ハイライトの優先度を浮動小数点数ではなく整数で扱うようにしました。 (Issue 4592 を参照)
-
ハイライト優先度のデフォルト値を 0 と定義しました。 (Issue 6136 を参照)
-
HighlightRegistry を(setlike ではなく)maplike にし、 Highlight から
nameプロパティを削除しました。 (Issue 5910 を参照) -
誤った window からの range はペイントされないことを明確化しました。 (Issue 6417 を参照)
-
カスタムハイライトには UA スタイルが存在しないことを規定しました。 (Issue 6375 を参照)
-
range の無効化について [DOM] 仕様に委ねました (Issue 4597 を参照)
-
Highlightにtype属性を追加し、異なるハイライトにより明確な意味論を与えることで、 ハイライトをアクセシビリティツールに公開することを支援しました。 (Issue 6498 を参照)
2020年10月22日付 ワーキングドラフト以降の変更点
2020年10月22日付ワーキング ドラフト以降は、編集上の変更のみが行われています。 差分を参照してください。