-
-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Force percent-encoding of fragment #1
base: master
Are you sure you want to change the base?
Conversation
ありがとうございます。
今のところ疑問に思っている点は以下 2 つです。
|
調査していてわかってきたことですが、フラグメントを Twitter の URL 判定の仕様を調査されたと思うのですが、先程の疑問点 2 つについて、このように修正された理由を教えていただけないでしょうか。 |
しかし、こちらでも更に調べ直したところ(よく調べずにPRを作成して申し訳ありません)、
はフラグメントだけでは十分ではないようです。 また、 https://github.com/ypc2e55orj/playground/tree/rfc3986-reserved-chars や https://ypc2e55orj.github.io/playground を参照していただきたいのですが、そもそもURIにこのような予約文字を使うべきではない( #1 (comment) で例に挙げたようなURLが悪い)考えも浮かんできており、申し訳ありませんが、このPRはかなり見当違いだったかもしれません。 |
解説ありがとうございます。 Twitter の URL 判定を調べれば調べるほど意味不明で困惑しています・・・。https://example.com/() や https://example.com/(hoge は invalid なのに https://example.com/(hoge) は valid なんですよね・・・。 どの文字をパーセントエンコーディングするかについてですが、少なくとも
また、RFC 3986 の 2.3. Unreserved Characters でも記述されていますが、unreserved な文字はパーセントエンコーディングすべきでないということだそうです。
とはいえ末尾に置かれた ところで、RFC 3986 として invalid な URL を扱うかどうかですけど、本来サイト側が適切にエンコードしておいてほしいものですが、実際問題ブラウザが問題なく扱っているので、できるだけサポートしたいなと考えてはいます。 どうあるべきなのか見当がつかず、まとまりのない文章になってすみません・・・。 |
twitter/twitter-text の Issues を見てると数年前のバグが放置されていたりして、RFC 3986 的に valid かどうかにかかわらず、このライブラリのバグった仕様に合わせる必要があるようです・・・。 怪しい文字はすべてエンコードしてしまえば URL として認識してくれるのですが、次のような URL もエンコードすべきなのかというところで頭を悩ませています。
この例ではエンコードしなくても URL として認識してくれますし、むしろエンコードしてしまうと Twitter Card が表示されなくなってしまうようです。 とはいえ、次のような URL ではリンクが壊れてしまうので、対策する必要があります。 カッコの中に文字が入っていると問題ないんですけどね・・・。 twitter/twitter-text の仕様に合わせて細かくチューニングする必要があるなあと考えている次第です。対応にお時間いただきたいです・・・。 |
これまでにいくつか考えていたことがありましたが、まず twitter/twitter-text を読んで仕様を探るべきだと思っていたので、申し訳ありませんが返信しておりませんでした。 考えていたことついて、ここに記させていただきます。 https://regex101.com/r/gUra89/1 // extended encodeURI that returns a value recognized as URL by Twitter
const extendedEncodeURI = uri => encodeURI(uri).replace(/\((?!.+\))|(?<!\(.+)\)|(?<=\)|.)[;,?:@&$.!~*'](?=$|\()/g, c => '%' + c.charCodeAt(0).toString(16).toUpperCase()) これにより、
のような動作をさせることが可能でした。ただ、正規表現部分を少しでも簡潔に書けないかと考えています。 これが twitter/twitter-text やTwitterのURL認識の仕様に合致しているかは未確認なので、漏れがあるかもしれません。 |
先読み・後読みで表現できるのですね。これはすごいです。 MDN によると後読みに対応したのが、Chrome は 62、Firefox は 78 のようなので(先読みはわかりませんでした)、ごくわずかですが切り捨てられるユーザーが出てきますが仕方ないでしょう(アドオンの統計情報を見ると未だに Firefox 56 などを使ってるユーザーがいたりします・・・Firefox Quantum が 57 でしたっけ?)。 ところでひとつ質問なのですが、listener に渡された URL をデコード→エンコード→置換していますが、デコード→エンコードはやっておいたほうが良いのでしょうか? |
エンコードした URL が twitter-text に認識されるかのテストコードを書いてるんですが・・・。 const twitter = require('twitter-text')
const url = 'https://example.com/!'
const text = twitter.autoLink(url)
const valid = twitter.isValidUrl(url)
console.log({ text, valid })
// {
// text: '<a href="https://example.com/" rel="nofollow">https://example.com/</a>!',
// valid: true
// }
URL 単体だと問題なくて、テキストと組み合わさったときに変な挙動になるようですね・・・。判定には |
これはするべきだと私は考えています。
twitter/twitter-text のCJKでの挙動は以下に記載がありました。
ref: https://github.com/twitter/twitter-text/tree/master/js#urls ( ところで、現在のTwitterのURL認識の仕様と twitter/twitter-text は同じなのだろうか、という疑問があります。 |
listenerに渡されたurlのデコード→エンコードはしたほうが良いかtabs.Tab で一部エンコードされるので、足りない分を置換して補う方法でいいのではないかと考えました。tabs.Tab によってエンコードが行われる文字の種類がわからない(Chromium や Firefox のソースコードを読めばわかるんでしょうけど)ので、不足がないか不安ではありますが、判明すれば置換リストに追加で良いかと思います。 twitter/twitter-text のCJKでの挙動おそらくこの巻き添えを食って変な挙動になっているんでしょうね・・・。 現在のTwitterのURL認識の仕様と twitter/twitter-text は同じなのだろうかその疑問はあったのですが、twitter/twitter-text の Description にこう書かれているので多分大丈夫かと思います。
バックエンドでは違う言語が使われている可能性もあります(Scala が使われているんでしたっけ)し、言語間による差もあるかもしれませんが、近い実装になっていると思うので問題ないと思います。 Twitter Web App で使われているか確認したかったのですが、minify されているので grep するのが難しく、断念しました・・・。 |
テストコードを master に push しました 14a9124 。テストコードから require する都合で extendedEncodeURI() を別ファイル( ところで、listener に渡された url のデコード→エンコードはしたほうが良いかについて、手のひら返しになって申し訳ないですが、渡される URL がブラウザに依存してテストが書きづらいのと、Chromium と Firefox で必ずしも同じ実装になってるとは限らないので、やはりデコード→エンコードはあったほうがいいと思いました。 現状とりあえず extendedEncodeURI() は受け取った文字列をそのまま返すだけになっていますが、デコードされた文字列を受け取って適切にエンコードして返すよう実装できればと思います。疑問点などありましたら、遠慮なくおっしゃってください。 |
Summary
chrome.browserAction.onClicked.addListener(listener)
がlistener
に渡すオブジェクトのurlプロパティでは、フラグメントのパーセントエンコーディングが不十分なため、TwitterはこのようなURLをURLとして認識しません。以下は、83eb8e3 を用いてツイートした例です。
このpull requestでは、上記のようなURLでもTwitterがURLとして認識するように改変しています。
encodeURIComponent()
のみではいくつかの文字がエンコードされないため、それらは置換しています。Reference
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent