ゆたんぶろぐ

気が向いたら書いてます

更新したファイルに該当するタスクだけ走らせる Gruntfile

grunt-contrib-watch って便利なんですが、監視ファイルが多くなる=走る処理が多くなるとどうしても時間がかかってしまいます。それでなんだか効率が落ちてたりするわけなんですが、grunt-este-watch が幸せということを聞いて、ぼくも幸せになりたいと思いやってみました。

更新されたファイルに関係ないタスクが走るのが良くないわけで、ちゃんと個別にタスクを走らせたら良いわけですね。ということで、以下にサンプルを置いておきます。とりあえず便宜上なので、ファイル名に意味はありません。

やりたいこと

Sass

common.sass

css へのコンパイル -> reset.sass との concat -> minify

mobile.sass

css へのコンパイル -> minify

JavaScript

common-a.js / common-b.js

common-a.js と common-b.js を concat -> minify

mobile.js

minify

YAML

functions.yml / settings.yml

それぞれのファイル名での json

前提

監視対象のファイルは全て ./src/ に入ってるものとします。

利用するプラグイン

  • grunt-contrib-compass
  • grunt-contrib-concat
  • grunt-contrib-cssmin
  • grunt-contrib-uglify
  • grunt-este-watch
  • grunt-yaml

Gruntfile.coffee

module.exports = (grunt) ->
  pkg = grunt.file.readJSON 'package.json'
  grunt.initConfig
    compass:
      dev:
        options:
          config: 'config.rb'
          environment: 'development'
          force: true
      prod:
        options:
          config: 'config.rb'
          environment: 'production'
          force: true
    concat:
      css:
        files:
          'css/styles.css': ['css/reset.css', 'css/common.css']
      js:
        files:
          'js/functions.js': ['src/common-a.js', 'src/common-b.js']
    cssmin:
      common:
        files:
          'css/styles.min.css': ['css/styles.css']
      mobile:
        files:
          'css/mobile.min.css': ['css/mobile.css']
    uglify:
      common:
        files:
          'js/functions.min.js': ['js/functions.js']
      mobile:
        files:
          'js/mobile.min.js': ['src/mobile.js']
    yaml:
      functions:
        files:
          'js/functions.json': ['src/functions.yml']
      settings:
        files:
          'js/settings.json': ['src/settings.yml']
    esteWatch:
      options:
        dirs: ['src/']
      sass: (file) ->
        return if getTarget(file) is 'mobile' then ['compass:dev', 'cssmin:mobile'] else ['compass:dev', 'concat:css', 'cssmin:common']
      js: (file) ->
        return if getTarget(file) is 'mobile' then ['uglify:mobile'] else ['concat:js', 'uglify:common']
      yml: (file) ->
        return ['yaml:' + getTarget(file)]

  for t of pkg.devDependencies
    if t.substring(0, 6) is 'grunt-'
      grunt.loadNpmTasks t

  grunt.registerTask 'w', ['esteWatch']
  grunt.registerTask 'default', ['compass:dev', 'concat', 'cssmin', 'uglify']

getTarget = (file) ->
  return file.split('/')[1].split('.')[0]

これで grunt w で、css でも yaml でも該当タスクだけ走るので、劇的にスピードが変わりました。めでたしめでたし。

Path API を叩く PHP / Python / Ruby のサンプル

あけましておめでとうございます(遅

Path が API を公開してたので(気づくの遅い)、叩いてみました。
今までいくつかの API を叩いてきたけど、json で渡すのは初めてでした。

それぞれ下記を叩くことにします。
GET: /user/:id
https://path.com/developers/docs#get-user

POST: /moment/thought
https://path.com/developers/docs#post-moment-thought

PHP

GET

<?php
header('Content-type: application/json; charset=utf-8');

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://partner.path.com/1/user/self');
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization: Bearer YOUR API TOKEN'));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

$response = curl_exec($ch);
curl_close($ch);

echo $response;

POST

<?php
header('Content-type: application/json; charset=utf-8');

$options = array('thought' => 'PHP Test', 'private' => 1);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://partner.path.com/1/moment/thought');
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization: Bearer YOUR API TOKEN', 'Content-Type: application/json'));
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($options));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

$response = curl_exec($ch);
curl_close($ch);

echo $response;

Python

GET

#!/usr/local/bin/python
# -*- coding: utf-8 -*-
print "Content-Type: application/json";

import pycurl

c = pycurl.Curl()
c.setopt(pycurl.URL, 'https://partner.path.com/1/user/self')
c.setopt(pycurl.HTTPHEADER, ['Authorization: Bearer YOUR API TOKEN'])
c.perform()

POST

#!/usr/local/bin/python
# -*- coding: utf-8 -*-
import pycurl
import json

options = {'thought': 'Python test', 'private': 1}

c = pycurl.Curl()
c.setopt(pycurl.URL, 'https://partner.path.com/1/moment/thought')
c.setopt(pycurl.HTTPHEADER, ['Authorization: Bearer YOUR API TOKEN', 'Content-Type: application/json'])
c.setopt(pycurl.POST, 1)
c.setopt(pycurl.POSTFIELDS, json.dumps(options))
c.perform()

