Windowsでプロキシ自動設定ファイルを適用するPowerShellスクリプト2020年03月21日 22時23分

Windowsで一時的にプロキシ自動設定ファイル(プロキシ自動構成スクリプト、pacファイル)を利用したいとき、

  • プロキシ自動設定ファイルを配信するHTTPサーバーを立てなければいけない。(以前はローカルファイルが使えたが、Windows 10 Creators Updateから使えなくなった。)
  • Windowsの「プロキシ」設定画面で「スクリプトのアドレス」を指定しなければいけない。

という手間があります。

そこで、プロキシ自動設定ファイルを配信するHTTPサーバーを立ち上げ、そのURLをWindowsのプロキシ設定に指定するPowerShellスクリプトを書きました。

上記リンク先のスクリプトをローカルに保存し、Explorerでスクリプトファイルのコンテキストメニューから「PowerShell で実行」を選択すると、コンソールウィンドウが開き、スクリプト中に記述されたプロキシ自動設定が適用された状態になります。コンソールウィンドウ内でCtrl + Cを押下すれば、プロキシ自動設定が解除されます。

なお、プロキシ自動設定でSOCKSプロキシを使う場合、そのためのSSH接続は別途立ち上げておく必要があります。

既知の不具合

EdgeやInternet Explorerではプロキシ自動設定が期待通り適用されないことがあるようです。

プロキシ設定の変更をブラウザに通知する

プロキシ設定はレジストリに保存されていますが、レジストリの値を書き換えるだけではうまく機能しませんでした。どうもプロキシ設定が変更されたことをWebブラウザなどの各アプリケーションに伝えるために、Windows APIを呼び出す必要があるようです(スクリプト中のRefresh-Proxy-Settings関数の処理)。

もっと言うと、プロキシ設定の変更自体もレジストリを直接いじるのではなく、WinInetライブラリのInternetSetOption関数経由でやったほうがよいようです。ただし、そのためには構造体を定義するなど、PowerShellスクリプト中にC#のコードを書く必要があり、面倒になってやっていません。

Windows PowerShellの感想

今回初めてWindows PowerShellを書いたのですが、.NET Frameworkをそのまま使え、C#のコードを書け、Windows APIまで呼び出せるなど、何でもできる感じで感心しました。Taskオブジェクトを直接扱うことでC#のasync/await相当の処理を実現できるのも面白かったです。

もっとも、気をつけないと「PowerShellを書いていたつもりが、いつの間にかC#を書いていた」ということになりかねませんが(笑)

xargsで入力が空のときに何も実行しない2019年12月31日 19時56分

xargsコマンドで入力が空のときは何も実行しないようにしたいのですが、BSD版(macOSなど)とGNU版(Linuxなど)などで挙動が異なります。BSD版は最初からそのような挙動なのに対し、GNU版では--no-run-if-emptyオプションをつけないとそのような挙動になりません。両者で挙動を合わせるために、シェルスクリプトで以下のように書けます。

NO_RUN_IF_EMPTY=$(: | xargs echo '--no-run-if-empty')
command1 | xargs $NO_RUN_IF_EMPTY command2

コロン(:)は何もしないコマンドであり、パイプでつながれたxargsの入力も空となります。なので、BSD版ではechoコマンドが実行されずNO_RUN_IF_EMPTY変数の値が空文字列となり、一方GNU版ではechoコマンドが実行されNO_RUN_IF_EMPTY変数の値に文字列'--no-run-if-empty'が入ります。

参考: GNU版, BSD版 xargsの挙動の違い - syohex’s diary

JavaScriptの正規表現の戻り読みはPerlのそれよりも表現力が高い2018年12月29日 22時37分

ECMAScript 2018で正規表現の戻り読み(lookbehind)が追加されました。

/(?<=foo)bar/.test('foobar'); // => true
'foobar'.replace(/(?<=foo)bar/, 'baz'); // => 'foobaz

正規表現の戻り読みと言えばPerlでは1998年7月リリースのバージョン5.005からサポートしており、そこから20年もたってと思いたくなるかもしれません。しかし、ECMAScript (JavaScript)のそれはPerlのものとは一味違います。なんと戻り読みの中で量指定子(*+?{n}など)を使えるのです。

// JavaScriptなら(?<=...)の中で+が使える。
/(?<=fo+)bar/.test('foobar'); // => true
# Perlでは(?<=...)の中で+を使おうとするとエラーになる。
"foobar" =~ m/(?<=fo+)bar/;
# => Variable length lookbehind not implemented in regex m/(?<=fo+)bar/ at - line 1.

Perlの場合、戻り読みとして指定されたパターンの文字数だけ戻ってから(文字列末尾方向に向けて)マッチしていきます。あらかじめ戻る文字数がわからないといけないので、戻り読みの中で量指定子を使えません。

一方、ECMAScriptでは戻り読みとして指定されたパターンそのものを逆方向に解釈し、1文字ずつ逆向きに(文字列先頭方向に向けて)マッチしていきます。ですから量指定子が含まれていても問題ないのです。

