Text
PostCSSでCSSを変換する
1年ほど前に作った開発環境のテンプレートのようなものを最近使う機会があったのだけど、いざ使ってみようとモジュールをインストールしたらgulp-sassが動作しなかった。
どうもバージョンが古いせいだったようなのだけど、自分も他の人もSCSSのすべての機能を使いこなしているわけではない(というか、ほとんどネストくらいしか使っていない)ので、node-sassと違ってバイナリをコンパイルする必要がないPostCSSを使ったほうが良いのではないかと思って使ってみることにした。
最初に必要なモジュールをインストールする。
$ npm install postcss postcss-cli postcss-import postcss-nested autoprefixer
とりあえずimportとnestedとautoprefixerをインストールした。
postcss.jsonというファイル名で設定ファイルを書く。
{ "use": [ "postcss-import", "postcss-nested", "autoprefixer" ], "input": "index.css", "output": "output.css", "local-plugins": true, "autoprefixer": { "browsers": "last 2 version" } }
useには使用するモジュールを書く必要があるのだけど、importを使用する場合は先頭に書く必要がある。あとはCSSをいくつか書く。
clearfix.cssというファイル名でCSSを書く。
.clearfix::after { content: ""; clear: both; display: block; }
index.cssというファイル名でCSSを書く。
@import "./clearfix.css"; /* comment */ div { opacity: 0.5; border-radius: 5px; animation: anime 1s linear 0s; &.div { opacity: 1; } } @keyframes anime { from { transform: translateY(0px); } to { transform: translateY(100px); } }
これらをpostcss-cliから変換する。
$ ./node_modules/.bin/postcss --config postcss.json
変換されたoutput.cssは以下の通り。
.clearfix::after { content: ""; clear: both; display: block; } /* comment */ div { opacity: 0.5; border-radius: 5px; -webkit-animation: anime 1s linear 0s; animation: anime 1s linear 0s; } div.div { opacity: 1; } @-webkit-keyframes anime { from { -webkit-transform: translateY(0px); transform: translateY(0px); } to { -webkit-transform: translateY(100px); transform: translateY(100px); } } @keyframes anime { from { -webkit-transform: translateY(0px); transform: translateY(0px); } to { -webkit-transform: translateY(100px); transform: translateY(100px); } }
今回はファイル名を指定したけれど、ディレクトリを指定することもできるようなので用途に応じて使用方法を変えれば良いと思う。
変換も早いし、よほどnode.jsが古くなければ動作すると思うのでnode-sassを使う必要がなくなるかな、と思った。
0 notes
Text
node-canvasとフォントサイズ
ブラウザ上のCanvasで出力している画像を、なんとかnode.js内で出力できないかと思い、node-canvasを試しに使ってみる事にした。
使ってみたところ、ブラウザ上のCanvasでテキストを出力しているのだけど、node-canvasだとフォントサイズが小さいままになっている。 Ubuntuで試していたのだけど、どうもCairoなのかPangoなのか、なにか相性の悪いものがきちんとフォントサイズが取れないみたいだった。
IssueとPull Requestを眺めていたら、フォントに関しての修正を行っているスレッドがあったのでそれを見てみたら、chearon/node-canvasにたどり着いた。
このリポジトリのprefer-pangoブランチで修正を行っているようだったので、早速使用してみる事に。
$ npm install https://github.com/chearon/node-canvas#prefer-pango
インストールはGitリポジトリのURLを直接指定してインストールした。
var Canvas = require('canvas'), fs = require('fs'); Canvas.registerFont( __dirname + '/NotoSansCJKjp-Regular.otf' ); var canvas = new Canvas(300, 300); var context = canvas.getContext('2d'); context.font = '40px NotoSansCJKjp'; context.fillText('能登麻美子', 10, 10); fs.writeFileSync('./canvas.png', canvas.toBuffer());
Notoフォントはあらかじめダウンロードして展開しておく。公式のnode-canvasとフォントの登録の仕方が異なるところを気をつける必要がある。
これで実行してみたところ、期待した通りにフォントサイズが大きくなってくれた。早いところ、公式のnode-canvasにマージされて欲しい。
0 notes
Text
D3.jsをカスタムビルドしてファイルサイズを小さく抑える
D3.jsにある特定の機能だけ使いたかったのだけど、d3.min.jsを見てみたら150KBと大きいファイルサイズだったので、なんとかして小さくできないかと思いカスタムビルドした。
まずはD3.jsとD3.jsと同じ作者が作っていたsmashをインストールする。
$ npm install d3 smash
smashはwebpackやbrowserifyのようなもの。ただし両者のように賢いものではなく、ただファイルを連結するだけ。smashのリポジトリにはdeprecatedと書いてあって、rollupを代わりに使えと書いてあるが、使い方がさっぱりわからなかった上にsmashで十分だったのでsmashを使っている。
次にカスタムビルドをするためのJavaScriptを記述する。node_modules/d3/src/d3.jsを見るとわかるが、以下のような記述をする。
import "./node_modules/d3/src/start"; import "./node_modules/d3/src/compat/"; import "./node_modules/d3/src/end";
これをファイルとして保存する。とりあえずはd3.jsとして保存した。
保存したファイルをsmashでビルドする。
$ ./node_modules/.bin/smash ./d3.js > d3.custom.js
これでカスタムビルドされたd3.custom.jsが生成される。
D3.js ver.4ではES6 Modulesに対応するので上記のようなことをする必要はなくなると思う。
https://github.com/mbostock/d3/issues/430
https://github.com/mbostock/d3/issues/1978
https://github.com/mbostock/d3/issues/2220
https://github.com/mbostock/d3/issues/2461
ちなみに使いたかったのはD3.jsのbehaviorの一つであるzoomの機能。以下のような感じ。
http://bl.ocks.org/shawnbot/6518285
きちんとカーソル位置に向かって拡大してくれるのが良い。スマートフォンでもピンチイン・ピンチアウトで動作した。
この機能を使うには以下のJavaScriptでビルドできた。これが最小だと思う。
import "./node_modules/d3/src/start"; import "./node_modules/d3/src/compat/"; import "./node_modules/d3/src/behavior/behavior"; import "./node_modules/d3/src/behavior/zoom"; import "./node_modules/d3/src/selection/interrupt"; import "./node_modules/d3/src/transition/transition"; import "./node_modules/d3/src/end";
このJavaScriptでビルドされたD3.jsを含んだスクリプトが縮小して39KBほどなので、かなり小さくなったと思う。
0 notes
Text
jQueryを使用せずにイベントを発生させる
jQueryに頼らずにイベントを発生させるにはどうしたら良いのか調べた。
https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events
http://stackoverflow.com/questions/15951468/what-is-a-good-example-of-using-event-constructors-in-js
http://shim0mura.hatenadiary.jp/entry/20111224/1324735206
上記の記事たちがとてもよくまとまっている。上記を参考に実装したものが以下になる。
https://github.com/sasaplus1-prototype/trigger-to-events
IE8とIE9とChromeとFirefoxとSafariで試した。後者4つでは普通に動作したが、IE8はやはりそれに合わせたコードを書く必要があった。
また、記事にもある通りIE8ではカスタムイベントは実行できないようだ。
jQueryのコードを読んでみたところ、jQueryは内部でイベントシステムを持っているようですべて管理しているようだった。
https://github.com/jquery/jquery/blob/1.12.1/src/event.js
これを真似するのは簡単ではないと思うので、ここまで複雑なことを古いIEでもしたいのであれば素直にjQueryを読み込ませた方が良いと思う。
0 notes
Text
Google Chrome DevToolsのConsoleでデバッグを簡単にする
DevTools 上で jQuery などのお気に入りのライブラリを簡単に使いたい方へを読んでlodashとjQueryをスニペットに登録した。
これでスニペットをRunさせると、lodashやjQueryが読み込まれていないウェブサイトでもConsoleから使えるようになる。なので_.filterでデータを抽出して表示したり、jQueryでDOMを簡単に編集したりデバッグが簡単になる。
1 note
·
View note
Text
mdfindでディレクトリを検索する
findでなくmdfindでディレクトリを検索したかったので調べてみた。
あの日,mdfind が見つけたもの
Spotlight syntax, mdfind examples, and metadata attributes
Spotlight Metadata Attributes
mdfind(1)
File Metadata Query Expression Syntax
上記のサイトを一通り見れば大体わかると思う。mdfindで使えるメタデータやクエリの記述方法はわかった。
mdlsでいくつかディレクトリのメタデータを見てみたのだけど、ディレクトリによって全然違っていた。
大体これでディレクトリと判定できるだろう、という条件が見つけられたので以下のようなクエリを使うことに。
$ mdfind 'kMDItemContentType == "public.folder" || kMDItemFSNodeCount > 0'
kMDItemContentTypeにpublic.folderが入っているディレクトリはこれで見つけられる。 kMDItemFSNodeCountは配下にファイルやディレクトリをいくつ持っているかという値らしく、 kMDItemContentTypeが指定されていない場合はこちらで見つけられる。
.gitディレクトリ配下にkMDItemContentTypeにpublic.folderが指定されておらず、kMDItemFSNodeCountも0のディレクトリがあるにはあったが……
これをpecoと組み合わせていい加減にディレクトリを移動したかったので、.bashrcに以下のような関数を書いた。
mcd() { cd "$(mdfind -onlyin $HOME 'kMDItemContentType == "public.folder" || kMDItemFSNodeCount > 0' | peco --query="$*")" }
ただ、mdfindは隠しディレクトリ配下をデフォルトでは検索してくれない。なので、findを使う関数も書いた。
icd() { cd "$(find $HOME -maxdepth 20 -type d -print 2>/dev/null | peco --query="$*")" }
これなら$HOME配下のディレクトリを大体検索してくれる。
上に書いたスクリプトをそのまま使ったのでなく、.gitやnode_modulesなど各種ディレクトリを無視するスクリプトを書いたので実際にはもう少し長いスクリプトになったが。
まだまだターミナル内でのディレクトリの移動や、Vimでのファイルの開き方には改善の余地があると思っているのでもっと楽にしていきたい。
1 note
·
View note
Text
AWSでアカウントを作る際に参考にした情報
AWSのアカウントを作る必要があったので、作ったあといろいろな情報を参考にしてセキュアにしたつもり。
AWS での多要素認証 (MFA) の使用
最初の IAM ユーザーと管理者グループの作成
IAM のベストプラクティス
AWS 権限管理のベストプラクティスについて考えてみた
AWSのアカウント開設後にすべき事をまとめてみた
IAMによるAWS権限管理運用ベストプラクティス (1)
IAMによるAWS権限管理運用ベストプラクティス (2)
Gitを初めて触った時のような複雑さを感じつつも、使い慣れたらその柔軟さを思い知るのだろうか、とも思った。
0 notes
Text
matchMedia関数でウィンドウサイズの変更を監視する
レスポンシブなウェブサイトでJavaScriptを書く必要があったのだけど、 そこでwindow.matchMediaを使うとウィンドウサイズの変更を監視できることを知った。
var mql = window.matchMedia('screen and (min-width: 768px)');
とすると、mqlにMediaQueryListが返ってくる。 matchMedia関数にはCSSで書いているメディアクエリの文字列そのものが渡せる。
mql.matches;
とすると、メディアクエリの条件に一致していた場合にtrueになっている。一致していない場合はfalseになる。
MediaQueryListにはリスナー関数を登録できる関数があって、addListener関数を使うと登録できる。
mql.addListener(function(event) { event.matches; });
登録したリスナー関数は、メディアクエリの条件が変更されたときに呼ばれる。
これでわざわざwindow.onresizeを監視する必要がなくなる。
caniuseによるとIE9以下で使用できない以外は主要ブラウザは使用できるようだ。
Can I use matchMedia?
IE9以下でも使用したい場合はmatchMedia.jsのpolyfillを使う。
<!--[if lt IE 10.0]> <script src="matchMedia.js"></script> <script src="matchMedia.addListener.js"></script> <![endif]-->
で良いと思う。
addListenerのコードを呼んだ感じでは、resizeが起きてから30ms後に登録した関数が呼ばれるようだ。 常に監視などはしていないようなので、パフォーマンスへの影響はそこまで大きくないと思う。
参考:
メディアクエリ
スクリプトからのメディアクエリの使用
0 notes
Text
都道府県の並び
よく会員登録などで住所を入力する際に表示される、都道府県のコンボボックスの並びが大体一緒なのが気になっていたのだけど、JISで定義されていたのを知った。
全国地方公共団体コード
まあ、JISで定義されているという言い訳が出来るのでおかしな並び順にせずに済む。ご丁寧に都道府県コードまで付いているので、システムに保存する場合などの値もそのままこれを使う事が多いんだろう。
0 notes
Text
Vagrantで起動しているVMに対して一行のコマンドを実行する
Vagrantで起動しているVMに対して一行のコマンドを実行するには
$ vagrant ssh -c 'command'
でいい。いままでvagrant sshでログインしてコマンドを実行してexitしていたのでこれなら自動化などにも使用できる。
0 notes
Text
hasOwnPropertyを直接呼ばない
とあるモジュールのソースコードを読んでいたら、以下のissueへのリンクがコメントとして書いてあった。
https://github.com/nodejs/node-v0.x-archive/issues/1707
hasOwnPropertyを直接呼ぶのでなく、Object.prototype経由で呼んだ方がよいとのこと。これ、parseIntとかグローバル直下の関数全般に言えるよな……
0 notes
Text
モックテストについていくらか調べた
いままでJavaScriptでモックを使ったテストというとSinon.JSしか使ったことがなかった。 そこにReactのテストを書く必要がある事態になったのでいろいろ調べて試してみることに。ちなみにJestは使わない。
proxyquireについて
requireをフックしてインジェクションするモジュール。
b.js
module.exports = function() { console.log('Hello!'); };
a.js
var b = require('./b'); b();
index.js
require('./a');
上記3つのファイルがあるとして、index.jsを実行すると以下のようになる。
$ node index.js Hello!
ここでb.jsをproxyquireで別のモジュールとして置き換える。
index.js
var proxyquire = require('proxyquire'); var mock = function() { console.log('See you!'); }; // 第一引数にindex.jsでrequireの引数に渡す文字列を、 // 第二引数のキーにrequireされるモジュール内でrequireされる引数の文字列を渡す // どちらも完全一致している必要がある proxyquire('./a', { './b': mock }); require('./a');
これでindex.jsを実行すると結果が変わる。
$ node index.js See you!
また、proxyquireに渡す第二引数内に特殊なキーを指定すると、node_modules内から読み込まれるはずのものも置き換えることができる。
a.js
var deepcopy = require('deepcopy'); deepcopy();
index.js
var proxyquire = require('proxyquire'); var mock = function() { console.log('mock'); }; mock['@global'] = true; proxyquire('./a', { 'deepcopy': mock }); require('./a');
これで実行するとモジュールを置き換えられていることがわかる。
$ npm install deepcopy $ node index.js mock
ただ、Babelなどでimport文などを使用していると正常に動作しないようだ。
inject-loaderについて
webpackのloaderとして実装されている。当然ながらwebpackと一緒に使用する。
webpackのissueでもproxyquireの代わりのものとしてコメントされていた。
以下のコードはbabel-loaderも一緒に使用することを想定したもの。
mod.jsx
(空のファイル)
sample.jsx
import mod from './mod.jsx'; export default mod;
index.jsx
import sampleInjector from 'inject!./sample.jsx'; const sample = sampleInjector({ './mod.jsx': { method() { console.log('Hello!'); } } }).default; sample.method();
これでwebpackでコンパイルしたあとに実行すると以下のようになる。
$ node index.js Hello!
使いかたはproxyquireなどとほとんど似たような記述になる。
こちらはproxyquireと違ってimport文で書いても失敗しない。といっても結局は関数を呼んでいるのだが。
webpack内で使えるloaderなだけあって、externalsで指定した名前などでも置き換えられる。 おそらくaliasなども置き換えられると思う。
karma-webpackでも当然使えるので、今回はinject-loaderで解決した。というよりかはこれでないと解決できなかった。
0 notes
Text
CommonsChunkPluginの設定
webpackは良く使うのだけど、CommonsChunkPluginを久しぶりに使ったら設定方法を忘れていたのでメモ。
webpack.config.js
var webpack = require('webpack'); module.exports = { entry: { bundle: [ 'jquery', 'react' ] }, output: { path: './', publicPath: '/', filename: '[name].js' }, plugins: [ new webpack.optimize.CommonsChunkPlugin({ minChunks: 3, name: 'bundle' }) ] };
こんなふうに設定を書いてあげてwebpackを実行する。
$ npm install jquery react webpack $ ./node_modules/.bin/webpack
CommonsChunkPluginのnameにentry以下のキーを渡すとその対象が共通ライブラリ的な扱いになる。
0 notes
Text
babel-plugin-lodashでlodashの一部の関数だけ取り込む
babel-plugin-lodashというBabelプラグインを見かけたので早速試しに使ってみた。
package.json
{ "private": true, "dependencies": { "lodash": "^3.10.1" }, "devDependencies": { "babel": "^6.3.26", "babel-cli": "^6.4.0", "babel-plugin-lodash": "^1.1.0", "babel-preset-es2015": "^6.3.13" } }
lodashがver.4.0.0になったのだけど、対応していないみたいなのでlodashのver.3をインストールした。 lodash-esというものが追加されていたようなのだけど、ver.4ならこちらを使えば動作するのだろうか。
.babelrc
{ "presets": [ "es2015" ], "plugins": [ "lodash" ] }
src/index.js
import _ from 'lodash'; console.log(_.get({ aaa: { bbb: 100 } }, 'aaa.bbb'));
コンパイル
$ ./node_modules/.bin/babel --out-dir ./lib ./src
lib/index.js
'use strict'; var _get = require('lodash/object/get'); var _get2 = _interopRequireDefault(_get); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } console.log((0, _get2.default)({ aaa: { bbb: 100 } }, 'aaa.bbb'));
_.getだけ使用しているので、それだけ取り込まれている。
これでさらにwebpackを使えばブラウザでも取り込まれるのだろうと思う。
0 notes
Text
_.getと_.has
_.getと_.hasという関数がlodashにあるのを知った。
_.get
第一引数に渡したオブジェクト内の値を文字列のパスから取得できる関数。
_.get([[[100]]], '[0][0][0]'); // => 100
パスの指定には他の記述もできる。
_.get({ aaa: { bbb: [ { ccc: 100 } ] } }, ['aaa', 'bbb', '0', 'ccc']); // => 100
何が便利かというと、やはり深い位置にある値を取得する際にエラーがスローされるのを気にしなくて良いところだと思う。
_.get({}, 'aaa.bbb.ccc.ddd'); // => undefined
それに、値が存在しなかった場合の戻り値も指定できる。
_.get({}, 'aaa.bbb.ccc.ddd', 100) // => 100
_.has
_.getとは異なり、値は取得せずに値が存在するかどうかを調べる関数。
_.has([[[100]]], '[0][0][0]'); // => true
_.getとほぼ同じ使い方になる。
0 notes
Text
looseに対応しているBabelプラグイン
looseに対応しているBabelのプラグインが具体的にどれなのかわからなかったので調べてみた。ドキュメントに書いていなかったのでリポジトリをクローンしてきて、検索してみた。
$ ghq get --shallow babel/babel
のあとにptでlooseで検索した。find + grepでも良いと思う。
babel-plugin-transform-es2015-classes
babel-plugin-transform-es2015-computed-properties
babel-plugin-transform-es2015-destructuring
babel-plugin-transform-es2015-for-of
babel-plugin-transform-es2015-modules-commonjs
babel-plugin-transform-es2015-spread
babel-plugin-transform-es2015-template-literals
上記のプラグインだけかな?
0 notes
Text
練習用リポジトリをいくつか作った
調子が良かったのでいくつか練習用リポジトリを作ったりした。
pause-animation-with-animation-play-state
animation-play-stateというプロパティ知らなかったのだけど、これを使うとCSS3アニメーションを一時停止したり再開したりできる。
control-job-queue-with-kue
Redisをバックエンドに使っているジョブキューのライブラリ、Kueを使ってみたもの。とても便利だ。
control-formdata-with-formidable
HTML5のFormDataを使ってAjax経由で複数渡されたファイルをFormidableで受け取るもの。これもとても便利。
control-progress-with-socket-io
HTML5のprogressタグをSocket.IOから変えるもの。Socket.IO ver.1になってからちゃんと使ったのはこれが初めてかもしれない。
0 notes