Quantcast
Channel: 風柳メモ
Viewing all 92 articles
Browse latest View live

【覚書】 Twitter の画像サイズの変換など(PNG・JPEG)

$
0
0

Twitter に画像(PNG・JPEG)をアップロードし、これを表示する際、URLの末尾によってそれぞれ異なるサイズの画像が得られるが、これに関する覚え書きなど。



Twitter の画像サイズ種別

Twitter にアップロードした画像は、以下のような URL で参照(表示)できる。

https://pbs.twimg.com/media/~.<拡張子>[:サイズ種別]

サイズ種別は以下のようになっている。

:サイズ種別最大サイズ(*1)
:thumb150px×150px
:small680px×680px横340px(*2)
680px×680px(*3)
:medium
(なし)
1200px×1200px横600px(*2)
1200px×1200px(*3)
:large2048px×2048px横1024px(*2)
2048px×2048px(*3)
:orig(制限なしか?)横8000px(?)(*2)
4096px×4096px(*3)

(*1) このサイズ内の画像は原寸で取得できるが、それ以上のものは矩形に収まるよう縮小される(:thumbについては、短辺に合わせてトリミング&リサイズされているものと思われる)。
なお、各種別毎の最大サイズは2016/02/24時点。これまでも何度か変更されている模様。

(*2) 2016/04/13の時点で確認した内容に修正(いつの時点で変更されたかは不明、過去の画像サイズはそのまま)。矩形に収めるようにではなく、横幅を基準に縮小されている?
(*3) 2016/06/05の時点で確認した内容に修正(いつの時点で変更されたかは不明、過去の画像サイズはそのまま)。再び、矩形に収めるように縮小されるようになった(戻った)?


また、試した範囲では、:orig を除く種別については、アップロードした画像の種別(PNG/JPEG)に関わらず、二種類(PNGおよびJPEG)の画像がそれぞれ作成される模様。
これはURL中の拡張子の部分を、pngにしたものjpgにしたものとをダウンロードして調べた。なお、拡張子をgifにしたものもダウンロードできるが、中身はPNG形式のものと同一の模様。

原寸画像(:orig)の画像種別について

:orig については、2016/02/24時点で、表示(ダウンロード)できるのは PNG もしくは JPEG のどちらかに限られる(それ以外は 404 not found となる)。
アップロードした画像の種別と、実際に表示(ダウンロード)出来る画像の関係は以下のようになっている。

アップロード種別PNG(.png:orig)を表示JPEG(.jpg:orig)を表示
JPEG×
PNG(24bpp)PNG(透明ピクセル無し、もしくは約3MBを超えるもの?)×
PNG(32bpp)PNG(透明ピクセル有り、かつ約3MB以下のもの?)×

なお、種別に関わらず、Twitter側での画像変換は実施されるため、完全に元画像と同じものではない。

トピックス

原寸画像(:orig)の劣化を抑えるには?(アップロードの前に)

24bpp(アルファチャンネル無し)透明ピクセル無しのPNG画像はJPEGに変換されてしまうため、PNG形式のままで表示(ダウンロード)させたい場合は、32bpp(アルファチャンネル有り)に変換透明ピクセルを追加した後にアップロードするのが今のところ解決方法となる。
ただし、32bpp のPNG 画像が :orig を付けて原寸でダウンロードできた場合も、元画像そのものがダウンロードできるわけではなく、Twitter側で変換されたものになる(アップロードしたものとはファイルサイズ等が異なっている)。

既存の画像については、例えばPNG 32bpp変換 | しぇ庫を使って簡単に24bppから32bppへ変換できる(2016/02/27現在、Twitterの仕様変更により、透明ピクセル追加の対応検討中とのこと→2016/02/28に改訂版がリリースされた)。

原寸画像を表示・保存するためのブラウザ拡張機能/スクリプト

PC 用ブラウザで、Web 版 Twitter の原寸画像を表示したり、ダウンロードしたり出来る拡張機能/ユーザースクリプト等。
furyu.hatenablog.com
いちいち :orig をつけたり、ダウンロード時に拡張子を修正するのが面倒だったので、↓の二つを参考に、独自機能も付け加えて自作したもの。原寸表示・ダウンロード共に対応。Google Chrome、Opera、Firefox(Greasemonkey)に対応(ブックマークレットは一部機能を IE11 にも対応)
hogashi.hatenablog.com
chrome.google.com

試行錯誤など


スマートフォンで公式アプリを使った場合、最大横2048pxあたりまで(アプリ側で)縮められてしまうのかも…?


↑は元画像がJPEG・3264px×2448px(3.39MB)だが、:orig で見ても2048px×1536pxまで縮小させれてしまっている


【アマゾン注文履歴フィルタ】CSVファイルとExcelを使って必要な注文だけを印刷(PDF出力)する手順

$
0
0

アマゾン注文履歴フィルタ
furyu.hatenablog.com
で、『領収書を必要な分だけ細かく指定して印刷(PDF出力)したい』といった場合、いったん全件表示を行い、そこからダウンロードした CSV ファイルを Excel で読み込ませて必要な注文を絞り込むのが、比較的楽な方法だと思います。
ここでは、その手順を示します。




CSV ファイルと Excel を使って、必要な注文だけを絞り込む方法

  1. まず、対象月等の最低限の条件を指定し、
    f:id:furyu-tei:20180301002736p:plain
    [領収書印刷用画面]を開きます。

     

  2. 領収書の読み込みが完了したら(印刷はせずに)[注文履歴CSV(参考用)ダウンロード]をクリックし、
    f:id:furyu-tei:20180301002803p:plain
    CSVファイルをダウンロードします。

     

  3. ダウンロードしたCSVファイルをExcelで開き、適当な位置に作業用の列を挿入します(例では「チェック」列としています)。
    f:id:furyu-tei:20180301002831p:plain
    商品名などを確認しつつ、必要なものに印(○印など)をつけて仕分けていきます。
    同一の注文番号のものは、一番上の奴だけ印を付ければ大丈夫です。

     

  4. 仕分け終わったら、Excelの機能でフィルタをかけます。
    f:id:furyu-tei:20180301002849p:plain

     

  5. 結果から、「注文番号」列の表示されているセルだけを選択します。
    表示されているものだけを選択するには(普通に範囲選択した状態で)「[Alt]+[;](セミコロン)」を押します(これはWindowsの場合です。Macの場合、「[shift] + [command] + [Z]」だそうです)。
    f:id:furyu-tei:20180301013017p:plain
    選択したら、コピー([Ctrl]+[C])します。

     

  6. 上でコピーした注文番号を、別のシートに貼り付けます([Ctrl]+[V])。
    f:id:furyu-tei:20180301002927p:plain
    その上で、TEXTJOIN関数を使って、各注文番号を" OR "でつなぎます。
    =TEXTJOIN( " OR ", TRUE, <注文番号の入ったセルの範囲> )
    なお、TEXTJOINはExcel2016からサポートされたワークシート関数だそうです
    Excel2013以前をご使用の場合、後で示すアドインを入れてみて下さい
    もしくは、別途テキストエディタ等に注文番号列をコピー&ペーストし、改行を" OR "に変換します。

     

  7. 得られた文字列(注文番号を" OR "でつなげたもの)を、注文履歴フィルタの「絞り込み」欄に貼り付け、[適用]ボタンを押します。
    f:id:furyu-tei:20180301013309p:plain
    必要な注文のみが抽出されるので、再度[領収書印刷用画面]を開き、印刷(PDF出力)を行います。

     

TEXTJOINなどのExcel2013以前ではサポートしていない関数を、疑似的に使えるようにするアドイン

上で述べたTEXTJOINは便利な関数なのですが、残念なことにExcel2016より前のバージョンでは含まれていません。
幸い、Excel2013以前でもTEXTJOIN等のワークシート関数を、ユーザー定義関数として使う方法を紹介してくださっている一連の記事がありました。
ありがとうございます!>はけた @さん
www.excelspeedup.com


これらをまとめて、アドイン(Excel2016Func.xlam)としてインストールできるようにしてみました。
以下からダウンロードできます。

Excel2016Funcのダウンロード

GitHub - furyutei/Excel2016Func: Excel2013以前で未サポートのワークシート関数の一部を疑似的に使用可能にするアドイン

インストール方法などは、こちらをご覧ください。
なお、Mac の場合には、インストール/アンインストール用のスクリプト(VBScript)は動作しないため、"Excel2016Func.xlam"を適当なディレクトリにコピーした上で、手動でインストールする必要があります。
support.office.com
を参考にしてください。
[ツール] メニューの [アドイン] を選択し、 [アドイン] ダイアログ ボックスの [参照] をクリックして、"Excel2016Func.xlam"をコピーした場所を探して指定し、[OK]を押します。
「☑Excel2016Func」にチェックがついていることを確認してください。