パターンが逆方向に解釈されるので、後方参照を使えるようになるのも戻る方向になります。

// 1番目の(...)よりも\1のほうが文字列先頭方向側にある。
                                 //     $&     $1
/(?<=f\1(o))bar/.exec('foobar'); // => ["bar", "o"]

ただし、後方参照の番号はパターン内での出現順のままです。

                                              //     $&          $1     $2
/([0-9]+)([0-9]+)兆円/.exec('5000兆円');      // => ["5000兆円", "500", "0"  ]
/(?<=([0-9]+)([0-9]+))兆円/.exec('5000兆円'); // => ["兆円",     "5",   "000"]

D2D アクセシビリティ勉強会 ~WAI-ARIAでアクセシブルにしてみよう~2017年03月20日 12時09分

先日大阪で開催された「D2D アクセシビリティ勉強会 ~WAI-ARIAでアクセシブルにしてみよう~」に参加しました。Web ページ (特に JavaScript を使った動的なもの) のアクセシビリティを高めていくための話と演習です。

前半

前半は SAWADA STANDARD DESIGN の澤田さんによる発表「WAI-ARIAの考え方と使い方を整理しよう」です。

  • WAI-ARIA は要素 (の役割) と属性を追加する
    • 構造や変化をユーザーエージェントに伝える
  • ロール (役割) にはランドマークロール、文書構造ロール、ウィジェットロールがある
    • HTML にもともと同じロールの要素があるのならそれを使えばいい (無理に WAI-ARIA のロールを指定する必要はない)
  • ロールは文書構造やウィジェットを示すだけであり、見た目や機能を変化させるわけではない
    • 見た目を変化させるには CSS が必要
    • 機能 (挙動) を変化させるには JavaScript が必要
  • 実際に支援ソフト (スクリーンリーダーなど) が対応しているか
    • macOS / iOS には VoiceOver、Android には TalkBack、Windows にはナレーターが標準で付属している
      • VoiceOver のローター機能でランドマークを読み上げられる
    • 日本では PC-Talker のシェアが高いので、そこを押さえておきたい

後半

後半はグループごとに分かれ、実際に WAI-ARIA を使ってみる演習です。グループごとに「新着情報」「アコーディオン」「タブメニュー」の三つのお題の中から二つを選び、WAI-ARIA の属性を適宜追加していきました。回答発表時には VoiceOver での読み上げ確認も行われました。

各グループでの議論のポイントおよび回答例はみるくさんの「D2D アクセシビリティ勉強会 ~WAI-ARIAでアクセシブルにしてみよう~を開催しました。 - White Stage」に掲載されています。

感想など

「新着情報」では「続きを読む」リンクにラベルや説明を追加するか議論し、私のグループでは「過不足なく」という観点から (説明過剰にならないように) 結局追加しませんでした。しかし、視覚障碍者は Tab キーでリンクだけたどっていくこともあるので、リンクにも何の続きかわかるようラベル (aria-labelledby 属性、aria-label 属性) や説明 (aria-describedby 属性) を付けたほうがいいとのこと。


回答例を見ると、

<dl>
  ...
  <dt id="day01">2016年5月8日</dt>
  <dd>
    <p id="headline01">第6回 D2D アクセシビリティ勉強会でアクセシブルなフォームを作成!</p>
    <a id="more01" href="news01" aria-labelledby="day01 headline01 more01">&gt;&gt;続きを読む</a>
  </dd>
</dl>

のように aria-labelledby 属性に自分自身の ID を指定しており、そんなこともできるのかとびっくりです。


CMS で生成された内容に適用しやすいよう、新着情報への WAI-ARIA の属性の指定を JavaScript で行うというチームもありました。サーバー側でやるかクライアント側で付与やるかはさておき、指定を (そしてできることなら検証も) 自動化していくのは、広く利用されるために重要なことでしょう。


WAI-ARIA のウィジェットロールの指定は React のような宣言的な UI 記述と相性がよさそうです。「WAI-ARIA 対応のアクセシブルなタブ UI を React で実装する ::ハブろぐ」という記事もあります。

一方、[aria-hidden="true"] { display: none !important; } のように CSS の属性セレクタを使うという話もありましたが、こちらは BEM などの命名規則と組み合わせるとどうなるのか、気になるところです。


懇親会では tabindex 属性に二つの意味があって分かりづらいという話が出ました。その要素にフォーカスできるかどうか (tabindex 属性が存在するかどうか) と、Tab ナビゲーションの順序はどうなるか (tabindex 属性の値が 0 以上のとき) です。この辺りは IE 5 の拡張 (HTML 4 ではリンクとフォームコントロール要素にしか付けられなかった tabindex 属性を、どんな要素にも付けられるようにした) に根差すことでしょうから、今考えるならもう少しうまくできるのではと思ってしまいますね。