Ruby

GET

#!/usr/local/bin/ruby
# encoding utf-8
print "Content-Type: text/html\n\n";

require 'faraday'
require 'json'

conn = Faraday::Connection.new(url: 'https://partner.path.com') do |builder|
  builder.use Faraday::Request::UrlEncoded
   builder.use Faraday::Response::Logger
  builder.use Faraday::Adapter::NetHttp
end

response = conn.get do |request|
  request.url '/1/user/self'
  request.headers = {'Authorization' => 'Bearer YOUR API TOKEN'}
end

json = JSON.parser.new(response.body)
p json.parse

POST

#!/usr/local/bin/ruby
# encoding utf-8
print "Content-Type: application/json\n\n";

require 'faraday'
require 'json'

options = {'thought' => 'Ruby Test', 'private' => 1}

conn = Faraday::Connection.new(url: 'https://partner.path.com') do |builder|
  builder.use Faraday::Request::UrlEncoded
  builder.use Faraday::Response::Logger
  builder.use Faraday::Adapter::NetHttp
end

response = conn.post do |request|
  request.url '/1/moment/thought'
  request.headers = {
    'Authorization' => 'Bearer YOUR API TOKEN',
    'Content-Type' => 'application/json'
  }
  request.body = JSON.generate(options)
end

json = JSON.parser.new(response.body)
p json.parse

Illustrator で端っこがアートボードに揃わないときの対処

年賀状を作る憂鬱な季節になりました。デザインとか超苦手分野なので毎年憂鬱です。

さて、そんな年賀状を作ってましたが、Illustrator でオブジェクトをアートボードの端っこに寄せようと思うんですが、揃わないんですよ。

f:id:primedesignworks:20131211115046p:plain
「いやっ/// あたしそんなに軽い女じゃないもんっ///」って聞こえてきそうです。ええ、デザイン嫌過ぎて壊れてますすいません。

さて、この対処ですが、「整列」パネル内右下にある「整列」ってのをクリックして出るメニューの「アートボードに整列」をにチェックを入れて、整列させてみましょう。すると、揃いましたよ!
f:id:primedesignworks:20131211115047p:plain

この対処方法は @75mix さんから教えてもらいました。ありがとうございました。

grunt-play の終了音に Mac の警告音を使う

astronaughts さんの grunt-play が便利ですね!いっつも grunt の終了はターミナルをチラ見してたので、大変助かっておりますありがとうございます。

さて、終了音に好きな音を鳴らせるのは魅力的なんですが、手頃なものがない場合、Mac の警告音を使うという手もあります。「システム環境設定 -> サウンド」にあるこの子たちです。
f:id:primedesignworks:20131207075752p:plain

Gruntfile.coffee 内での設定を以下のようにすれば、使えるようになります。その他 grunt-play に関して詳しくは、冒頭のリンクにあるエントリーを参照してください。

play:
  fanfare:
    file: '/System/Library/Sounds/Purr.aiff'

ファイル名はシステム環境設定内での文字列「Glass」とか「Hero」とかがそのままなので、「Glass.aiff」「Hero.aiff」などです。

Wikipedia Mobile のようなスライドメニューを簡単に作る

WikipediaiPhone で見ると、左上にメニューボタンがあって、それをタップすると左からメニューが表示される、まぁよくあるタイプですが、簡単に実装しましょう。

開閉の制御は jQuery、アニメーションはヒマなんで CSS3 でやりましょう。

HTML

<nav>
  <a href="#">link</a>
  <a href="#">link</a>
  <a href="#">link</a>
</nav>
<div id="content">
 <button id="btn_menu">menu</button>
</div>

Sass

nav {
  width: 200px;
  min-height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 0;
  background: rgb(180, 180, 180);

  a {display: block;}
}
#content {
  width: 100%;
  min-height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  z-index: 1;
  background: rgb(220, 220, 220);
}
#content.menu_open, #content.menu_close {
  @include experimental('animation-duration', 0.5s, webkit);
  $animation-support: webkit;
  @include experimental('animation-iteration-count', 1);
}
#content.menu_open {
  @include experimental('animation-name', menu_on, webkit);
  left: 200px;
}
#content.menu_close {
  @include experimental('animation-name', menu_off, webkit);
  left: 0;
}
@-webkit-keyframes menu_on {0% {left: 0;} 100% {left: 200px;}}
@-webkit-keyframes menu_off {0% {left: 200px;} 100% {left: 0;}}

JavaScript

$(function() {
  $(document)
    .on('touchend', '#btn_menu', function() {
      var $content = $('#content');
      $content.attr('class', $content.hasClass('menu_open') ? 'menu_close' : 'menu_open');
    })
    .on('touchend', '.menu_open', function() {
      $('#content').attr('class', 'menu_close');
    })
  ;
});

結果

普段の状態

f:id:primedesignworks:20131205152215p:plain

コンテンツ部分をタップすると元に戻る

f:id:primedesignworks:20131205152216p:plain