なお、作者はMacを持っていないため、詳細はわかりません。あしからずご了承ください。

参考にした記事など

artfulplace.hatenablog.com

www.excelspeedup.com

fnya.cocolog-nifty.com

【覚書】ノートン 360 のせいで、pip freeze がフリーズした件

$
0
0

Windows 10 上の Ubuntu で

$ pip freeze

を実行したら、文字通りフリーズしてしまった。
プロンプトに返ってこない。pip install 等を実行した場合も同様。

原因は、ノートン 360 Norton 360のファイアウォールだった。
同様の事が発生したときに焦らないように、メモ書きしておく。




原因と対策

Python 3(3.6.3)の python3 (実行ファイル) がブロックされていたのが原因。
ノートン 360 の
「設定」→「ファイアウォール」→「プログラム制御」
で確認すると、python3の『信頼』項目が『未確認』になっていた。
この状態で、アクセスが『自動』になっていると、ネットワークアクセスがブロックされてしまうため、これを手動で『許可』に変更して[適用する]必要があった。
ファイアウォールのプログラム制御画面

余談…というべきかどうか

ノートン 360 のライブアップデートで、インストール失敗

pip freeze や pip install が固まってしまう状態になった際、過去の経験


もあって、「どうせまた、ノートン 360 が原因だろう」と思い、軽い気持ちで手動でライブアップデートを実施したところ……再起動後に
ノートン 360のインストールでエラーがありました。続行できません。
と言われてしまい、往生した。
もちろん、ノートン 360 そのものも動作していないので、ノーガードです。
その後の復旧

上記の状態で、どうしようもないのでそのまま強制的に再起動すると*1、今度は、
ライブアップデートエラー
のようなダイアログが現れた。
最初からこっちを出してくれ、と思わないでもない。
『サポートWebページに移動する』リンク先の指示に従って、『ノートン削除/再インストールツール』(NRnR.exe) をダウンロードして実行。
削除と再インストールを行うことで、なんとか復旧することができた。

*1:普通に再起動しようとすると、再起動をキャンセルしてとノートン360に言われてしまう……キャンセルせず、強制的に再起動する必要があった

【覚書】viewport指定について

$
0
0

モバイルデバイス用のviewport設定についてまじめに調べようとしたら深みにはまりそうだったので、とりあえず整理を兼ねて、覚え書きを残しておく。
また、viewportの簡易的な表示テストができるページも作ってみた




viewport の指定方法

viewportは、HTMLのhead内のmeta要素として指定する

<metaname="viewport"content="(viewportのパラメータ)" />

viewportのパラメータはカンマ(",")区切りで指定。

なお、これは主としてモバイルデバイス(スマートフォン・タブレットなど)用の設定であり、基本的にはデスクトップ用ブラウザの表示には影響を与えない。
ブラウザが常に全画面で表示されるために、基本、ウィンドウの幅=デバイスの表示幅となるモバイルデバイスにおいて(余白が出来たり見切れたりすることなく)適切なページを表示を行うための指定という認識。

viewportの主要なパラメータ

<meta name="viewport">の content の値
設定可能な値説明
width正の整数または文字列 device-widthウェブサイトを描画したいビューポートの幅をピクセル数で定義します。
height正の整数またはテキスト device-heightビューポートの高さを定義します。どのブラウザーでも使用されていません。
initial-scale0.0から 10.0までの、正の数値デバイスの幅 (ポートレートモードでの device-widthまたはランドスケープモードでの device-height) とビューポートの寸法との比率を定義します。
maximum-scale0.0から 10.0までの、正の数値ズームの最大値を定義します。この値は minimum-scaleと同じまたはより大きくしなければなりません。そうではないときの動作は未定義です。ブラウザーの設定でこの規則を無視できます。また、iOS 10 以降は既定で無視します。
minimum-scale0.0から 10.0までの、正の数値ズームの最小値を定義します。この値は maximum-scaleと同じまたはより小さくしなければなりません。そうではないときの動作は未定義です。ブラウザーの設定でこの規則を無視できます。また、iOS 10 以降は既定で無視します。
user-scalableyesまたは nonoを設定すると、ユーザーはページのズームができなくなります。既定値は yesです。ブラウザーの設定でこの規則を無視できます。また、iOS 10 以降は既定で無視します。
<meta>: 文書レベルメタデータ要素 - HTML | MDN
viewportを指定しないとどうなる?

viewport指定を省略した場合、モバイルデバイスでは、ブラウザが暗黙的にデフォルトのwidth値(ブラウザ毎に異なる、例えば980といった値)を用いて、これをウィンドウ(≒スクリーン)内に収めるように表示される。
例えば、デスクトップ向けのページなどで、横幅がこれより大きい値を前提として設計されていたら見切れてしまう。

device-width とは?

device-widthとは、モバイルデバイスが持つ画面(スクリーン)の論理解像度(ポイント実質解像度CSSピクセル)の横幅のことで、これはカタログに載っている解像度(画素数)とは異なる。
device-heightは同じく縦幅のことだが、ほとんど使うことはないと思われる。
例えば、iPhone X のディスプレイは5.8インチ・1125x2436ピクセルの解像度を持つが、device-widthは375(device-heightは812)となる。
すなわち、ブラウザのウィンドウで375px×812pxの画像を等倍で表示した場合、画面にピッタリと収まるサイズで表示されるということになる。

initial-scale とは?

基本的には、ページを表示した際の、最初の表示倍率(拡大率)のこと。
例えば、initial-scale=1 の時は等倍で、initial-scale=0.5の時は幅が半分に縮小(矩形としては4分の1)、initial-scale=2の時には幅が倍に拡大(矩形としては4倍)となる。

これだけならばよいのだが、ややこしいのが『条件によっては viewport の大きさに影響してしまう』ということ(後述)。

viewport が影響する主な要素

JavaScript

viewportの指定によりブラウザのウィンドウの大きさが決まることになるため、window.innerWidth・innerHeightといったパラメータに影響する。
なお、window.screen.widthやwindow.screen.availWidthは、viewportの指定によらず一定で、デバイス固有の値(≒device-width)を持つ。

viewport 設定テスト用ページについて

簡易的な viewport 設定テスト用ページを作成した。

viewport setting tester

  • radioボタンに応じて、meta[name="viewport"]を書き換えるようになっている。
  • 条件によっては、値を変更しても表示が変わらない場合がある。この場合、[Reload]を押すことで反映される。
    Mobile 版 Firefox では、[Reload]を押しても変わらない場合あり。この場合、ページをいったん閉じて、開きなおす必要がある。
  • Google Chrome の開発者ツールのモバイルデバイスエミュレータ(device toolbar)で、画面の拡大縮小(ピンチアウト/イン)の操作は、[Shift]+ドラッグ(スワイプ)で行う([Ctrl]+[+]/[-]では変化しないことに注意)。リセットは[Ctrl]+[0]。

具体的な viewport 指定の例

"width=device-width, initial-scale=1"で、万全!?

viewportについて調べていると、典型的な設定例として出てくるのは、

<metaname="viewport"content="width=device-width, initial-scale=1" />

のようなもの。

  • viewport(≒ブラウザのウィンドウ)幅を device-width に
  • 最初の表示倍率を 1 に

という指定。
f:id:furyu-tei:20180520095805p:plain

適切なレスポンシブ対応(メディアクエリのブレイクポイントの設定)が行われている場合には、この設定で問題は無い。

レスポンシブ対応がなされていない場合

レスポンシブ対応がなされておらず、『とりあえず、デスクトップ用の画面を、モバイルデバイスでも横幅が綺麗に収まる形で表示したい』という場合の設定。
例は、横幅1000pxで設計されているページの例

<metaname="viewport"content="width=1000, user-scalable=no" />

f:id:furyu-tei:20180520095818p:plain
本来ならば、width さえ指定しておけば、ブラウザが拡大率を適切に設定して、スクリーン内に収まるように調整してくれそうなもの。
ではなぜ user-scalable=no を設定しているのかというと、状況によってはこの自動調整がうまくいかないケース(等倍で表示されるケース)があったため
うまく自動調整されない場合の原因は不明。
いずれにしても、user-scalable=no にするとユーザーが拡大縮小できなくなってしまい不便なので、早期にきちんとレスポンシブ対応すべきではある。

レスポンシブ対応が不完全な場合

スマートフォンには対応したのだけれど、ある範囲(例えば横幅768px~1199px)のデバイス(タブレット)だけ表示が見切れる(デスクトップ用に1200px前提でページ設計)という場合の設定。

