はてなブログにpdfをobjectタグで埋め込む

原三溪展@横浜美術館の出品リスト(の魚拓)を埋め込む。

<object type="application/pdf" width="600" height="800" data="PDF_URL"></object>

iOS 内蔵ブラウザ( Safari ベース)ではプレビューとしてしか表示されない。のでページがめくれないのが残念。

.oO(ところで。HTML5では(4にあったような)空タグを避ける <ほにゃらら /> 的な記法は無くなったのかねえ)

参考

ffmpegやffprobeの出力にコピーライトやライブラリ情報を含ませない

-hide_banner オプションを追加すればおk。

$ ffmpeg -hide_banner ...
$ ffprobe -hide_banner ...

典拠

-hide_banner

Suppress printing banner.

All FFmpeg tools will normally show a copyright notice, build options and library versions. This option can be used to suppress printing this information.

aliasしておけばいいんじゃね

~/.bashrc に書いておきましょう。私は ffprobe にだけ設定しました。

alias ffmpeg='ffmpeg -hide_banner'
alias ffprobe='ffprobe -hide_banner'

Rubyで末尾に=が付くメソッドは「属性参照」と呼ぶらしい(英語だとAssignment Methods)

のコメントを書いたときに Ruby のリファレンスマニュアルを見直していました。Ruby 的にはどうやら「属性参照」と呼ぶらしいです(仮称のようにも感じますが)。ちなみに英語マニュアルだと Assignment Methods (代入メソッド)でした1

代入

例:

foo.bar = baz

文法:

式`.'識別子 '=' 式

(中略)

属性参照

式1 `.' 識別子 '=' 式2

式 1 を評価して得られるオブジェクトに対して、 識別子= というメソッドを、式 2 を引数にして呼び出します。

例:

class C
  def foo
    @foo
  end
  def foo=( v )
    @foo = v
  end
end
c = C.new
c.foo = 5   # c.foo=( 5 ) のように変換される
p c.foo     # => 5

属性は Module#attr を使って同じように定義できます。

例:

class C
  attr :foo, true
end
c = C.new
c.foo = 5   # c.foo=( 5 ) のように変換される
p c.foo     # => 5

「気になる展覧会」記事の表部分に使ったJavaScriptのメモ

ブログ本館では、3か月毎に以下のような展覧会リストを(自分のために)作っています。

このブログで次のようなことが出来るように JavaScript を書いてみました。

  • 展覧会期間が過ぎた行は非表示にする。
  • 展覧会開始4週間(28日)前及び12週間(96日)前の行は表示を薄くする。
  • 開催中の展覧会の期間部分をボールド且つ背景色をグレーに。
  • 展覧会開始後1週間及び終了前1週間は展覧会名の色を変更して目立たせる。

いままで書いていたはてなダイアリーでは JS が使えなかったので、やりたくても出来なかったのです。

JS を一から書いたのは初めてに近いので、下手くそなのは見逃してください。

const trs = document.querySelectorAll('table > tbody > tr');
const re = /^([\d\/]+)-([\d\/]+)/;
const yyyy = "2019" // 該当する記事の年に変更する
const now = new Date();
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate()); // 当日真夜中
for (let i=1; i < trs.length; i++) { // i=0 は項目名なので排除
  let tr = trs[i]
  let titleElem = tr.childNodes[1];
  let scheduleElem = tr.childNodes[3];
  let text = scheduleElem.innerText;
  let dates = text.match(re); // dates[1]が期間開始日、dates[2]が期間終了日
  
  // 終了日関係
  let endDateArray = dates[2].split("/");
  let endDate;
  if (endDateArray.length === 2) {
    endDate = new Date(yyyy + "/" + endDateArray.join("/"));
  } else {
    endDate = new Date(endDateArray.join("/"));
  }
  
  let endDateCountFromToday = (endDate - today)/86400/1000
  // 展覧会終了日を過ぎていたら表示しない(visibility:collapse;)
  if (endDateCountFromToday < 0) {
    tr.setAttribute('style', 'display:none;');
    continue;
  } else if (endDateCountFromToday < 7) {
    titleElem.setAttribute('style', 'color:#39f;'); // 終了日7日以内ならばタイトルtitleElemを青色に
  }
  
  // 開始日関係
  let startDateArray = dates[1].split("/");
  let startDate;
  if (startDateArray.length === 2) {
    startDate = new Date(yyyy + "/" + startDateArray.join("/"));
  } else {
    startDate = new Date(startDateArray.join("/"));
  }
  
  let startDateCountFromToday = (startDate - today)/86400/1000
  // 展覧会開始日が96日前よりも前だったらopacityをかなり小さくする
  if (startDateCountFromToday > 96) {
    tr.setAttribute('style', 'opacity:0.25;');
    continue;
  }
  // 展覧会開始日が28日前よりも前だったらopacityを小さくする
  if (startDateCountFromToday > 28) {
    tr.setAttribute('style', 'opacity:0.6;');
    continue;
  }
  // 展覧会開始日を過ぎていたら日程部分scheduleElemをボールドに
  if (startDateCountFromToday <= 0) {
    scheduleElem.setAttribute('style', 'background:#eee;font-weight:bold;');
  // 展覧会開始日を過ぎて7日以内ならばタイトルtitleElemを赤色に
    if (startDateCountFromToday > -7 && endDateCountFromToday >= 7) {
      titleElem.setAttribute('style', 'color:#f63;');
    }
    continue;
  }
  // 展覧会開始前3日以内だったらタイトルtitleElemを赤茶色に
  if (startDateCountFromToday <= 3) {
    titleElem.setAttribute('style', 'color:#c42;');
  }
}

もちろんこの JavaScript<script> タグに挟んで記事末尾に入れておくわけです。

参考:HTMLのテーブルの要素を消したり薄くしたりするCSSは(Safari除く) - 別館 子子子子子子(ねこのここねこ)はてブロ部

