読者です 読者をやめる 読者になる 読者になる

Coding Memos

try {coding} catch {questions}

sassの連想配列とfont-awesomeのUnicodeの記述

ちょっとハマったので、メモとして。

<ul>
  <li class="list-red"></li>
  <li class="list-blue"></li>
  <li class="list-yellow"></li>
</ul>

上記のようなリストにおいて、個別にアイコンを入れたい場合、たとえば、wordpressなんかだと、テンプレートタグで 投稿ページや固定ページの一覧を吐出させることがある。

html要素にアイコン要素をかき入れられる場合は、問題ないのだが、 テンプレートタグだと、ループの制御に関わったりするので面倒。

そこで、cssの疑似要素::beforeや::afterによってアイコンを書き入れたい場合がある

//sassの連想配列
$list_items:(
  red:f015,
  blue:f232,
  yellow:115
);

として連想配列をつくっておく。redなどがkeyで、f015などはfont-awesomeのunicodeだが、valueという組み合わせである。

そこで、以下のように、sassで配列ループさせる

//sassの連想配列
$list_items:(
  red:f015,
  blue:f232,
  yellow:115
);

@each $key, $value in $list_items {
  .list-#{$key} {
   position: relative;
    $::before {
       position: absolute;
       content: "#{$value}";
       font-family: FontAwesome;
  //他のプロパティは略
     }
  }
}

さて、これでは実は上手くいかない。

contentにうまく$valueの各値が入らず、escapeされてしまうため、アイコンが表示できずTofuが出てしまう。 なにやら、ASCiiコードが含まれる場合に、sassコンパイルすると文字化けしてしまうとか?

qiita.com

というわけで、sassのfunction機能を使ってやる。

sass functionで何ができるかは、いかの公式ドキュメントをみてほしい。

Module: Sass::Script::Functions — Sass Documentation

//sassの連想配列
$list_items:(
  red:f015,
  blue:f232,
  yellow:115
);



@function unicode($str) {
  @return unquote("\"")+unquote(str-insert($str, "\\", 1))+unquote("\"")
}

//unicode(f015) -> "\f015" とでるようになる関数

@each $key, $value in $list_items {
  .list-#{$key} {
   position: relative;
    $::before {
       position: absolute;
       content: unicode($value); //content: "\f015"; などとコンパイルされる
       font-family: FontAwesome;
  //他のプロパティは略
     }
  }
}

とすることで、おもったとおりにコンパイルされる。

ちなみに、font-awesomeのunicodeの調べかたとしては、アイコン各ページの下に書かれている。

fontawesome.io

f:id:codingmemos:20161027161351p:plain

Google Adsenseを記事内にPHPで入れる手法

昨日lazyloadに対応したsrcsetのいじり方を書いたついで、AdsenseWordpress記事内に入れる方法を書いてみようと思う。

収益化スペシャリストによると、リード文の下に記事内広告を入れるとさらに収益化が進むということで

<p>(リード文)</p>
<h2>
 初めのh2タグ
</h2>

という感じで記事フォーマットをルール化したとして、 初めのh2タグの上にAdsense広告入れる場合を考える。

スニペットから

これだけでもまあ使えると思う。もちろん、data-ad-clientなどはご自身のものを入れてもらうとして。

function addAdsense($content){
    $pos = strpos($content, '<h2>');
    $adsense = '<div>';
    $adsense .= '<ins class="adsbygoogle" data-ad-client="ca-pub-xxx" data-ad-slot="xxx"></ins><script>(adsbygoogle = window.adsbygoogle || []).push({});</script>';
    $adsense .= '</div>';
    $content = substr_replace($content, $adsense, $pos, 0);
    return $content;
}

add_filter('the_content', 'addAdsense' , 1, 10);

簡単な解説

the_contentは記事内容を呼び出すフック。パラメータとしてもつのは$contentのみ。 で。まず、

strpos($content, <h2>) で記事内に出てくる初めてのh2タグの場所を見つけている。これを$posとして保持。 次に、このh2タグのまえに挿入したいAdsenseタグを$adsenseとして持っておく。

substr_replace()はシングルバイトの文字列位置めがけて、文字列を挿入できる関数。 なので、解釈すると、$contentの$pos文字目に$adsenseを挿入してってこと。

これで、adsenseタグは入る。