<metaname="viewport"content="width=device-width, initial-scale=1" /><script>
(function(){'use strict';var min_screen_width_for_tablet = 768, // @media (min-width: <min_screen_width_for_tablet>px) { ... }    viewport_width_for_tablet = 1200,    screen_width = window.screen.width;if( min_screen_width_for_tablet <= screen_width ){document.querySelector('meta[name="viewport"]').setAttribute('content', 'width=' + viewport_width_for_tablet + ', user-scalable=no');}})();</script>

デフォルトとして、meta[name="viewport"]には"width=device-width, initial-scale=1"を指定しておき、JavaScript で window.screen.width によりデバイスのスクリーン幅(≒device-width)を調べ、条件に当てはまる場合だけ書き換えを行う。

注意点・問題点など

initial-scale について

上記のとおり、initial-scaleは初期の表示倍率を示すほかに、条件によっては viewport の大きさに影響してしまう。
具体的には、

X = device-width / initial-scale
とするとき、
width < X となる場合には、viewport の幅として X が適用される(widthの指定は無視される)。

模様。
例えばdevice-widthが360のモバイルデバイスの場合に、
"width=640, initial-scale=0.5"
のような指定をすると、実際の viewport の幅としては 720(=360/0.5)が適用されてしまう

また、initial-scale に 1 未満の値を指定しても、状況によってはうまく縮小表示されないケースもある。
具体的な条件は不明。ただし、この場合でも、user-scalable=no と併用すれば正しく縮小表示される模様。

ブラウザによってウィンドウサイズ(innerWidth/Height)の決定方法が異なっている?

f:id:furyu-tei:20180520095827p:plain

Google Chromeの場合
innerWidth/innerHeightは、ユーザーがscale(ピンチインで縮小表示)して表示可能な最大領域のピクセル数を示す模様。

この最大領域の横幅は、document.body の大きさと viewport の minimum-scale により、以下のように決まっている模様。

  • document.body の横幅が viewport の以下の場合には、viewport の幅
  • document.body の横幅が viewport より大きい場合、device-width / minimum-scale と document.body の横幅のうち、小さい方

あくまで最大領域に応じて決まるため、実際のユーザーの拡大縮小操作には影響されない。

Firefoxの場合
innerWidth/innerHeightは、ドキュメントのうち、ブラウザの表示領域に実際に表示されているピクセル数を示す模様。
ユーザーの拡大縮小操作に伴って変動する。

【未確認】Safariの場合
実機が無いため、確認できていない。
【未確認】Windows Tablet / Phone について

Windows 系のモバイルデバイスについては、meta[name="viewport"] による指定は効かないため、別途、CSS で @-ms-viewport による指定が必要
実機が無いこともあり、確認が取れていない。

WordPressをhttps化したら、Contact Form 7 の設定が消えてしまった⁉

$
0
0

WordPress を設置してあるサイトを SSL/TLS(http → https)化し、記事なども含めて http://~ となっていたサイトの URL を https://~ に置換したところ、Contact Form 7 の一部の設定が消えてしまった。
今後も似たような失敗をしそうなので、覚え書きとして記事にしておく。




現象

f:id:furyu-tei:20180607212208p:plain

のような、コンタクトフォーム(Contact Form 7)のメールテンプレート設定がなされていたところに、Search Regexを使用して、Post meta value 中のサイトの URL を http://~ から https://~ に置換した。

f:id:furyu-tei:20180607212720p:plain

すると、なぜか、コンタクトフォームのメールテンプレート設定が無くなってしまっていた。

f:id:furyu-tei:20180607212804p:plain

原因

バックアップして置いたデータベースのファイルを調べてみたところ、コンタクトフォームのメールテンプレートは、

(9, 5, '_mail', 'a:9:{s:6:\"active\";b:1;s:7:\"subject\";s:35:\"WordPressてすと \"[your-subject]\"\";s:6:\"sender\";s:42:\"[your-name] \";s:9:\"recipient\";s:18:\"xxxxxxxx@xxxxxxxxx\";s:4:\"body\";s:238:\"差出人: [your-name] <[your-email]>\n題名: [your-subject]\n\nメッセージ本文:\n[your-message]\n\n-- \nこのメールは WordPressてすと (http://xxxxxxxxxxxxxxxxxxxxxxxxx) のお問い合わせフォームから送信されました\";s:18:\"additional_headers\";s:22:\"Reply-To: [your-email]\";s:11:\"attachments\";s:0:\"\";s:8:\"use_html\";b:0;s:13:\"exclude_blank\";b:0;}'),

のような形で格納されていた。

勘のいい方はお気づきだろう……そう、つまり、PHPでシリアル化(serialize)された形式になっているため、http → https へと単純に置換してしまうと、文字数が1文字増えて、シリアル化データとしては壊れてしまい、コンタクトフォームでは不正な値として設定が無効化されてしまったのである。

対策

今回たまたま当方が気付いたのがコンタクトフォームだっただけで、似たような現象は他のプラグインでも発生しうると思われる。
Search Regex による Post meta value の機械的な置換は実施せず、各プラグインの設定にサイトの URL が含まれる場合には、逐次確認して手動で変更するのが無難だろう。
コンタクトフォームに限れば、データベースファイル中の '_mail'や '_mail_2'といった行の "body"中にサイトの URL が含まれる場合、 "body"の長さをひとつ増加させるようなスクリプトでも組んでやれば対応可能ではあろうが。

より効率の良い方法やプラグインなどをご存知の方は、ご教示願いたい。

追記

はけた氏(@)にもツイートでご指摘いただいたが、こういう場合は
interconnectit.com
を使うのが定石の模様。

Search Replace DB を使うと、
f:id:furyu-tei:20180608090145p:plain
このように、Post meta value 等のシリアル化されたデータについても、それに考慮した変換を行ってくれる。

なお、実際に不具合で発生したサイトでも最初はこれを試そうとしたのだが、WordPress のバージョンの問題でうまく実行できなかったのであった……環境はなるべく最新のものを使おうね、というお話(自分が制作・管理していない場合、いかんともしがたいが・苦笑)。

Firefox のアドオン(content_scripts)でXMLHttpRequestやfetchを使う場合の注意

$
0
0

先日、Firefox で Twitter メディアダウンローダが正常に動作しないという報告を受け(その後、近傍ツイート検索も異常な動作をすることが判明)、原因を突き止めるのに時間がかかったので、覚え書き。

結論として、Firefox(バージョン58以降)では、アドオンの content_scripts 内で XMLHttpRequest や fetch にページ(コンテンツ)上から実行されたのと同じ動作を期待するためには、window.XMLHttpRequest や window.fetch の代わりに content.XMLHttpRequest や content.fetch を使う必要がある、ということ。





現象

Firefox 上で、Twitter 用のアドオン(Twitter メディアダウンローダ(0.1.1.2801以前)/近傍ツイート検索(0.2.6.1200以前))を動かすと、jQuery.getJSON() や jQuery.ajax() で、本来 JSON が返されるべきところが HTML が返ってきてしまい、正常に動作しない。
Google Chrome 拡張機能版や、Firefox でも Tampermonkey 上のユーザースクリプトとして問題なく動作する。

原因

当該関数による GET リクエストの HTTP Request Header に

  • Origin: null がセットされる
  • Referer はセットされない

という動作になっていた。
このため(Twitter 側で(おそらく 最近になって)これらをチェックするようになったため)正常な応答が返されなくなっていた。

なお、この現象が発生した際には、当該通信は開発者ツールのネットワークモニタ上に表示されない、という副作用もある。


追記(2018/07/19)

SWSが本脅威を対策するためには、Refererなどを確認してリクエストの正当性を検証したり、CookieにSameSite属性を付与する手法などが考えられます。

ソーシャルウェブサービスにおける新たなプライバシー脅威「Silhouette」を発見:NTT持株会社ニュースリリース:NTT HOME

実は、このプライバシー脅威(Silhouette)への対策の影響だった、とか?

対策

This is accomplished by exposing more privileged XHR and fetch instances in the content script, which has the side-effect of not setting the Origin and Referer headers like a request from the page itself would, this is often preferable to prevent the request from revealing its cross-orign nature. From version 58 onwards extensions that need to perform requests that behave as if they were sent by the content itself can use content.XMLHttpRequest and content.fetch() instead. For cross-browser extensions their presence must be feature-detected.

Content scripts - Mozilla | MDN

バージョン58以上の Firefox においては、アドオンで content_scripts 内で XMLHttpRequest や fetch (およびそれらを使用している jQuery 等のライブラリ)を使用するときには、window.XMLHttpRequest や window.fetch の代わりに、content.XMLHttpRequest や content.fetch を用いればよいらしい。
これにより、普通にページ(コンテンツ)上から発行されたのと同様に、Origin や Referer がセットされるようになる。

注意事項

content_scripts 内では、window.XMLHttpRequest や window.fetch は read-only になっているため、content.* で上書きしようとしてもできない。

自作スクリプト内ならば、使用するスコープの最初で、

const XMLHttpRequest = ( typeof content != 'undefined'&& typeof content.XMLHttpRequest == 'function' ) ? content.XMLHttpRequest  : window.XMLHttpRequest;
const fetch = ( typeof content != 'undefined'&& typeof content.fetch == 'function' ) ? content.fetch  : window.fetch;

のようにしておけばよいかも。

問題なのは、jQuery のようなライブラリを使用する場合で、作りによってはソースコードを直接書き換えるしか無いかもしれない。
なお、Firefox のアドオンを AMO にアップする際には、既知のライブラリを使う場合、改変されたものは同梱出来ない、という制約がある。レビューでチェックされ、改変が見つかった場合は当該バージョンが無効化されてしまう(経験済み(汗))。

幸い、jQuery の場合には、読み込んだ後にjQuery.ajaxSettings.xhrを次のような感じにオーバーライドしてやればよいっぽい。

if ( ( typeof content != 'undefined' ) && ( typeof content.XMLHttpRequest == 'function' ) ) {
    jQuery.ajaxSettings.xhr = function () {try{returnnew content.XMLHttpRequest();
        }catch ( e ) {}};
}

【覚書】他社で取得した独自ドメインのメールアカウントをさくらのレンタルサーバーで使う場合のDNS設定方法

$
0
0

さくらのレンタルサーバーのメールサーバー機能を利用して、(さくら外で取得した)独自ドメインのアカウントでメールを送信したら、Gmail で「未認証メール」扱いとなった(「?」マークがついた)。
調べてみると、独自ドメインの DNS 設定(SPFレコード)が誤っていた。
再発防止のため、メモ書きとして恥をさらしておく。





メール用の DNS 設定例

さくらのレンタルサーバーの設定が以下の様になっている場合、

項目値(例)備考
初期ドメインmyaccount.sakura.ne.jpさくらのアカウント名が頭に付くドメイン名
独自ドメインmydomain.com(さくら外で取得した)独自ドメイン名
ホスト名wwwNNN.sakura.ne.jpさくらのサーバーのホスト名(IPv4アドレス=YYY.YYY.YYY.YYY)
※サーバ情報の表示>サーバに関する情報の「ホスト名」
SPFチェック対象となる(メールヘッダのReceived: from ~に記載される)のはこちら
IPアドレスXXX.XXX.XXX.XXX初期ドメインに紐づいたIPv4アドレス
※サーバ情報の表示>サーバに関する情報の「IPアドレス」
※共有アドレスか専用アドレスかはプランによって異なる
サーバーのホスト名に紐づいたもの(YYY.YYY.YYY.YYY)とは異なる場合があることに注意

メール用として、(他社の)DNSサーバーには以下の様に MX レコードと TXT レコード(SPFレコード)を登録する。

mydomain.com.          3600    IN      MX      10 myaccount.sakura.ne.jp.
mydomain.com.          3600    IN      TXT     "v=spf1 a:wwwNNN.sakura.ne.jp mx ~all"
失敗例

SPF レコードを

mydomain.com.          3600    IN      TXT     "v=spf1 ip4:XXX.XXX.XXX.XXX ~all"
mydomain.com.          3600    IN      TXT     "v=spf1 a:myaccount.sakura.ne.jp ~all"
mydomain.com.          3600    IN      TXT     "v=spf1 mx ~all"

といった様に、許容するIPアドレス/ドメインとして初期ドメインを設定してしまうと、認証に失敗してしまう(場合がある)。
ビジネスプラン等では、初期ドメイン(myaccount.sakura.ne.jp)とサーバーのホスト(wwwNNN.sakura.ne.jp)が示すIPアドレスが異なっているため、失敗(softfail)する。スタンダードプラン等では同じIPアドレスを示すので、結果的に通る(pass)場合もある。

例えば Gmail アドレス宛にメールを送付したとき、認証に失敗していると、メールヘッダで

ARC-Authentication-Results: i=1; mx.google.com;
       spf=softfail (google.com: domain of transitioning user@mydomain.com does not designate YYY.YYY.YYY.YYY as permitted sender)smtp.mailfrom=user@mydomain.com

のように SPF チェックの結果が "softfail"であったことが記載され、Gmail で当該メールを見たときに「未認証メール」として、「?」マークが付く。
メールを開き、「?」マークをタップ/マウスオーバすると、「Gmail では、このメールが(スパム発信者からではなく)本当に mydomain.com から送信されたメールであることを確認できませんでした。」といった文言が表示される。

SPF レコードの妥当性チェック

設定した SPF レコードが有効かどうかは、port25が提供しているサービスを使うのが手っ取り早い。

check-auth@verifier.port25.com

宛にメールを送信すると、「Authentication Report」という Subject がついて、

==========================================================
Summary of Results
==========================================================
SPF check:          pass
"iprev" check:      pass
DKIM check:         none
SpamAssassin check: ham

のように SPF チェックの結果などを含むメールが返信されてくる。

chrome-extension-kickstart-typescript が Node.js v12 だとうまく動かない件とその対策

$
0
0

勉強を兼ねてブラウザ拡張機能をTypeScriptで書いてみようと、swimath2.hatenablog.comgenerator-chrome-extension-kickstart-typescriptを試してみたところ、Node.js v12 ではそのままでは動作しませんでした。
試行錯誤の末にとりあえず動くようになったので、覚え書きとして手順等を書いておきます。




対策(お急ぎの方はこちらだけお読みください)

試行環境
# Node.js v12.14.1 LTS および Yarn 1.21.1 は、それぞれインストーラをダウンロードしてインストール済
$ node -v&& npm -v
v12.14.16.13.4

$ yarn -v1.21.1# yo および generator-chrome-extension-kickstart-typescript を npm もしくは yarn にて global インストール#$ npm install -g yo generator-chrome-extension-kickstart-typescript
$ yarn global add yo generator-chrome-extension-kickstart-typescript

$ yo --version3.1.1
手順

1. 拡張機能用のプロジェクト作成
拡張機能用のフォルダを作り(例では sample)chrome-extension-kickstart-typescript を --skip-install 付きで実行
$ mkdir-p sample
$ cd sample
# --skip-install を付けて、npm による自動インストールを抑制
$ yo chrome-extension-kickstart-typescript --skip-install

2. package.json 編集
$ vi ./package.json

※差分例

--- ./package.json.orig 2020-01-11 14:33:14.473509100 +0900+++ ./package.json      2020-01-11 14:44:36.316563000 +0900@@ -32,7 +32,7 @@"chromereload": "0.x.x",
     "debounce": "1.x.x",
     "del": "3.x.x",
-    "gulp": "3.x.x",+    "gulp": "3.9.0","gulp-bump": "2.x.x",
     "gulp-cache": "0.x.x",
     "gulp-clean-css": "^3.x.x",
@@ -57,6 +57,10 @@"vinyl-named": "1.x.x",
     "webpack": "3.x.x",
     "webpack-stream": "3.x.x",
-    "yargs": "^8.x.x"+    "yargs": "^8.x.x",+    "typescript": "^3.x.x"+  },+  "resolutions": {+    "gulp/**/graceful-fs": "^4.x.x"
   }
 }

3. パッケージのインストール
yarn install で必要な全パッケージをインストール
$ yarn install

4. 動作確認
動作するかどうかを yarn run で確認
$ yarn run dev:chrome

※ 正常動作したときの例

yarn run v1.21.1
$ gulp --watch--vendor=chrome[14:56:00] Requiring external module babel-core/register
[14:56:07] Using gulpfile D:\webext\sample\gulpfile.babel.js
[14:56:07] Starting 'build'...
[14:56:07] Starting 'clean'...
[14:56:07] Finished 'clean' after 3.37 ms
[14:56:07] Starting 'manifest'...
[14:56:07] Starting 'scripts'...
[14:56:07] Starting 'styles:css'...
[14:56:07] Starting 'styles:less'...
[14:56:07] Starting 'styles:sass'...
[14:56:07] Starting 'pages'...
[14:56:07] Starting 'locales'...
[14:56:07] Starting 'images'...
[14:56:07] Starting 'fonts'...
[14:56:07] Starting 'chromereload'...
[14:56:07] Starting 'livereload-server'[14:56:07] Finished 'styles:css' after 32 ms
[14:56:07] Finished 'styles:less' after 26 ms
[14:56:07] Finished 'styles:sass' after 26 ms
[14:56:07] Starting 'styles'...
[14:56:07] Finished 'styles' after 20μs
[14:56:07] Finished 'pages' after 27 ms
[14:56:07] Finished 'fonts' after 26 ms
[14:56:07] Finished 'manifest' after 264 ms
[14:56:07] Finished 'locales' after 237 ms
[14:56:07] Finished 'images' after 237 ms
ts-loader: Using typescript@3.7.4 and D:\webext\sample\tsconfig.json
[14:56:10] Finished 'scripts' Hash: 941f7e8c10f53a4b8956
Version: webpack 3.12.0
Time: 2076ms
        Asset     Size  Chunks             Chunk Names