備忘録なので、誰の参考にもならなくてもいいのです(イイワケ

DRY じゃない部分をそのうち関数にしてみたりしよう(ひとりごと

HTMLのテーブルの要素を消したり薄くしたりするCSSは(Safari除く)

テーブルの要素を消して詰めるには

世間的には要素を非表示にするときに「display: none;visibility: hidden;」を使うようですね(例:【CSS】非表示にするならどっち?display:noneとvisibility:hiddenの違い | BeGeek)。が、テーブルの行であれば visibility: collapse; というのがかなり使えるようです。原理的にはコストがかからないようなので速いのではないでしょうか。

2019/2/25夜追記

残念なことに Safari1 では visibility: collapse;visibility: hidden; と同じになってしまい、行の表示が詰められませんでしたorz

collapse
  • <table> の行、列、列グループ、行グループでは、行や列が不可視になり、 (表の列や行に display: none が適用された場合のように) 占めていた領域も除去されます。しかし、他の行や列の寸法は、不可視になった行や列のセルが存在するときのように計算されます。この値は表全体の幅や高さを強制的に再計算することなく、すばやく行や列を不可視にすることができます
  • その他の要素では、 collapsehidden と同じと扱われます。

visibility - CSS: カスケーディングスタイルシート | MDN(下線は引用者追加)

上にも書きましたが、いちおう再度書きます。行要素 <tr> を非表示にするときにコストが低そうですが、他の要素では特に意味が無さそうです。

サンプルをこちらに載せています。

要素を薄く表示するには

文字も背景色も普段より薄く表示してみたいなあ、と思ったときにいちいち文字と背景色の値を変更するのは面倒。ということでまとめて薄く表示させるのは opacity プロパティを使います。

CSSopacity プロパティは、要素の透明度、または要素の裏にあるコンテンツが見える度合いを設定します。

opacity - CSS: カスケーディングスタイルシート | MDN

引数は0以上1以下です。つまり opacity: 1; とか opacity: 0.6; などのように書きます。

サンプルをこちらに載せています。

テーブルの要素を消す例

サンプルとして2018年度気になる展覧会その4(冬編) - 子子子子子子(ねこのここねこ)はてブロ部のテーブルを使います。なおブラウザは「Chrome バージョン: 71.0.3578.98(Official Build) (64 ビット)」です。

行要素 <tr> を非表示にする場合

王羲之書法の残影―唐時代への道程―」の行を取り扱います。

  • オリジナル

f:id:riocampos:20190225160839p:plain:w500

  • display: none;

指定した行が詰められています。完全に消えてしまって、位置表示もされませんね。

f:id:riocampos:20190225160901p:plain:w500

  • visibility: hidden;

行が存在した場所が空白として空きます。

f:id:riocampos:20190225160955p:plain:w500 f:id:riocampos:20190225161003p:plain:w500

  • visibility: collapse;

display:none; のように行が詰められていますが、存在した位置は表示されます。

f:id:riocampos:20190225161013p:plain:w500

単一要素 <td> を非表示にする場合

  • オリジナル

f:id:riocampos:20190225165728p:plain:w500

  • display: none;

指定した要素が消え、右にあった要素が左へ詰められています。完全に消えてしまって、位置表示もされませんね。

f:id:riocampos:20190225170503p:plain:w500

  • visibility: hidden;

指定した要素が表示されません。この例では下の枠線が消えてしまい、真下の要素が縦に伸びたように見えます。

f:id:riocampos:20190225170602p:plain:w500 f:id:riocampos:20190225165815p:plain:w500

  • visibility: collapse;

指定した要素が表示されません。visibility:hidden; と同じ表示になっています。

f:id:riocampos:20190225170231p:plain:w500 f:id:riocampos:20190225170210p:plain:w500

行要素 <tr> を薄く表示する例

やはり「王羲之書法の残影―唐時代への道程―」の行を取り扱います。

  • opacity: 1;

オリジナルと同じです。

f:id:riocampos:20190225172732p:plain:w500

  • opacity: 0.5;

半分の濃度。わりと薄くなります。

f:id:riocampos:20190225172750p:plain:w500

  • opacity: 0.1;

かなり読みづらいです。

f:id:riocampos:20190225172806p:plain:w500


  1. macOSSafari バージョン12.0.3 (12606.4.5.3.1) 及び iOSSafariiOS 12.1.4)にて確認

はてなブログにおける脚注メモ(Markdown方式)

Markdownの脚注記法に対応しました

はてなブログの記事編集画面で利用できるMarkdownモードで、Makrndownの脚注記法に対応しました。

 :

今回サポートした脚注は、PHP Markdown Extra由来の記法です。

はてな記法Markdownの脚注に互換性はなく、それぞれ個別にフォーマットされます。


Footnotes

Footnotes work mostly like reference-style links. A footnote is made of two things: a marker in the text that will become a superscript number; a footnote definition that will be placed in a list of footnotes at the end of the document.

いままでのはてなダイアリー由来の脚注*1Markdown 方式の脚注1とは残念ながら全く別個なのよね。書く側が統一しなきゃいけないので、なんだかなあと思う。


  1. こっちがMarkdown方式の脚注

*1:こっちがはてなダイアリー由来の脚注

はてなブログでブログ外リンクを別ウィンドウ/タブで開くように(JS解説付き)

ポイント

はてなブログで全てのリンクを別ウィンドウで開くならば <base target="_blank"> を設定しておけば済むのだけど、しかしこの状況でははてなブログ内のリンクまで別ウィンドウで開いてしまう。これはウザい。ってことで先人の知恵を借りた。けど若干のチューニングをしたのでメモっておく。

どうするの?

はてなブログの「設定>デザイン>カスタマイズ>ヘッダ」の「タイトル下」に HTML を書く欄があるので、そこに

<script>window.addEventListener("DOMContentLoaded",()=>document.querySelectorAll("a[href^='http']:not([href*='"+location.hostname+"'])").forEach(anchor=>anchor.setAttribute('target','_blank');));</script>

をコピペして「変更を保存する」ボタンを押して保存。これでおk。

スクリプトを読みやすくして解釈していく

<script>
window.addEventListener("DOMContentLoaded", () => {
  document.querySelectorAll("a[href^='http']:not([href*='" + location.hostname + "'])").forEach( (anchor) => {
    anchor.setAttribute('target', '_blank');
  })
});
</script>

1. document.querySelectorAll を解釈

document.querySelectorAll の引数は CSS セレクタで指定します。その中身である

"a[href^='http']:not([href*='" + location.hostname + "'])"

を解釈していきましょう。

まず a[href^='http'] から…との記事を書いていたのですが、先に location.hostname から。location.hostname は「現在ページURLのホスト名」の文字列です(参考:location.hostname-JavaScriptリファレンス)。ここでは本ブログのホスト名 riocampos-tech.hatenablog.com になります。次に、その前後をみると '" + location.hostname + "' とあります。シングルクオートとダブルクオートとが並んでいて読みづらい上、なぜシングルクオートとダブルクオートとが並んでいるのか?と悩んでしまいます。結論から言ってしまうと、+ location.hostname の前のダブルクオートは冒頭 a から続く文字列を閉じるものです。CSS セレクタは当然ながら文字列なので、文字列の中にさらに文字列であるURLを引用するにはシングルクオートを使う必要があります。しかし文字列の中に引用を入れるのは従来の JavaScript では不可能だった1ので、シングルクオートとダブルクオートとを並べることになるわけです。ややこしいので、先に location.hostname の部分を文字列にしましょう。すると[href*='riocampos-tech.hatenablog.com'] という文字列になります。CSS セレクタ全体を見直してみると

"a[href^='http']:not([href*='riocampos-tech.hatenablog.com'])"

となりました。では改めて解釈していきましょう。

まず a[href^='http'] は「a 要素のうち href 属性の値が文字列 http から始まる要素」という意味です(参考:E[foo^="bar"]-CSS3リファレンス)。

次に :not(〜) は「引数(〜)に該当しない要素」なので a[href^='http']:not(〜) は「a 要素のうち href 属性の値が文字列 http から始まり、且つ引数(〜)に該当しない要素」という意味になります2(参考:E:not(s)-CSS3リファレンス)。で、引数の部分は [href*='riocampos-tech.hatenablog.com'] となっています。ここは「href 属性の値が文字列 riocampos-tech.hatenablog.com を含む要素」という意味です(参考:E[foo*="bar"]-CSS3リファレンス)。

まとめると「a 要素のうち href 属性の値が文字列 http から始まり、且つhref 属性の値が文字列 riocampos-tech.hatenablog.com含まない要素」が document.querySelectorAll で選び出されることが分かります。

2. forEach 以降を解釈

(いずれ書きます)

先人の情報

この記事の内容は、基本的には一つ目のリンク先のままなのだけど、空白や改行を削除したり、jQuery のリンク先をはてな内にしたり、<script>タグの表現を変更したり jQuery から ES5 へ変更したり、ヘッダじゃなくフッタへの設定に変更したり、 function を Fat arrowにしたりしてます。

補足

じつは Document.querySelectorAll() の返値 NodeListNodeList.forEach() を使えなかったのですよ。最近のブラウザは使えるようになったようなので、それで使ってます。古いブラウザ対応は無視w (参考:NodeList.prototype.forEach() - Web APIs | MDN

はてなブログスマホビューのとき

でもね。iPhoneスマホビューで見たときには別タブで開いてくれないのです…なんでなの。 jQuery$(document).ready なのがスマホだとダメなときがあるという話を読んで「これは jQuery を止めちゃおう」と思って ES5 に書き換えたのにな。 HTML 読み込みなどの設定はスマホ用サイトだと別設定になっているし、はてなブログ PRO じゃないとスマホ用の HTML を書けないということに気付きました…うーむ。2年まとめ払いでも月額600円だから、はてなダイアリープラスの価格より大幅値上げに感じてしまうのよね…。 まあそれぞれのブログの末尾に

<script>document.querySelectorAll("a[href^='http']:not([href*='"+location.hostname+"'])").forEach(anchor=>anchor.setAttribute('target','_blank'))</script>

って毎回追記しておいてもいいのだけどね。面倒だけど3

なお、ブログ末尾に上記のスクリプトを追記するのであれば、はてなブログの設定のスクリプト

<script>window.addEventListener("DOMContentLoaded",()=>document.querySelectorAll("a[href^='http']:not([href*='"+location.hostname+"'])").forEach(anchor=>{if(anchor.getAttribute('target')!=='_blank')return;anchor.setAttribute('target','_blank');}));</script>

のように target="_blank" がある場合にはスクリプトを実行しないようにしておいたほうがいいかなと思います。


  1. いまはテンプレートリテラル``を使えば読みやすく書ける。今回の場合だと`a[href^='http']:not([href*='${location.hostname}'])`

  2. セレクタを続けて書くとandになると思われます。

  3. セコイねw