まぁjsでクライアント側から入れてもいいとはおもうけど、できればjsの負荷はなるべく減らしたいってことで。

wordpressにおけるレスポンシブイメージに対するlazyload対策

wordpressアイキャッチを出すときに、lazyloadしたいっていう話。

<img src="hoge.jpg" alt="" >

は慣れ親しんだ記述だが、HTML5.1となると、レスポンシブイメージの書き方が、標準装備となる。

<img srcset="" sizes="" alt="">

srcsetでは、画像が複数リストとして記述される。sizesはどの範囲のviewportで、どのサイズの画像をつかうかということを示す。

まぁこの辺の解説は、普段からHTML CSSを書いている人にとっては、理解できることだろうから、詳細には立ち入らない。

今回はsrcsetも踏襲した上で、lazyloadつかおうということが主題である。

lazyloadによって、ユーザーの体感速度をあげる

ページ内の下の方の画像は、ユーザーがスクロールしたらロードされればいい。

lazyloadってのはそういうものだろうし。

つかってるlazyloadライブラリは、lazySizesというもの。

github.com

デモはこっち。

lazysizes - the ultimate lazyloader for responsive images, iframes and widget

Lazy load Plugin for jQueryじゃないの?

Lazy Load Plugin for jQuery

そう、これは前に使っていたが、lazysizesがさらにいいのは、jqueryを使わなくてもいいということ。

これによって、jQuery $ is not function Reference Error なんて依存関係の必要なものではなくなるし、軽いらしかった。

使いかた

簡単

  1. 外部ソースファイルをよみこむ
  2. lazyloadしたいimgにlazyloadというclassをつける。
  3. srcsetに入れたいurlリストをはじめはdata-srcsetにいれる
  4. sizesもdata-sizesとしてデータ持っておく

たったこれだけ。

jsを書かなくても使える。

もちろんオプションとか設定はある。jquery.lazyloadのときは、画像を出す演出がjqueryによってfadeInなどしていたが、こちらでは、cssによって、opacityとtransitionなどでふわっと画像を出したりすることができる。

Wordpressは4.4からすでにsrcset sizesを導入している

たぶん今後はこの書き方を要求されることが多くなりそう。今回は論を踏み入れないけど

<picture>
  <source 
    media="(min-width: 650px)"
    srcset="images/kitten-stretching.png">
  <source 
    media="(min-width: 465px)"
    srcset="images/kitten-sitting.png">
  <img 
    src="images/kitten-curled.png" 
    alt="a cute kitten">
</picture>

という書き方もある。

レスポンシブイメージのネイティブサポート - HTML5 Rocks

画像の対応の仕方は、Web屋はキャッチアップしておかないとまずそう。

前置きはさておき、今回は、アイキャッチを出すときに、lazyloadで画像読み込みをしたかった。 なので、Wordpressのフィルターフックを利用して以下のように記述した。

function thumbnailForLazyload($html, $post_id, $post_image_id)
{
    $html = '<a href="' . get_permalink( $post_id )  . '" title="' . esc_attr( get_the_title( $post_id ) ) . '" >';
    $html .= '<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" data-srcset="' .wp_get_attachment_image_srcset($post_image_id).'"';
    $html .= 'data-sizes="'.wp_get_attachment_image_sizes($post_image_id) . '" class="lazyload wp-post-image">';
    return $html;
}

add_filter('post_thumbnail_html', 'thumbnailForLazyload', 3, 10);

post_thumbnail_html はテンプレートタグのthe_post_thumbnail()を使うときのフィルターフック。

ここに、lazyloadというクラスや、data-srcset, data-sizeを書き入れて、利用する感じにした。

はじめから、srcsetに画像URLがはいってしまうと、lazyloadにならないため、data-srcsetにしてある。(この使い方自体は、lazysizesのもともとの使いかた)

srcが書き入れてあるのは、1px x 1pxの透過イメージ。ここにlow qualityな画像を入れて、レガシーブラウザ(srcsetに対応していないブラウザ)に対してはsrcの画像を読み込ませるということもできる。

その他関数など

thumbnailForLazyload($html, $post_id, $post_image_id)は三つの引数をとる。$html,$post_id ,$post_image_idはもともと、post_thumbnail_htmlで用意された引数なので、フィルターフックで使う場合は、そのまま引数を渡せばいいだけ。

post_thumbnail_html | Hook | WordPress Developer Resources