background.js  6.83 kB       0[emitted]  background
   [0] multi ./app/scripts/background.ts 28 bytes {0}[built][1] ./app/scripts/background.ts 254 bytes {0}[built][14:56:10] webpack is watching for changes

経緯

発生した不具合

最初に、qiita.comを参考にして、

$ mkdir-p sample
$ cd sample
$ yo chrome-extension-kickstart-typescript
# 試行のためとりあえず問にはすべて[Enter]
$ npm install --save-dev typescript
$ npm install --save-dev gulp@3.9.0
$ npm run dev:chrome

のようにしたところ、

$ npm run dev:chrome

> sample@0.0.0 dev:chrome D:\webext\sample
> gulp --watch--vendor=chrome[08:33:12] Requiring external module babel-core/register
fs.js:27
const { Math, Object }= primordials;
                         ^

ReferenceError: primordials is not defined
    at fs.js:27:26
    at req_ (D:\webext\sample\node_modules\natives\index.js:143:24)
    at Object.req [as require](D:\webext\sample\node_modules\natives\index.js:55:10)
    at Object.<anonymous>(D:\webext\sample\node_modules\vinyl-fs\node_modules\graceful-fs\fs.js:1:37)
    at Module._compile (internal/modules/cjs/loader.js:955:30)
    at Module._extensions..js (internal/modules/cjs/loader.js:991:10)
    at Object.require.extensions.<computed>[as .js](D:\webext\sample\node_modules\babel-register\lib\node.js:152:7)
    at Module.load (internal/modules/cjs/loader.js:811:32)
    at Function.Module._load (internal/modules/cjs/loader.js:723:14)
    at Module.require (internal/modules/cjs/loader.js:848:19)
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! sample@0.0.0 dev:chrome: `gulp --watch --vendor=chrome`
npm ERR! Exit status1
npm ERR!
npm ERR! Failed at the sample@0.0.0 dev:chrome script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\testuser\AppData\Roaming\npm-cache\_logs\2020-01-11T06_33_12_337Z-debug.log
調査

Node.js v12 と gulp.js 3 は相性が悪いらしい?!
とりあえず「ReferenceError: primordials is not defined」で検索してみると
stackoverflow.com
に行き当たる。
こちらの回答によると、
  1. gulp.js を version 4 にする
  2. Node.js のバージョンを v12 未満へ下げる

のいずれかで対応できるらしい。

1. の gulp.js のバージョンを変える方は、3→4 の変更に対応してソースコードも変更が必要になると思われるので手間がかかりそうだったため、2. の方法を試してみる。
nvm-windowsで Node.js のバージョンを 10.18.1 LTS にしてみると、確かに動作するようになった。

Node.js v12 & gulp.js 3 のまま使いたいな……
できれば Node.js や gulp.js のバージョンを変えずに使う方法はないか、と調べていると、
timonweb.com
に行き当たる。

要は、gulp.js が利用している graceful-fs のバージョンが古いのが悪いらしい。

$ npm list graceful-fs

で調べてみると、他はほとんどが "graceful-fs@4.2.3"を使っているのに対し、gulp(及び
gulp が依存しているパッケージ)については

+-- gulp@3.9.0
| `-- vinyl-fs@0.3.14|   +-- glob-watcher@0.0.6|| `-- gaze@0.5.2
|   |   `-- globule@0.1.0||     `-- glob@3.1.21
|   |       `-- graceful-fs@1.2.3|   `-- graceful-fs@3.0.12

のように、確かに古いバージョン("graceful-fs@1.2.3"、"graceful-fs@3.0.12")を使っている。

そういえば、yo chrome-extension-kickstart-typescript 実行時にも

npm WARN deprecated graceful-fs@1.2.3: please upgrade to graceful-fs 4for compatibility with current and future versions of Node.js

のような警告が出ていた。これによれば、graceful-fs 4 以降を使うようにすれば良さげ。

上記の記事を参考に、npm-shrinkwrap.json を

{"dependencies": {"graceful-fs": {"version": "^4.x.x"
     }}}

の内容で作成した後、改めて npm install 後に npm run dev:chrome をすると、

# package-lock.json は npm-shrinkwrap.json と排他なため、消しておく
$ rm package-lock.json
# パッケージのインストール
$ npm install
# ※このとき、npm-shrinkwrap.json も更新されることに注意# 開発環境を起動
$ npm run dev:chrome

すると、今度はエラーになると起動することができた。

ただし、この方法だと、

  • npm install --save-dev でパッケージを入れたりすると、最初に指定した "dependencies"が維持されないため、再度 npm-shrinkwrap.json を上記内容に書き換えた上で npm install を実行しなおす必要がある

ということで、やや保守性に欠ける。

特定のパッケージが依存関係にあるパッケージだけバージョンを指定したい
要望としては
  • gulp が依存している graceful-fs のみ、バージョンを指定したい
  • メンテナンスは最小限(意識するのは初回のみ)としたい(パッケージの追加時等に影響無いようにしたい)

となる。

調べてみると npm の代わりに Yarn を使用し、『選択的な依存関係の解決(Selective dependency resolutions)』機能を使えばできそう(package.json に "resolutions"フィールドを追加)。

"resolutions": {"gulp/**/graceful-fs": "^4.x.x"
  }

この方針で調整したのが、こちらの手順になる

参考:npm で Yarn の "resolutions"っぽいことはできないか?
一応、npm 用にそういうパッケージも存在する模様。
github.com

ただ、試してみた限りでは

  • 階層指定("gulp/**/graceful-fs"等といった書き方)はできない
  • "scripts"セクションに"preinstall"を追加するのは、一度 npm install を実行後にする必要あり
    いったん npm install してから(package-lock.json が作成されてから)でないと、npm-force-resolutions がエラーになる
  • パッケージの追加時等でpackage-lock.jsonが更新された際には、npm install をやり直す必要あり

のような感じで、今ひとつ使い勝手が良くないように感じた。
ざっくりとか見ていないため、誤解しているかもしれない

その他

generator-chrome-extension-kickstart 及び主な fork の状況

Google ドライブの共用 PDF を画像データとしてダウンロードするユーザースクリプトを試作

$
0
0

Google ドライブで共用されている PDF ファイルを、画像データにして ZIP 化し、ダウンロードできるユーザースクリプトを作ってみました。
通常は PDF をそのままダウンロードすればよいのですが、まれにダウンロード権限が「閲覧者はダウンロードできません」となっている場合があるため、主にその対策用です。
画像として取得しても、PDF 化したり OCR にかけたりと結局は別途手間はかかってしまいますが……まぁ、手動で1ページずつ落としたりするよりは幾分マシかなと。

インストール・使い方など

github.com
をご参照下さい。

ユーザースクリプトのソースコード


はてなブログでは Gist 貼り付けしかできないみたいなので、gist-it.appspot.com - Embed files from a github repository like a gistを使って GitHub 上のソースコードを貼り付けてみました

Git for WindowsのGit BASHでウィンドウタイトルだけが文字化けする現象(winptyが原因)と対処方法

$
0
0

Git BASHで、たまたま日本語を含むフォルダ下で作業していたら、ウィンドウのタイトルだけが文字化けしていることに気がついた(ウィンドウ内については正常に表示されている)。
Windows 10 Pro バージョン 1909 (OS ビルド 18363.959)、Git for Windows 2.28.0-64-bit、mintty 3.2.0 (x86_64-pc-msys) [Windows 18363]

f:id:furyu-tei:20200812030339p:plain
Git BASHでウィンドウタイトルだけが文字化けしている様子

この現象の原因と、対処方法についての覚え書きを残しておく。




原因

どうやら、~/.bash_profile にて

exec winpty bash

を記述していたためらしい。

試しにこの記述を外すと、ウィンドウタイトルは化けなくなる。
ただし当然ながら、対話型コマンドがそのままではうまく動作しなくなる。

f:id:furyu-tei:20200812040929p:plain
exec winpy bash の記述を外した場合


Python なんかの Windows ネイティブな対話型コマンドを呼び出すのに、いちいち

$ winpty python

としたり、あるいは ~/.bashrc で対話型コマンド毎に

alias python="winpty python.exe"

のように alias 定義するのが面倒だったので bash 自体を winpty で呼び出していたのだけれど、これが原因でウィンドウタイトルが化けてしまうのは想定外……。

対処方法

A. 必要なコマンド毎に個別に winpty を付けて呼び出す alias を定義しておく

