ふるさと納税で届いたうどんを茹でている。具という具を用意してなくてただ食べることになりそう。 10〜12分 + 蒸らし 2分とか書かれているけど、こないだそうしたらかなり柔らかかったので 8分 + 2分くらい茹でつつある。
続きを読む切る/切って落とす
何を? | 切る? | 落とす? |
---|---|---|
幕 | 切る | 落とす |
火蓋 | 切る | 落とさない |
口火 | 切る | 落とさない |
火ぶたを切って落とす? | ことば(放送用語) - 放送現場の疑問・視聴者の疑問 | NHK放送文化研究所
「火蓋(ひぶた)」は、「(昔の鉄砲の)火縄銃の火皿の火口をおおうふた」のことで、「火ぶたを切る」の本来の意味は「火縄銃の火蓋を開いて点火の用意をする。また、発砲する」(『日本国語大辞典』小学館)ことです。
https://www.nhk.or.jp/bunken/summary/kotoba/gimon/137.html
(中略)
ところで、「~を切る」という慣用語の一つに「口火を切る」ということばがありますが、この「口火」も火縄銃に関係があります。もともとは「火縄銃の火ぶたに点火するための火」のことで、ここから「物事を始めるきっかけをつくる」という意味の「口火を切る」が生まれました。
きょうの日本語検定:時事ドットコムきょうの日本語検定:時事ドットコム
「幕を切って落とす」は、元々歌舞伎の用語で、舞台の幕を一気に落として演技を始めることから、何かを華々しく開始することをいう。
https://www.jiji.com/jc/e?g=e07&d=20180512&ans=3
ページ内のどの要素でscrollイベントが発火しているかとにかく見るには全部の要素にイベントリスナをつけると便利
スクロールしたときどの要素で scroll イベントが発火しているか探すのが大変なことがあるけど、とにかく全部の要素にイベントリスナをつけて、実際にスクロールしてみることで、とにかく発見することができる。
document.querySelectorAll('body *').forEach(el => { el.addEventListener('scroll', e => { console.log(e.currentTarget); }); });
たまにこういう力技が役に立つ。↓は以前やった body *
の例。
Slackはハイライト部分をU+E000とU+E001で囲って表していそう
Slack は、メッセージのどこからどこまでハイライトするかを、 Unicode の私用領域 *1の U+E000 と U+E001 を使って表しているらしく、こういう HTML を glitch とかで書いて、
<html> <head> <meta property="og:title" content="Slackでタイトルをハイライトする" /> <meta property="og:description" content="Slackで説明も好きな部分をハイライトする" /> </head> </html>
そのページを Slack で展開させたりすることで、好きな部分を勝手にハイライトできて面白い *2 *3。
ちなみに printf "\ue000寿司\ue001が光ったら成功" | pbcopy
とかして Slack のメッセージ欄にペーストして普通に送信しても、そのまま豆腐が出るだけだった。 API 経由で送ったりしたらハイライトされたりするかも。
詳しくどういうことなのかはわからないものの、ハイライトすべき部分を U+E000 と U+E001 で囲い、そこをハイライトする HTML タグ (スマホアプリではそれ用のコンポーネントとか?) に変換したりしていそう。
これに気づいたのは偶然で、同僚が「Slack の検索画面で自分の名前が豆腐に囲まれている」と言っていたのがきっかけ。文字コードを調べると U+E000 と U+E001 で、これをググってふむ〜って Slack に貼ったら光っていて、マジか!と言いながら glitch を開いて確かめた、という感じ。
「Slack E000」とかでググると意外とヒットして、というか Slack の API の説明にも登場する (https://api.slack.com/search?query=e000 で検索できる)。登場するのは https://api.slack.com/methods/search.messages と https://api.slack.com/methods/search.files で、どちらも同じような説明が書かれている。メッセージやファイルを検索する API で、ハイライト部分を表すのに U+E000 と U+E001 が使われているよ、とのことだった。
All search methods support the
highlight
parameter. If specified, the matching query terms will be marked
up in the results so that clients may replace them with appropriate highlighting markers
(e.g.<span class="highlight"></span>
). The UTF-8 markers we use are:start: "\xEE\x80\x80"; # U+E000 (private-use) end : "\xEE\x80\x81"; # U+E001 (private-use)search.messages method | Slack
*1:https://www.unicode.org/charts/PDF/UE000.pdf とかを見ると「E000-F8FF」は「Private Use Area」で「The Private Use Area does not contain any character assignments, consequently no character code charts or names lists are provided for this area.」らしい
*2:クエリパラメータは違う URL として認識してもらって展開のキャッシュを無視するためにつけている
*3:面白いのでこの記事の og:description の最初の読点の前後にも入れてみた → もっと面白いとよいということで「U+E000 と U+E001 を使って」をハイライトするようにしてみた
ブラウザで:has()セレクタが実装されてjQueryの:has()セレクタの挙動が変わったの調べた
Chromeに実装された疑似クラス「:has()」がjQueryの「:has()」に悪影響、一定の条件下でWebサイトが壊れる可能性 - Publickey を読んだので、調べたものとあわせてまとめる。
三行
原因
- jQuery には CSS セレクタの拡張がされている
- jQuery Extensions | jQuery API Documentation
:has()
もそのひとつだった
- jQuery は、セレクタによって要素を取得する際、パフォーマンスのためにブラウザの
querySelectorAll()
メソッドを使う- セレクタが不正だった場合は
querySelectorAll()
メソッドがエラーになるので、 jQuery の拡張された実装で要素を取得し直す (フォールバックするような感じ)- (そのために jQuery の拡張を使わないほうが速いと書かれているドキュメントもある Optimize Selectors | jQuery Learning Center)
- セレクタが不正だった場合は
- かつては
:has()
はブラウザのquerySelectorAll()
メソッドにとって不正なセレクタだったため、 (エラーになるので、) jQuery の実装で要素が取得されていた- このほどブラウザで
:has()
が実装された- ここまでは問題なく、 jQuery でやっていたことがブラウザでもできるようになったということ
- ただし、
:has()
の引数に書かれたセレクタは不正でも無視される- forgiving-relative-selector-list というもの (後述) https://w3c.github.io/csswg-drafts/selectors-4/#typedef-forgiving-selector-list
:has()
の引数に jQuery の拡張のセレクタを使った場合、 jQuery では問題ないがブラウザのquerySelectorAll()
ではエラーになってほしいのだけど、エラーにはならない (単に取得するものがなかった扱いで成功する)
- このほどブラウザで
- これにより、
:has()
の引数に、ブラウザでは対応していない jQuery の拡張のセレクタを書いた場合、 jQuery で処理されなくなってしまった- 今まで jQuery で取得できていたが、取得できなくなった
forgiving-selector-list
MDN から :has()
の仕様をたどるとここで、引数には <forgiving-relative-selector-list>
をとると書かれている。
The relational pseudo-class, :has(), is a functional pseudo-class taking a <forgiving-relative-selector-list> as an argument.
https://w3c.github.io/csswg-drafts/selectors-4/#has-pseudo
<forgiving-relative-selector-list>
の項 https://w3c.github.io/csswg-drafts/selectors-4/#typedef-forgiving-relative-selector-list を見ると、 <forgiving-selector-list>
でありながら <complex-selector>
ではなく <relative-selector>
としてパースされるものとある。今回は <forgiving-selector-list>
であるという部分だけ気にしたらよい。
<forgiving-selector-list>
は、セレクタそれぞれをひとつずつパースし、パースに失敗したセレクタは無視して、成功したものだけを使うとのこと。今回の (ブラウザの) :has()
で querySelectorAll()
だけを試すとこういう感じで、ブラウザではセレクタとしてパースできない :even
が引数にあるが、エラーにならずに単に無視されている *1。
Chrome と Safari の状況の違い
- 記事中のツイートでは、 Safari の実装では jQuery の挙動を変えないと書かれているように読めた
- Safari は
:has()
の引数を forgiving-relative-selector-list として完全に実装できていないので、 jQuery の挙動が変わってしまう場合と変わらない場合がある- https://github.com/w3c/csswg-drafts/issues/6952#issuecomment-1148856670
:has()
の引数に、ブラウザではパースできないセレクタのみが渡された場合はエラーになるので、ブラウザのquerySelectorAll()
が従来通りエラーになるため、 jQuery の挙動は変わらない (jQuery の実装で要素を取得できる)- これは Safari が仕様に沿えていない (forgiving-relative-selector-list に完全に対応できていない) 状態 244708 – :has() selector does not accept forgiving selector list
:has()
の引数に、ブラウザでパースできるセレクタがひとつでも渡されていた場合、 forgiving-relative-selector-list の挙動になり、ブラウザのquerySelectorAll()
はエラーにならないため、 (Chrome 同様) jQuery の挙動は変わってしまう
実際 Safari で querySelectorAll()
だけを試すとそのようになっている *2。 :even
はブラウザでパースできないので、 :even
がついたセレクタだけが引数にある場合 (1行目と 3行目) はエラーになっている (この場合は jQuery が要素を取得でき、挙動は変わらない)。対して 2行目は body
がパースできるセレクタのため、エラーにならない (この場合は jQuery が処理をしないので、挙動が変わってしまう)。
されている対応と今後
- Chrome は Safari の実装に合わせた修正を入れた
- https://bugs.chromium.org/p/chromium/issues/detail?id=1358953
- Safari と同じ挙動なので、パースできるセレクタが含まれる
:has()
はエラーにはならない (のでその場合は jQuery の挙動は以前から変わっている状態)- が、そういう場合はあまりなかろうということで進んでいそう
Of course, there's still some breakage for selectors like `div:has(div, span:contains('Item'))` but, as I understand, Chrome is hoping that there's not much usage of it in the wild considering WebKit was able to go away with it.
https://bugs.chromium.org/p/chromium/issues/detail?id=1358953#c40
- W3C の対応 issue では、今はかなり混乱する状態で、ここから従来の jQuery の挙動を変えないようにしていくのがよかろう、と書かれていそう
- https://github.com/w3c/csswg-drafts/issues/7676#issuecomment-1250070779
- ブラウザの
:has()
の名前を変えて jQuery の:has()
に影響しないようにするか、ブラウザの:has()
の引数にパースできないセレクタが入っていたらエラーになるようにするか
感想
jQuery 側を直したい気持ちになるけど、古いバージョンのまま残っているサイトを壊さないという観点ではそれは難しいので、ブラウザ側がなんとかして避けるしかないのが (いつもそうだけどやはり) 大変そう。 forgiving-selector-list は初めて知ったし forgiving/unforgiving という表現が使われるのはへ〜という感じだった。あと Chromium の issue で querySelectorAll()
が qSA
と略されて呼ばれているのが面白い。
*1:Google Chrome 105.0.5195.102