wp_get_attachment_image_sizes(), wp_get_attachment_image_srcset()は引数に、$post_image_idつまり画像のidを渡すことで、srcsetとsizesを吐き出してくれるテンプレートタグになっている。

wp_get_attachment_image_sizes() | Function | WordPress Developer Resources

wp_get_attachment_image_srcset() | Function | WordPress Developer Resources

the_post_thumbnail()のlazyload対応

上記までで、アイキャッチを吐き出す際のlazyload対応ができたはず。

ほかにも、記事内の画像をlazyloadさせるときは、

function contentImgLazyload(引数何個か) {
    //処理
}

add_filter('the_content', 'contentImgLazyload', n(引数の個数), m(この処理の優先度));

という感じで書けば行けそう。

懸念点

the_post_thumbnail()アイキャッチを吐き出させるときには、第一選択といってもいいテンプレートタグなので、このやり方がいつでも正しいかは微妙なところ。

というのも、srcsetなど使いたくないアイキャッチ(ってどんな状況かおもいつかないけど)を呼び出すときなど、柔軟性に欠ける書き方をしているわけなので、もしかしたら、もう少しいい方法があるかもしれない。

もっといい方法をご存知でしたら教えてください〜。

Laravel-Breadcrumbsと、Laravel-sitemap

Laravel-Breadcrumbsを導入

Official Documentation

Laravel Frameworkを使っていて、パンくずリストを入れたいなってことで、Laravel-breadcrumbsを使った時のメモ。

基本的には、official documentを読めばなんとかなる。分かりやすく書かれているので、英語がアレでも読めます。

まぁ英語読みたくない人は、ざっくり下記を参考にしていただければ。

app/Http/breadcrumbs.php を新たに作った。

Breadcrumbs::register('home', function($breadcrumbs)
{
    $breadcrumbs->push('ホーム', action('HomeController@index'));
});

registerメソッドの中の、'home'はviewで呼び出す時に、使う名前。

{!! Breadcrumbs::render('home') !!}

でViewに呼び出せる。

styleはbootstrapがデフォルトっぽい。

親ページを呼び出すときは、

//parentをすでにregister済みだとして
Breadcrumbs::register('child', function($breadcrumbs){
    $breadcrumbs->parent('parent');
    $breadcrumbs->push('child', action('ChildController@index'));
});

などとして、

{!! Breadcrumbs::render('child') !!}

で呼び出せば、 parent / child のように表示される(bootstrap styleの場合)

SEO的にもリンクが増えるので、Laravel使ってる人でパンくずリスト入れてみようって思ってる人は導入を考えてもいいかもです。

Laravel-Sitemap

他にも、Sitemapも導入したけど、これも使いやすかった。 Laravel-sitemap

これは、app/Http/routes.phpにsitemapとして登録するurlを記述する感じですね。wordpressとかだとプラグインが山ほどあるんですけど、Webアプリを自作した場合にsitemapちょろっと書いておくといいかなと言うことで、利用した。

これも、使い方は本家に任せるとして、使用感としては、まぁ普通に悩むこともなく使える感じでした。

wordpressのOGP設定

最近あるサイトのOGP設定に詰まってたので、ちょっと見直してた。

Facebookで意図した通りの画像が取れないっていう話。 (Twitterではうまくいくんだが・・・。)

アイキャッチをOGPとして設定して、Jetpack入れてるので、公開した時にTwitterにもFBにも パブリサイズされるという感じの運用。

ひとまず、JetPackのCDNであるPhotonをオフにしてる。あとは、Jetpackが meta og設定を書き出すのは無効にして、headの中に自分でコード書いた。 実際のコードは探せば結構出てくるので、そちらを参照して下さい。

うんーこの設定でうまくいくと良いけど。。。

Atom使いのメモ(矩型選択)

Atom Editor普段使ってるんですけど、矩型選択したいのに、Mission Controlとコンフリクトしてできないっていう。

Mac Userにはあるあるでしょうかね。

Atomがデフォルトで用意してる矩型選択のショートカットは

ctrl + shift + up (down)

なので、まぁMission Controlなんて普段使うとき4本指スワイプで済ましてるし、なんだったらF3でもできるし。

ということで、PreferenceからMissionControlのCtrl + Upなどのショートカット切った。

これで、矩型選択がPackageに頼らずできるようになりますね。

