ちくわのパフェなんだよ

Explore Tagged Posts
Last Seen Blogs
Statistics

We looked inside some of the posts by chikuwa-parfait and here's what we found interesting.

Inside last 20 posts
Time between posts
5 days
Number of posts by type
Photo
0
Video
0
Audio
0
Text
20
Chat
0
Answer
0
Link
0
Quote
0
Fun Fact

There's almost an equal split between the sexes on Tumblr - 51% male, 49% female.

chikuwa-parfait·4 years agoText

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 · See All
chikuwa-parfait·4 years agoText

ブラウザ上の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 · See All
chikuwa-parfait·4 years agoText

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に対応するので上記のようなことをする必要はなくなると思う。


ちなみに使いたかったのは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 · See All
chikuwa-parfait·4 years agoText

jQueryに頼らずにイベントを発生させるにはどうしたら良いのか調べた。

上記の記事たちがとてもよくまとまっている。上記を参考に実装したものが以下になる。

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 · See All
chikuwa-parfait·4 years agoText

DevTools 上で jQuery などのお気に入りのライブラリを簡単に使いたい方へを読んでlodashとjQueryをスニペットに登録した。

これでスニペットをRunさせると、lodashやjQueryが読み込まれていないウェブサイトでもConsoleから使えるようになる。なので_.filterでデータを抽出して表示したり、jQueryでDOMを簡単に編集したりデバッグが簡単になる。

0 notes · See All
chikuwa-parfait·4 years agoText

findでなくmdfindでディレクトリを検索したかったので調べてみた。

上記のサイトを一通り見れば大体わかると思う。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 notes · See All
chikuwa-parfait·4 years agoText

AWSのアカウントを作る必要があったので、作ったあといろいろな情報を参考にしてセキュアにしたつもり。

Gitを初めて触った時のような複雑さを感じつつも、使い慣れたらその柔軟さを思い知るのだろうか、とも思った。

0 notes · See All
chikuwa-parfait·4 years agoText

レスポンシブなウェブサイトで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 · See All
chikuwa-parfait·4 years agoText

よく会員登録などで住所を入力する際に表示される、都道府県のコンボボックスの並びが大体一緒なのが気になっていたのだけど、JISで定義されていたのを知った。

全国地方公共団体コード

まあ、JISで定義されているという言い訳が出来るのでおかしな並び順にせずに済む。ご丁寧に都道府県コードまで付いているので、システムに保存する場合などの値もそのままこれを使う事が多いんだろう。

0 notes · See All
chikuwa-parfait·4 years agoText

Vagrantで起動しているVMに対して一行のコマンドを実行するには

$ vagrant ssh -c 'command'

でいい。いままでvagrant sshでログインしてコマンドを実行してexitしていたのでこれなら自動化などにも使用できる。

0 notes · See All
chikuwa-parfait·4 years agoText

とあるモジュールのソースコードを読んでいたら、以下のissueへのリンクがコメントとして書いてあった。

https://github.com/nodejs/node-v0.x-archive/issues/1707

hasOwnPropertyを直接呼ぶのでなく、Object.prototype経由で呼んだ方がよいとのこと。これ、parseIntとかグローバル直下の関数全般に言えるよな……

0 notes · See All
chikuwa-parfait·4 years agoText

いままで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 · See All
chikuwa-parfait·4 years agoText

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 · See All
chikuwa-parfait·4 years agoText

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 · See All
chikuwa-parfait·4 years agoText

_.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 · See All
chikuwa-parfait·4 years agoText

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 · See All
chikuwa-parfait·4 years agoText

調子が良かったのでいくつか練習用リポジトリを作ったりした。

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 · See All
chikuwa-parfait·4 years agoText

そろそろBabel5でなくBabel6に移行しても大丈夫なのかと思い、試しにBabel6用のブランチを作ってBabel6を試してみたのだけど、ver.5からver.6に上がった際に仕様が変わった部分がありその箇所のせいで既存のコードが一部動作しなくなった。

具体的には以下のようなコードが動作しなくなった。

lib.js

export default {
  aaa: 1,
  bbb: 2,
  ccc: 3,
};

index.js

import { aaa, bbb } from './lib.js';

console.log(aaa);  // undefined
console.log(bbb);  // undefined

これが何故動作しなくなったかというのはStackOverflowのBabel 6 changes how it exports defaultの回答Misunderstanding ES6 Modules, Upgrading Babel, Tears, and a Solutionという記事に書いてある。

まあ、仕様に反した実装が出来てしまっていたのを出来ないように修正した、という感じか。


これをどういう風に書き換えるかを記事を参考にしつつ調べていたのだけど、importする側でexportする側を意識してコードを書く必要があるみたいだ。

lib.js

export default {
  aaa: 1,
  bbb: 2,
  ccc: 3,
};

index.js

// import { default as lib } from './lib.js'; と等価
import lib from './lib.js';

const { aaa, bbb } = lib;

console.log(aaa);
console.log(bbb);

exportする側がこれまで通りexport defaultしてくるならこれで。Babelがいい感じにdefaultを補完してくれるようなのでrequire(’./lib.js’).defaultと書く必要がない。

lib.js

export const aaa = 1;
export const bbb = 2;

index.js

import { aaa, bbb } from './lib.js';

console.log(aaa);
console.log(bbb);

exportする側がnamed exportsしている場合はimportする側で分割代入できる。

index.js

import * as lib from './lib.js';

console.log(lib.aaa);
console.log(lib.bbb);

exportする側がnamed exportsしているが、importする側で特定のオブジェクトの配下にimportしたい場合はこれで。

index.js

import lib from './lib.js';

だと正常にimportできない。


いろいろ書いたけど、babel-plugin-add-module-exportsを使えばBabel5相当の挙動に戻せるので、ソースコードを書き直さずにとりあえず解決したい場合はこれを使うのがとても楽。

特にimport/export周りの仕様を知らずにBabelがよしなにしてくれるのでそれでテキトーに書いていたのだけど、ここへ来てその無知により痛い目に会った。

参考記事

0 notes · See All
chikuwa-parfait·4 years agoText

昔書いた記事を書き直したもの。


いくつかの非同期処理を並列に実行してすべての結果を待つには、 Promise.allを使えば解決するのだけど、直列に実行したい場合に綺麗に書けなくて微妙な気持ちになっていた。

ちょっと調べたらPromiseとArray#reduceを使うと綺麗に書けるようだったのだけど、 書いてみたらはまったのでメモがてらいろいろ書いておく。

結論としてはPromise#thenにPromiseを渡すとその場で実行されてしまうので、無名関数でラップしてあげて返すと言うのが大事。

function a(n, timeout) {
  return function() {
    return new Promise(function(resolve, reject) {
      setTimeout(function() {
        console.log(n);
        resolve(n);
      }, timeout);
    });
  };
}

var processes = [
  a(1, 300),
  a(2, 200),
  a(3, 100)
];

processes.reduce(function(prev, curr, index, array) {
  return prev.then(curr);
}, Promise.resolve());

これで出力は

1
2
3

となる。

1 notes · See All
Next Page