bash そのものを winpty 経由で呼び出しているのが原因なのでこれを止め、個別のコマンド毎に winpty 付き呼び出しを行うようにすれば問題はなくなる。
その場合、標準では /etc/profile.d/aliases.sh にて

for name in node ipython php php5 psql python2.7docase"$(type -p "$name".exe 2>/dev/null)"in''|/usr/bin/*)continue;;esacalias$name="winpty $name.exe"done

のように、いくつかのコマンドについて対応されているのを参考にして ~/.bashrc に必要なコマンドについて同様の記述を追記するというのが一つの方法。

B. 環境変数 PS1 を書き換える

A. のようにすると、対話型コマンドの種類が増えるごとにメンテナンスしなければならないため、面倒なのが難点。
bash を winpty で呼び出したときにウィンドウタイトルのみが化けているのが問題なので、プロンプト定義用の環境変数(PS1)を書き換えてやれば良いのではないか? という発想。
状況的に、bash を winpty 経由にした際には、mintty はウィンドウタイトル文字列としては Shift-JIS(CP932) で渡されることを期待しているのではないか、と考えて、$PS1 中に含まれる $PWD の文字コードを変換するように定義してみると、

export PS1=`echo"$PS1"|sed"s~\\$PWD~\\\`echo \\$PWD | iconv -f utf-8 -t cp932 2>/dev/null\\\`~"`

うまくいった。
ウィンドウタイトルに関してだけはなんとかなったということで、winpty bash したときに出る潜在的な問題は他にもあるかも知れない。

f:id:furyu-tei:20200812042525p:plain
ウィンドウタイトルも文字化けせず、対話型コマンドも正常に起動できている

覚え書きを兼ねて、現状の ~/.bash_profile および ~/.bashrc を残しておく。

~/.bash_profile
#【覚書】# ※参考:[bashの.profileや.bashrc等を実行する動作仕様 - sgryjp.log](https://blog.sgry.jp/entry/2019/11/09/232927)#===============================================================================# ・ ~/.bash_profile はログインシェルで一度だけ実行される#   このため、主に##   - ログイン時に一度だけ実行したい処理#   - 対話操作では必要のない(対話操作以外のコマンド実行に必要な)設定(環境変数 LANG 定義等)#   - ログインシェル/サブシェルに関わらず基本変更不要な設定(環境変数 PATH 定義等)##   を記述するのに向く## ・ ~/.bashrc はサブシェルでは自動的に呼ばれる(ログインシェルでは自動では呼ばれない)#   このため、~/.bash_profile からも呼び出されるよう設定の上で (^1)##   - alias や関数等、暗黙的に引き継がれない設定#   - 対話操作のみで必要となる設定(環境変数 PS1、EDITOR 等)##   を記述するのに向く##   (^1) ~/.bashrc があるのに ~/.bash_profile, ~/.bash_login or ~/.profile が無い環境は推奨されず、#        例えば Git for Windows においては、その場合、/etc/profile.d/bash_profile.sh により#        ~/.bashrc を呼び出す記述が入った ~/.bash_profile が生成される#===============================================================================# ■ ~/.bashrc 実行#   ※ログインシェルでは ~/.bashrc は自動的には実行されないため、この設定が必要#test -f ~/.profile && . ~/.profiletest-f ~/.bashrc && . ~/.bashrc

# ■ 各種定義export PYTHONUTF8=1export PYTHONSTARTUP=~/.pythonstartup

# ■ bash を winpty 経由で起動#   ※ Windows ネイティブな対話型コマンド(Python 等の、interactive mode が mintty に対応していないもの)に対応exec winpty bash
#   ※ exec によりシェルプロセス自体を置換しているため、これ以降に書いた内容は反映されないことに注意

~/.bashrc
if [[$TERM_PROGRAM="mintty"]];then# ■ mintty 専用設定case`tty`in
        /dev/cons*)# winpty# winpty 経由だと $PWD が日本語を含む場合ウィンドウタイトルが文字化けする(mintty 3.2.0)問題に対処export PS1=`echo"$PS1"|sed"s~\\$PWD~\\\`echo \\$PWD | iconv -f utf-8 -t cp932 2>/dev/null\\\`~"`;;
        /dev/pty*)# (default);;esacfi# ■ 暗黙的にサブシェルに引き継がれない設定(alias・関数定義)# ※サブシェルでは、#   - profile系スクリプト(/etc/profile、/etc/profile.d/*、~/.bash_profile等)は実行されない#   - ログインシェルで定義された alias や関数は引き継がれない#   ことに注意shopt-q login_shell || {# サブシェル専用設定# ※必要に応じて /etc/profile や /etc/profile.d/* (aliases.sh等)で定義されている alias 等をコピーしておくalias ls='ls -F --color=auto --show-control-chars'alias ll='ls -l'}# ~/.bash_profile 経由/サブシェル共用設定alias ls='ls -aF --color=auto --show-control-chars'alias tree='tree -N'alias python2='py -2'alias python3='py -3'alias python='python3'alias pip2='python2 -m pip'alias pip3='python3 -m pip'alias pip='pip3'# ■ 非対話ログインで不要かつ対話ログインで使いたい設定(環境変数定義)export EDITOR=vim

その他の覚え書き等

Evaluate all user-specific Bash completion scripts (if any)(Git BASH 独自仕様?)
  • /etc/profile.d 下のファイルは通常はログインシェルからしか呼ばれないものだが、git-prompt.sh に限り、サブシェルからも呼び出される(/etc/bash.bashrc 経由)
  • ~/bash_completion.d/ というディレクトリを作成し、この下に拡張子 .bash の付いた任意の bash スクリプトを置いておくと、/etc/profile.d/git-prompt.sh 経由で呼び出される(結果的にはログインシェル/サブシェルの区別なく呼ばれることになる)

参考

winpty・mintty 関連

mseeeen.msen.jp

bash 関連ファイル(~/.bash_profile・~/.bashrc 等)の動作仕様について

blog.sgry.jp
なんとなくで設定しがちだった bash の ~/.bash_profile や ~/.bashrc といったファイルの動作仕様が分かりやすくまとまっていて非常に参考になった。

はてなブログの記事に更新日付を表示&古い記事に警告を出す試み

$
0
0

はてなブログが配信しているサイトマップの仕様が変わっていることに、今更ながら気が付きました
変化したのが2020/04/01からなので、何ヶ月気が付かなかったのか、という話ですが。
sitemap.xmlの中身を覗いてみたら、クエリで年月を指定することにより、指定月に作成した記事の更新日付を取得できるようです。

これを利用して、フッタなどに貼り付けることで

  • 個別記事に更新日付を表示
  • 更新日付が古い場合には、警告を表示

するようなスクリプトを試作してみました。

f:id:furyu-tei:20200818053148p:plain
はてなブログの記事に更新日付を入れてみる&古い記事には警告を表示する



更新日付の取得方法について

はてなブログの記事には作成日付は最初から入っており、例えば

var entry_date = newDate( document.querySelector( 'time[datetime][pubdate].updated' ).getAttribute( 'datetime' ) );

のようにすることで、簡単に取得することができます。
これを用いて記事が古いかどうかを判断して表示するスクリプトは以前から存在します。
sprint-life.hatenablog.com

しかし、実際には記事は更新されることもよくあり、その記事の情報が古いかどうかは更新日付を元に判断したいところです。

2020/04/01より前のサイトマップ仕様

2020/03/31まで、サイトマップの仕様は

/sitemap.xml?page=<ページ番号>

のような形式で、1ページ毎に作成日付の新しいものから順に100件ずつ、記事のURLと更新日付が含まれる仕様になっていました。
なお、当概仕様のサイトマップには現在でもアクセス可能です。
これだと、特定記事の更新日付を取得するためには、当該記事のURLが現れるまでひたすらページ番号を増やしてアクセスする必要があります。
上記の記事やコメント中でも、サイトマップから更新日を取得することは可能ではあるものの、記事と一致させることが手間なので実用的ではない旨書かれています。

このサイトマップを使った更新日付表示の実装例は
www.tsubasa-note.blog

等があるようです。
また、サイトマップの場合には何度もアクセスが発生してしまう問題を解消するため、AMP(更新日付が埋め込まれている)を利用した実装もあるようです。
psn.hatenablog.jp

2020/04/01 以降のサイトマップ仕様

2020/04/01から配信されるようになったサイトマップの仕様では、

/sitemap_periodical.xml?year=<作成年>&month=<作成月>

のようにすると、

<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"><url><loc>https://memo.furyutei.work/entry/20161015/1476495230</loc><lastmod>2016-12-06T09:08:18+09:00</lastmod></url><url><loc>https://memo.furyutei.work/entry/20161008/1475863694</loc><lastmod>2016-12-06T09:08:56+09:00</lastmod></url><url><loc>https://memo.furyutei.work/entry/20161008/1475860031</loc><lastmod>2017-11-14T07:08:24+09:00</lastmod></url><url><loc>https://memo.furyutei.work/entry/20161007/1475839249</loc><lastmod>2020-03-07T03:29:59+09:00</lastmod></url></urlset>

のように、指定した年月に作成した記事のURLと更新日の一覧を取得することが出来るようになっていました。
これならアクセスが1回だけで済むので、実用的だと思われます。

個別記事に更新日付を表示&古い記事に警告を表示するスクリプトとCSSのサンプル

注意事項
  • スクリプトをブログのフッタなどに貼り付ける場合、<script>~</script>で囲むのを忘れないこと
  • サンプルソースコードはGist上にあります。なお、残念ながら Gist 上のコードは外部スクリプトとしては読み込めません(Content-Type: text/plain; charset=utf-8 のため)
  • async/await とか使っているので、モダンブラウザじゃないと動きません(笑)
    それじゃ嫌だというかたはこちらの記事等を参考にして、新しいサイトマップ仕様に対応させてみてください

余談

記事の更新時刻が例えば

2017-11-14T07:08:24+09:00

という文字列で与えられたとき、閲覧者のタイムゾーンによらずに日本標準時の年月日で

2017-11-14

という文字列に変換するためにはどうするのがスマートなんですかね……?
いや、上記サンプル中ではT以降の文字を消す、という手抜き実装ですが……

また、同様に

2017-11-13T22:08:24Z

で与えられた場合には?

var modified_date = newDate( '2017-11-13T22:08:24Z' );
modified_date.setHours( modified_date.getHours()+9 );
var jst_date_string = modified_date.toISOString().replace( /T.*$/, '' );

のようにすれば一応できるけれど、正攻法ではないですね……。

Twitterのカユイところに手が届くブラウザ拡張/スクリプト

船を出すのなら九月…その船は今どこにふらふらと浮かんでいるのか?

$
0
0

九月というと反射的に、中島みゆきさんの「船を出すのなら九月」とか
アルバム「生きていてもいいですか」に収録に収録されています

生きていてもいいですか【リマスター(HQCD)】

生きていてもいいですか【リマスター(HQCD)】

シギサワカヤさんの「九月病」
九月病 上巻 (ジェッツコミックス)

九月病 上巻 (ジェッツコミックス)

九月病 下巻 (ジェッツコミックス)

九月病 下巻 (ジェッツコミックス)

とかを連想してしまう、業の深い(?)自分がいます。
いずれも名作ですので、体験したことのない方はぜひご体感ください。
なお、心身ともに良好なときに視聴することをおすすめします


船を出すのなら九月 [作詞・作曲:中島みゆき]

船を出すのなら九月 誰も見ていない星の九月
人を捨てるなら九月 人は皆 冬の仕度で夢中だ

あなたがいなくても 愛は愛は愛は
愛は まるで星のようにある

船を出すのなら九月 誰も皆 海を見飽きた頃の九月

夢をとばすなら九月 たくさんの愛がやせる九月
海へ逃げるなら九月 知らぬまに夜が誘いをのばしてる

あなたがいなくても 愛は愛は愛は
愛は どうせ砂のようにある

人を捨てるなら九月 誰も皆 冬を見ている夜の九月
船を出すのなら九月 誰も皆 海を見飽きた頃の九月

宙船(そらふね) [作詞・作曲:中島みゆき]

その船を漕いでゆけ おまえの手で漕いでゆけ
おまえが消えて喜ぶ者に おまえのオールをまかせるな

その船は今どこに ふらふらと浮かんでいるのか
その船は今どこで ボロボロで進んでいるのか
流されまいと逆らいながら
船は挑み 船は傷み
すべての水夫が恐れをなして逃げ去っても
その船を漕いでゆけ おまえの手で漕いでゆけ
おまえが消えて喜ぶ者に おまえのオールをまかせるな

その船は自らを宙船(そらふね)と 忘れているのか
その船は舞い上がるその時を 忘れているのか
地平の果て 水平の果て
そこが船の離陸地点
すべての港が灯りを消して黙り込んでも
その船を漕いでゆけ おまえの手で漕いでゆけ
おまえが消えて喜ぶ者に おまえのオールをまかせるな

何の試験の時間なんだ 何を裁く秤(はかり)なんだ
何を狙って付き合うんだ 何が船を動かすんだ
何の試験の時間なんだ 何を裁く秤なんだ
何を狙って付き合うんだ 何が船を動かすんだ
その船を漕いでゆけ おまえの手で漕いでゆけ
おまえが消えて喜ぶ者に おまえのオールをまかせるな
その船を漕いでゆけ おまえの手で漕いでゆけ
おまえが消えて喜ぶ者に おまえのオールをまかせるな

こちらはアルバム「ララバイSINGER」に収録されています

ララバイSINGER

ララバイSINGER

このブログにしては異色の記事ですが、せっかくはてなブログでJASRAC管理の歌詞を掲載できるようになったのに、そのことに気がついてからもそういえばまだ一度も利用したことなかったなとちょっと思ったので……。

関連

Amazon.co.jp のカユイところに手が届くブラウザ拡張/スクリプト

ちょっとだけカユイところに手が届くブラウザ拡張/スクリプト


エクセルで揮発性の数式を含むセルを抽出する試み

$
0
0

はじめに

エクセルのワークシートで使える関数の中には揮発性関数というものがあり、これらは再計算の度に再評価(実行)されてしまいます。

揮発性関数の中には OFFSETINDIRECTといった便利な関数も含まれているためについ使ってしまいがちですが、かといってこれらを多用していると動作が重くなる要因のひとつとなります。
場合によっては、他の関数に置き換える等の対処を考えたほうが良いかも知れません。
自動再計算を行わないという対処法もありますが、これはこれで何かと不便です。

そこで、調査用として、シート中の揮発性の数式を含む(再計算時に常に再評価されてしまう)セルを抽出する方法について考えてみました。

f:id:furyu-tei:20201105095343p:plain
サンプルマクロの実行結果例

なお、他の方々から知見を得るために、クイズ形式でツイートもしています。

もっとうまい方法をご存じの方、コメントやこのツイートへのリプライででも教えて下さいませ。

試し方

標準モジュールに下記のサンプルコードを貼り付けて、目的のシートをアクティブにした状態でマクロ(MarkVolatileCells)を実行すると、揮発性の数式を持つセルにメモが添付されます。

サンプルコード


解説

引数の値をそのまま返すような単純なユーザー定義関数(UDF)を作成した場合、その引数にセル参照を指定しておくと、再計算時には参照先が揮発性の場合にのみ当該 UDF が呼び出されることになります。

サンプルソースコードの MarkVolatileCells() では、この性質を利用して、

  1. 作業用に、対象シート(target_sheet)を複製
  2. 複製した作業用のシート(temp_sheet)中で数式を持つセル(=target_sheetでも同じアドレスのセルは数式を持つ)に対し、数式を target_sheet の同じアドレスのセルへの参照を引数としたUDF(ReferCellValue)に置換置換を行う前には自動計算状態(Application.Calculation = xlCalculationAutomatic)にして、全ての ReferCellValue が一度呼び出される(実行される)ようにしておく
  3. 手動計算状態に切り替え(Application.Calculation = xlCalculationManual)た後、コレクション(VolatileAddressCollection)を初期化する
  4. 強制的に再計算(temp_sheet.Calculate)を行うと、参照先が揮発性の場合にのみ ReferCellValue が呼び出されるため、このアドレスをコレクション(VolatileAddressCollection)に記録
  5. 記録されたアドレスに対応する target_sheet 中のセルにメモを添付

という処理を行っています。

注意事項

上記の手法は当方が思いつきで試してみたものであり、正しく揮発性の数式を持つセルが検出できるのかについての保証はありません。あくまで参考として考えて下さい。

また、数式が指定されているセルに対してしか使えないため、

  • 条件付き書式内で揮発性数式が使われている場合
  • リンクした図の場合

等のケースについては検出できません。

エクセルのVBAで正規表現のメソッド実行に時間がかかる現象と対策(仮)

$
0
0

エクセルの VBA で、正規表現(VBScript.RegExp)の .Excute メソッドを使っているプロジェクトにて、不自然に動作が重くなってしまう現象に遭遇しました。
Windows 10 Pro バージョン 2004 (OS ビルド 19041.630) 上で、Microsoft® Excel® for Microsoft 365 MSO (16.0.13328.20262) 32 ビットにて発生。

実は、以前にも同じ現象が発生していたのですが、そのときには Windows の再起動で発生しなくなったので放置していました。
しかし、今回の場合は Excel や Windows を再起動しても改善が見られなかったため、少し調べてみることにしました。




発生した状況(再現方法)

  1. 「Microsoft Excel マクロ有効ワークシート」を新規作成
  2. 標準モジュールを追加し、VBSCript.RegExp の Excute メソッドを使用しているこちらのプロジェクトのソースコードを貼付け
  3. サンプルツイートのテキスト(【】部分に隠し文あり)を選択してコピーし、A1セルに貼り付けたあと、B1セルに「=ZenDecode(A1)」のような数式を入力(画像1)
    なお、この段階では特に遅くは感じない
  4. 一度保存して閉じてから、再度開き、「セキュリティの警告」に対して [コンテンツの有効化] ボタンを押す(画像2)
f:id:furyu-tei:20201115142102p:plain
画像1. サンプル
f:id:furyu-tei:20201115142146p:plain
画像2.「セキュリティの警告 マクロが無効にされました。」ダイアログ
[コンテンツの有効化]を押した直後や、B1セルを再入力したり、A1&B1を別セルにコピーしたりすると、体感できるほどに不自然に動作が重くなってしまいました。

対策

ワークシートを作成直後には特に重くなかったのに、保存して閉じる→再度開く→[コンテンツの有効化] を実施後に重くなってしまう(その後はずっと重いまま)ことに気づいたので、セキュリティ関係の機能の問題ではないかとあたりをつけ、トラスト センターの「信頼できる場所」に、当該マクロ有効ワークシートの場所を追加してみました。
  1. リボンの「ファイル」メニューから、「オプション」→「トラスト センター」で [トラスト センターの設定 (T) ...] をクリック
  2. 「信頼できる場所」の [新しい場所の追加 (A) ...] で、当該ワークシートを置いてあるフォルダを指定する(必要に応じて、「□ この場所のサブフォルダーも信頼する (S)」にもチェックを入れておく)
その後、該当ワークシートで試してみると、軽快に動作するようになりました。

注意事項

  • 同様の環境であっても、現象が再現しない場合もあります
    自分のところでも、同じファイルを、別の PC 上で試しても(「信頼できる場所」に置いていないにも関わらず)特に重くなりませんでした。また、同一 PC 上であっても、ファイルの内容によっては(?)再現しない場合もあるようです。
  • 上記の対策は、マクロのセキュリティ関連の設定になるため、「信頼できる場所」に追加するフォルダについては慎重に検討するようにしてください。試して見る場合には自己責任でお願いします。
  • あくまで当方個人の環境での対策のため、同様の現象が発生していて対策通りの手順を踏んでも改善されない場合もあるかと思いますが、ご容赦願います。

【お知らせ】アマゾン注文履歴フィルタが突然使えなくなるかもしれません!!

$
0
0

多くの方にご利用いただいている拙作「アマゾン注文履歴フィルタ」

memo.furyutei.work

ですが、Amazon.co.jp様側のページ仕様の変更に伴い、残念ながら今後使えなくなる可能性が高いです。

現状、本拡張機能(アドオン)は、領収書ページのHTMLを用いて一括印刷やCSVダウンロード等の機能を実現しているのですが、領収書ページのフォーマットがHTMLからPDFに変わってしまったアカウントが存在するようです(2020/12下旬に確認)。今後はこの切り替えが実施されるユーザーの方が増えていくものと予想されます。

こうなると抜本的な改修が必要となってくるのですが、現状当方の所持するアカウントではまだ切り替えが行われておらず、また時間的な余裕もないことから、短期間での対応は困難です。
少なくとも、2020年分の確定申告の期間には本拡張機能は使用できないという前提で、各位対処されることをお勧めいたします。
大変ご不便をおかけしますが、ご容赦願います。

Web版TwitterからFleet画像/動画をダウンロードできるユーザースクリプト

$
0
0

スマホ用Twitterアプリに「Fleet(フリート)」がリリースされて早三ヶ月が経とうとしていますが、未だに使い道がよくわからない風柳です、ごきげんよう。

Web版TwitterではなかなかFleetが見られるようにならないので、こっそり(?)ダウンロードツールを作って公開していたのですが、現在もまだ見られないようなので、記事でも紹介しておきます。
スマホアプリ版みたいにリアルタイムで誰が投稿しているか表示されるわけでもなく、画像/動画を別タブで開いた際も誰が投稿したものかもわかりづらいので、使い勝手としてはイマイチですが……😅

インストール方法

ユーザースクリプトとして公開しています。
[このページを参考に](https://greasyfork.org/ja)、お使いのブラウザに Tampermonkey 等のユーザースクリプトマネージャーをインストールした状態で、
greasyfork.org
のページを開いて[スクリプトをインストール]ボタンを押し、フリートキャプチャーをインストールしてください。

使い方

フォローしている方のFleet画像/動画のダウンロード方法

[Twitterのホームタイムライン](https://twitter.com/home)を開くと、上部に[Fleets 💾]のようなボタンが表示されます。

f:id:furyu-tei:20210206123026p:plain
HOME画面上のボタン

これをクリックすると、フォローしている方が公開中のFleet画像/動画をまとめて(ZIPファイルで)ダウンロードできます。
また、[Alt]+クリックで、画像/動画を別タブでまとめて開くこともできます。
ブラウザのポップアップブロックにより別タブでうまく開けない場合は、ポップアップブロックをオフにするか、あきらめてください。

ユーザーが公開中のFleet画像/動画のダウンロード方法

ユーザーのプロフィールタイムラインを開くと、その方がFleetを公開中であれば、プロフィールアイコンの周りが水色になり、同時に[Fleets 💾]のようなボタンが表示されます。

f:id:furyu-tei:20210206123913p:plain
プロフィール上のボタン

これをクリックすると、その方が公開中のFleet画像/動画をまとめて(ZIPファイルで)ダウンロードできます。

f:id:furyu-tei:20210206123802p:plain
Zipファイルサンプル

こちらも、[Alt]+クリックで、画像/動画を別タブでまとめて開くこともできます。
注意書きも同上です。

おまけ

Fleet用自作テンプレートです。ご自由にお使いください。

f:id:furyu-tei:20210206124108p:plain
フリート用テンプレート.伝言板

Twitter で「.work」ドメインの記事を引用するとツイートが表示されなくなってしまう件

$
0
0

このブログは「memo.furyutei.work」のように、gTLDとして「.work」を使用しているわけですが。
Twitter にて「.work」ドメインの記事(URL)を引用してしまうと、状況によってはそのツイートが表示されないといった不具合が発生してしまう、というお話です(2021/02/11現在)。




不具合の内容

元ツイートが「.work」ドメインの記事を含む場合

「.work」ドメインの記事を引用してツイートした場合、そのツイートにリプライが付くと、元ツイートを開いたらリプライツイートも表示されます。
ここまではいいのですが、実は、

  • リプライツイート(およびリプライツリーで繋がったツイート)を開くと、(自分以外のユーザーからは)元のツイート(リプライ先・「.work」ドメインの記事を引用したもの)は見えず、「このツイートは表示できません。This Tweet is unavailable. )」状態となってしまう
    これ、自分で見る分には普通に表示されるため、誰かに指摘されたりしないと気が付かない罠

という不具合が発生します。

リプライツイートが「.work」ドメインの記事を含む場合

また、Twitter のツイートに対するリプライ中に「.work」ドメインの記事(URL)を引用してしまうと、

  • 元ツイートのユーザーには通知が行かない
  • (自分以外のユーザーが)元ツイートを表示しても、「.work」ドメインの記事を引用したリプライツイートは見えず、リプライ数としてもカウントされない
    この場合も、自分で見る分には普通に表示されているので気が付きにくい
  • 当該リプライツイートにさらにリプライが付いた場合、当該ツイートは「このツイートは表示できません。This Tweet is unavailable. )」状態となってしまう
    もちろん自分では普通に見える

という不具合が発生してしまいます。
なお、 (自分以外のユーザーであっても)当該リプライツイートを直接URLを指定して開けば見ることはできます。

自分のところだけではないらしい

最初、自分のところだけかと思いましたが、gTLD「.work」を使っているサイトを3か所ほど探して試してみたところ、いずれも同様の不具合が発生していたので、少なくとも「.work」に関しては普遍的に発生するのではないかと予想しています。
他の TLD で同様の不具合が発生するかどうかまでは調べられていません。
「.work」は新gTLDと呼ばれる比較的歴史の浅いものらしいですが、そういうのが関係していたりするのですかね?

回避方法

現状、「.work」ドメインの URL は引用しないようにするしか……。
このブログの場合、もともとはてなブログなので「furyu.hatenablog.com」の方の URL を使って引用する、という手はないではないです(面倒くさいけれど……)。

Twitter さんに不具合報告はしているのだけれど


2020/12/03・12/09、2021/02/09 と、これまで都合3回この不具合に関して報告しているのだけれど、なしのつぶて……(2021/02/11現在)。
Viewing all 92 articles
Browse latest View live