ちなみに矩型選択は(くけいせんたく)と読みます。たまに間違ってる読んでる人もいますので、これを機に。

D言語に入門してみた

掲題の通り。

dmd-2.07系が最新なんですが、日本語訳だと、2.06系になってる。私はMacユーザなのでHomebrewでdmdインストールできないかなと思ってやってみました。

editorはvisual studio codeを使って、プラグインのcode-dを使う。 code-dにはworkplace-dが必要で、workplace-dにはdubというD言語ビルドツールを使う。 という感じ。

brew install dmd

dmdが入る。コンパイラ自体は他に二つあるけど、dmdは、まぁ一応公式っぽいコンパイラっていう位置付けなのかな。

で、2.06系のライブラリはphobosディレクトリにあって、object.dはimportディレクトリにある。 2.07だと、object.dはdmdディレクトリにあって、ライブラリは、dmd/stdにある。

; dmd.conf file for dmd
; Names enclosed by %% are searched for in the existing environment
; and inserted. The special name %@P% is replaced with the path
; to this file.
[Environment]

DFLAGS=-I%@P%/../src/phobos -I%@P%/../src/druntime/import

公式にもこうやって書いてあるんだけど、どこにあんのかなーって2.06と2.07を見比べてたらあったので、dmd.confに書くDFLAGSのパス設定は、2.07だとちょっと注意したほうがいいですね。

SqaleにRails Appをデプロイした話

なぜか躓きまくりました。

デプロイが完了しました=> 503エラー jscompress => uglifierが動きません

などなど、意味がわからなかった。

一つずつ対処して、ExecJS環境を入れてみたり、Gemsを確認したりとわからなかった。

結局のところ原因の特定まではできなかったけど、おそらくapp/の中にvendor/bundleが入ってたり、binがルートディレクトリに入ってたりと、ぐちゃぐちゃな開発環境だったこともあって、パスの優先がおかしかったんじゃないかな。

サンプルアプリをSqaleが出してくれてるので、ディレクトリ構成を見直してみて、ここは削っても大丈夫だなってところを 削除していったらなんとか動いてくれた。

気づいた点としては、bundlerでinstallしたものを複数持ってちゃいけないってことなんだけど、 もうちょいRailsみたいなフレームワーク使ってるとそこまでパスを意識しなくてもなんとなかってしまうってのは、 便利な反面、トラブルの原因を覆い隠しかねないな、と。

まぁでも、つまずいた分次はすんなりできると思うので、いい経験だったかな。

phpmyadminでcollateの影響でログインできなかった問題

とつぶやいたんですが、とはいえ、何かないかなと調べところ

php - phpmysql error - #1273 - #1273 - Unknown collation: 'utf8mb4_general_ci' - Stack Overflow

stackoverflowでこんな質問があったので、バーっと見てみると、そもそもMAMPphpにパスを通していたり、現在使ってる環境がvagrant-centosの感じでしたので、どこのファイルいじればいいかなと、面倒でした。

で、解決策としては、上記のstackoverflowでversionについて書かれてたので、ひとまずこれならそんなにいじらなくていいしこれでやってみようと思ったら解決できました。

www.tam-tam.co.jp

vagrantないのmysqlをアップデートする必要がありそうだったので、この記事を参考に(というかそのまま)やったらうまくいきました。

Git pushでエラーが出たので調べた (error Device not configured)

Atomでgit controlするときに、赤い文字で、エラーが出てたので、なんだろうと思って調べてきました。

どうやら、クローンするときに、httpsのURLからクローンすると、Could not read UsernameとかDevice not Configuredって エラーメッセージが出てしまう。

そこで、httpsからじゃなくて、sshからクローンしたことにする?という上書きをすることで、これを回避すると pushが通った。

以下公式の案内

Changing a remote's URL - User Documentation

Switching remote URLs from HTTPS to SSH 

という見出しのところの手順に沿って、

ターミナルで、そのプロジェクトディレクトリに移動して、

$ git remote -v

とうって、そのリポジトリがリモートだとユーザー名が何で、リポジトリ名が何かを確認

$ git remote set-url origin git@github.com:USERNAME/OTHERREPOSITORY.git

を叩けば、sshに切りかわるらしいので、これでpushが通るようになった。

初心者向けだと思うけど、いちいち探すのも面倒だろうし、メモとして公開しました。