勉強会後に Windows 用スクリーンリーダー NVDA をインストールしてみました。開発者向けには「ポータブル版を作成」し、必要に応じて起動したほうがよいとのことです。ポータブル版作成時に、指定したフォルダの直下にファイルが展開されるので、新規にフォルダを作ってそれを指定するのがよさそうです。

CSS の -webkit-line-clamp プロパティについて2016年12月02日 15時07分

結論からいうと、CSS の -webkit-line-clamp プロパティは使わないほうがいい。現状および今後の Web ブラウザでのサポートが望めないからである。

-webkit-line-clamp CSS プロパティとは何か

複数行でも3点リーダーをきかせることができるというもの。

このプロパティはどうやって使うか

-webkit-line-clamp プロパティ単体では効果を持たず、他のプロパティと組み合わせて使う。

selector {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
}

このプロパティは何のために存在するのか

おそらくは Apple 製アプリケーションでの内部的な利用のため。このプロパティは、Safari CSS ReferenceAdditional Unsupported Properties の項に記載がある。

WebKit provides partial support for a number of properties that are not supported for developer use. This list may include:

  • Properties designed for Apple internal use, such as properties specific to the way Mail and other applications use WebKit.
  • Properties that are in a very early stage of development and are not really usable yet.
  • Properties that are used within WebKit itself and cannot be parsed in a CSS file.
  • Properties that are parsed for historical reasons, but that are not actually used.

適当に訳すと、

WebKit は、開発者の使用に対してはサポートされないプロパティを、いくつか部分的にサポートしている。このリストには以下を含む:

  • Apple の内部的な利用 (Mail など、WebKit を使うアプリケーションに固有のもの) のために設計されたプロパティ。
  • 開発のごく初期段階であり、まだ実用に耐えないプロパティ。
  • WebKit 内部で使われ、CSS ファイルからはパースできないプロパティ。
  • 歴史的な理由でパースはされるが、実際には使われないプロパティ。

このプロパティの開発状況はどうなっているか

このプロパティは -webkit-box、すなわち旧式の flexbox (flexible box) と組み合わせる必要がある。現 flexbox 仕様とは相いれない。このことから、このプロパティは旧 flexbox 時代に内部利用のため、もしくは実験的に実装され、そのまま放置されたものではないかと推測される。実際に上述の文書ではこのプロパティが「サポートされない」ものとして挙げられている。

このプロパティをベンダ接頭辞なしで書く必要があるか

ない。display: -webkit-box というのは旧 flexbox 仕様の値にベンダ接頭辞をつけたものであり、そこからベンダ接頭辞を外して display: box と書いたところで、どのブラウザもサポートしていない。現 flexbox 仕様では display: flex という全く別の値を使うようになっている。なので、

selector {
  display: -webkit-box;
  display: box;
  -webkit-box-orient: vertical;
  box-orient: vertical;
  -webkit-line-clamp: 3;
  line-clamp: 3;
}

のようにベンダ接頭辞付きのプロパティを併記するのは無意味である。後述するように、line-clamp というプロパティが制定されることもない。

このプロパティは標準化されるのか

line-clamp というプロパティ名では標準化されない。2014 年 6 月の W3C CSS WG のミーティングにおいて、-webkit-line-clamp プロパティのことが議題に上がっている。そこでの結論としては、最大行数の指定とブロックに対する省略記号の問題は別々に議論していこうというものである。

-webkit-line-clamp プロパティの持つ、

  • 最大行数の指定
  • 最大行数をはみ出した内容の扱い
  • 省略記号の表示

という機能は別々のプロパティや疑似要素として CSS Overflow Module で検討されていくことになると思われる。(該当 issue)

余談: ベンダ接頭辞について

開発者が -webkit- ベンダ接頭辞付きのプロパティ / 値しか書かないという状況が蔓延したため、ベンダ接頭辞は無意味なものとなった。今やモバイル向けブラウザの多くは (WebKit でなくとも) -webkit- ベンダ接頭辞付きのプロパティを解釈する。(そうしないとモバイル向け Web サイトがまともに機能しない)

挙句の果てには、――これは CSS ではなく DOM の話だが――webkit 接頭辞付きのメソッドがエイリアスとして仕様に取り込まれるという体たらくである。

これらの反省から、現在のブラウザ開発ベンダはベンダ接頭辞を使わず、開発版ブラウザを使っているときや、ユーザーが明示的にオプションを有効にしたときのみ仕様策定中の機能を有効にするという方針になっている。ベンダ接頭辞は、かつて試験的に実装されたプロパティにつけることはあっても、今後新規に実装されていくプロパティにつける必要はない。

ベンダ接頭辞をつけるにしても、手動でつけていくのではなく、Autoprefixerのようなツールを使って自動的につけていくのが確実である。


この記事は、はてなエンジニアアドベントカレンダー 2016 の 2 日目の記事として公開された。翌日の担当は id:wtatsuru である。