読みやすいPRの書き方まとめ
前提
コードを書く前に
- [ ] 実現したい要件はそれで合っていますか?
- [ ] フローチャートなどで処理の流れを可視化できていますか?
- [ ] 本当にそのソリューションで正しいですか?解決方法は本当にそれだけですか?
変数
- [ ] それ変数化する意味ありますか?
- [ ] その変数初期化する意味ありますか?
メソッド
- [ ] そのメソッド本当に抽象化する必要ありますか?
- [ ] その処理再利用できませんか?
- [ ] そのメソッドその責務負う必要ありますか??
制御文
- [ ] そのif文三項演算子でone linerでかけないですか??
- [ ] その評価・条件本当に必要ですか??
- [ ] それ以外(else)の処理書き忘れていませんか?
- [ ] そのif文、switch文にできませんか?もしそうしたら、break忘れてないですか?
コメント
- [ ] その処理コメントつけなくてもわかってもらえますか?
- [ ] 逆にそのコメント処理の内容とか関数名とか見れば自明ではないですか?
名前
- [ ] その名前抽象的じゃないですか?もっと具体的にできないですか?
- [ ] そこ本当にキャメルケースでその言語はその命名規則で正しいですか?
基本
- [ ] ちゃんと要件通りにうごいているかためしましたか?
- [ ] もっと短く書ける書き方はありませんか?
- [ ] その書き方は最新の安定版ですか?
- [ ] 無駄な評価、条件はありませんか?
- [ ] 文字リテラルの結合処理は + ではなく、interpolation使っていますか?
- [ ] そのメソッド、変数のスコープはそれで本当にただしいですか?
- [ ] その関数とかクラス、ちゃんと単一責任ですか?
- [ ] もう少し早くその関数から返すことってできませんか?fast returnできませんか?
- [ ] 既存のコードに流されていませんか?どうしてそのフォルダ構造、ファイル名になっているか考えましたか?
- [ ] もう少しそのコード単純にできませんか?
リーダブルコード
http://tenshotanaka.hatenablog.com/entry/2017/07/05/173544
注意すること
Commit (社内の元cookpadの「R言語上級ハンドブック」共著者の人が言ってたこと転載)
- どの commit の状態でも最低限動く状態にする
- 試行錯誤の結果、無意味になる commit は削除する or 1 commit にまとめる
- 変更の必要性がわかるようにする
- 例えば、model を追加する commit、controller を追加する commit、view を追加する commit みたいに分けると、commit 順で見ても model のメソッドがどこでどう使われるかがわからないし、controller で取得した情報が view でどのように使われるかわからないので良くない
- 開発途中で気付いた不要なコードの削除は 1 commit にする or 別 PR にする
- commitを適切な粒度で分ける
Comment
- プルリクエストには目的を明記する
- プルリクを読む人々が経緯に精通していると思い込まず、なぜその仕事が発生したのか概要を提供するように努める
- 会社の誰しもがプルリクエストを読めるということを忘れないようにする。今後、今参加している人以外が読んだ時にも、内容や雰囲気がわからなくてはいけない
- あなたがどんなフィードバックを望んでいるのか明確にする。例えば「コードに目を通して欲しい」「技術的な議論がしたい」「設計について批評してほしい」「文言を確認してほしい」などです
- 議論に関与させたい誰かがいるなら@hogeと指定(mention)する。そしてなぜmentionしたのかを添える。(例: /cc @jesseplusplus ロジックの明確化のため)
- チームに対してmentionする場合も同様に理由を添える。(例 /cc @github/security このやり方で問題ないですか?)
フィードバックへの対応
- とにかくまず感謝を表明する。
- 明確化するよう求める(「ねえよく分からないんだけど、もう少し説明してくれませんか?」)
- 質問されたら、なぜそのような実装に辿り着いたのか説明し、しっかりとわかってもらう
- できることなら、すべてのコメントに返信する
- 関連するコミットやプルリクエストにリンクを貼る(「1682851でしたやつ、名案だね!」)
- 議論の余地があったり混乱が見られる場合は、もっといい言葉をつかって彼らと会話できるのではないか自問してみる。対面で話し合っているつもりでやりとりし、オフラインで起きている議論を要約した続報をお互いに投稿してみる。(これから読む人に役にたちます)
Reference from
コードレビューまとめ
ざっと見てコードボリューム見る。 +400
くらいが妥当
コミット粒度とコメントを見てみる
ざっくり全体感を見る、splitで見る
Reviewをするときに、なぜそうするべきなのか、cons, prosを示し、参考リンクもはる。
hogeしたほうがいい。 fugaということが考えられるから。 具体的に示すとこんな感じ ` bar foo puts hoge` ref: http://tenshotanaka.hatenablog.com/
レビューコメントにラベルをつける
[MUST] 問題があり、必ず治す [IMO] 意見、緩やかな指摘。自分ならこう書くけどどう? [nits] ほんの小さな指摘。インデントやタイポ
- 問題の内容や、どうしてこのプルリクエストが発生したのか把握する
- 全く同意できない場合は、反応する前に数分自分の意見を検討する
- 命令するのではなく、質問する(「…しないでください」よりも「…についてどう思いますか?」)
- 誰かの作成した仕事を参照する際に、「バカな」などのような軽蔑的な言葉は避ける
- 謙虚にやる。(「あまり分からないけど、試してみましょう…」)
- 誇張を避ける。(「絶対に…しない」)
- オンラインのコミュニケーションでは、ネガティブなバイアスがかかることに注意する。(内容が中立であれば、我々はネガティブな発言だと仮定しがちです)。→肯定的な書き方をする
- 雰囲気を明確にするために絵文字を使う「いいじゃん」と「 :sparkles: :sparkles: いいじゃん :thumbsup: :sparkles: :sparkles: 」を比べてみてください。
Reference from
(随時更新) JS著名ツールなんとなくまとめ
Package manager
npm
- npm is the package manager for JavaScript and the world's largest software registry.
- a package manager for javascript
- npm makes it easy for JavaScript developers to share and reuse code, and makes it easy to update the code that you’re sharing, so you can build amazing things.
install
how to use
$ npm install <package> $ ls node_modules package-lock.json package.json
Reference from
bower
- A package manager for the web
...psst! While Bower is maintained, we recommend using Yarn and Webpack for front-end projects read how to migrate!
だそうです。
install
$ npm install -g bower
how to use
$ bower install <package> $ ls bower.json bower_components
Reference from
yarn
- FAST, RELIABLE, AND SECURE DEPENDENCY MANAGEMENT
install
$ brew install yarn
how to use
$ yarn init $ yarn add [package] $ ls node_modules package.json yarn.lock $ yarn install
Reference from
component
- frontend package manager and build tool for modular web applications
install
$ npm install -g component
how to use
$ ls component.json index.css index.html index.js $ component install necolas/normalize.css github remote: 54 of 60 requests remaining, resetting at Thu Oct 30 2014 00:23:36 GMT+0100 (CET) github remote: see https://github.com/component/guide/blob/master/changelogs/1.0.0.md#required-authentication for more information. installed : necolas/normalize.css@3.0.2 in 283ms install : complete $ cat component.json { "name": "my-first-component", "dependencies": { "necolas/normalize.css": "^3.0.2" }, "scripts": ["index.js"], "styles": ["index.css"] } $ component build $ ls build component.json index.css index.html index.js
Reference from
Duo
- Duo is a next-generation package manager that blends the best ideas from Component, Browserify and Go to make organizing and writing front-end code quick and painless.
install
$ npm install -g duo
how to use
$ cat index.js var uid = require('matthewmueller/uid'); var fmt = require('yields/fmt'); var msg = fmt('Your unique ID is %s!', uid()); window.alert(msg); $ duo index.js building : index.js using : compatibility using : stoj installed : yields-fmt@0.1.0 installed : matthewmueller-uid@0.0.2 built : index.js wrote : index.js $ ls build components index.js
<script src="build/index.js"></script>
Reference from
Loader
RequireJS
- RequireJS is a JavaScript file and module loader. It is optimized for in-browser use, but it can be used in other JavaScript environments, like Rhino and Node.
- A file and module loader for JavaScript
install
http://requirejs.org/docs/download.html#requirejs
how to use
project-directory/ index.html scripts/ main.js require.js helper/ util.js
<!DOCTYPE html> <html> <head> <title>My Sample Project</title> <!-- data-main attribute tells require.js to load scripts/main.js after require.js loads. --> <script data-main="scripts/main" src="scripts/require.js"></script> </head> <body> <h1>My Sample Project</h1> </body> </html>
requirejs(["helper/util"], function(util) { //This function is called when scripts/helper/util.js is loaded. //If util.js calls define(), then this function is not fired until //util's dependencies have loaded, and the util argument will hold //the module value for "helper/util". });
JavaScript 用のモジュール管理フレームワークの1つ。
JavaScript を実装していて、 view や model などで細かくファイルを分割していると、ファイル間の依存関係を意識して読み込む順序を注意しないといけなくなる。
ファイル数が少なかったり、個人で開発しているのであれば手動管理でも大きな問題はない。 しかし、ファイル数が多くなってきたり複数人で開発していると、手動管理では限界がある。
RequireJS では、 JavaScript のコードをモジュールという単位で管理する。 そして、各コードは実装の先頭で使用するモジュールを宣言する。
RequireJS は使用するモジュールの宣言を元に、各モジュール間の依存関係を調べ、適切な順序で JavaScript のコードを読み込むようにしてくれる(<script>
タグが自動で HTML に埋め込まれる)。
Reference from
- https://github.com/requirejs/requirejs
- https://qiita.com/opengl-8080/items/196213867b859daea719
- https://qiita.com/masarufuruya/items/b1f4195ea8c59431b464
Browserify
- Browserify lets you require('modules') in the browser by bundling up all of your dependencies.
- require('modules') in the browser
- モジュール間の依存解決やファイルの結合を行う
install
$ npm install -g browserify
how to use
Browsers don't have the require method defined, but Node.js does. Browserify you can write code that uses require in the same way that you would use it in Node.
var unique = require('uniq'); var data = [1, 2, 2, 3, 4, 5, 5, 5, 6]; console.log(unique(data));
$ npm install uniq $ ls index.html main.js node_modules/ $ browserify main.js -o bundle.js
<script src="bundle.js"></script>
Reference from
- https://github.com/browserify/browserify
- https://app.codegrid.net/entry/browserify-1
- https://qiita.com/cognitom/items/4c63969b5085c90639d4
Module bundlers
Browserify
- 省略
Webpack
- bundle your assets(scripts, images, styles)
- A bundler for javascript and friends. Packs many modules into a few bundled assets.
- webpack is a module bundler. Its main purpose is to bundle JavaScript files for usage in a browser, yet it is also capable of transforming, bundling, or packaging just about any resource or asset.
install
$ npm install -D webpack $ yarn add webpack --dev
how to use
webpack-demo |- package.json + |- index.html + |- /src + |- index.js
function component() { var element = document.createElement('div'); // Lodash, currently included via a script, is required for this line to work element.innerHTML = _.join(['Hello', 'webpack'], ' '); return element; } document.body.appendChild(component());
<html> <head> <title>Getting Started</title> <script src="https://unpkg.com/lodash@4.16.6"></script> </head> <body> <script src="./src/index.js"></script> </body> </html>
- 外部のライブラリに依存していることが見かけ上はわからない
- It is not immediately apparent that the script depends on an external library.
- 依存関係が考慮されていない
- If a dependency is missing, or included in the wrong order, the application will not function properly.
- 依存関係が含まれていたとしても、使われておらず、browserは余計なコードをダウンロードしてしまう
- If a dependency is included but not used, the browser will be forced to download unnecessary code.
Creating a Bundle
webpack-demo |- package.json + |- /dist + |- index.html - |- index.html |- /src |- index.js
To bundle the lodash dependency with index.js, we'll need to install the library locally...
$ npm install --save lodash
src/index.js
+ import _ from 'lodash'; + function component() { var element = document.createElement('div'); - // Lodash, currently included via a script, is required for this line to work + // Lodash, now imported by this script element.innerHTML = _.join(['Hello', 'webpack'], ' '); return element; } document.body.appendChild(component());
dist/index.html
<html> <head> <title>Getting Started</title> - <script src="https://unpkg.com/lodash@4.16.6"></script> </head> <body> - <script src="./src/index.js"></script> + <script src="bundle.js"></script> </body> </html>
The npx command, which ships with Node 8.2 or higher, runs the webpack binary (./node_modules/.bin/webpack) of the webpack package we installed in the beginning:
$ npx webpack src/index.js dist/bundle.js Hash: 80992cf8fa2cd6324ca0 Version: webpack 3.10.0 Time: 391ms Asset Size Chunks Chunk Names bundle.js 544 kB 0 [emitted] [big] main [0] ./src/index.js 267 bytes {0} [built] [2] (webpack)/buildin/global.js 509 bytes {0} [built] [3] (webpack)/buildin/module.js 517 bytes {0} [built] + 1 hidden module
Using a Configuration
Most projects will need a more complex setup, which is why webpack supports a configuration file.
webpack-demo
|- package.json
+ |- webpack.config.js
|- /dist
|- index.html
|- /src
|- index.js
const path = require('path'); module.exports = { entry: './src/index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') } };
$ npx webpack --config webpack.config.js Hash: 857f878815ce63ad5b4f Version: webpack 3.9.1 Time: 298ms Asset Size Chunks Chunk Names bundle.js 544 kB 0 [emitted] [big] main [0] ./src/index.js 222 bytes {0} [built] [2] (webpack)/buildin/global.js 509 bytes {0} [built] [3] (webpack)/buildin/module.js 517 bytes {0} [built] + 1 hidden module
webpack-demo |- package.json |- webpack.config.js |- /dist |- bundle.js |- index.html |- /src |- index.js |- /node_modules
Reference from
- https://github.com/webpack/webpack
- https://qiita.com/ossan-engineer/items/8352bdeab9ce8c8c00ef#_reference-10e4cb833cf135e7b2ef
- https://qiita.com/morrr/items/0f35adc38b59f5a67141
- https://techracho.bpsinc.jp/hachi8833/2017_12_26/49931
Parcel
- Blazing fast, zero configuration web application bundler
install
$ npm install -g parcel-bundler $ yarn global add parcel-bundler
how to use
<html> <body> <script src="./index.js"></script> </body> </html>
$ parcel index.html
$ cat package.json { "name": "parcel-sample", "version": "1.0.0", "description": "", "main": "index.js", "dependencies": { "parcel-bundler": "^1.3.1" }, "devDependencies": {}, "scripts": { "start": "parcel index.html" }, "keywords": [], "author": "", "license": "ISC" }
Bundler Time | --- |
---|---|
browserify | 22.98s |
webpack | 20.71s |
parcel | 9.98s |
parcel - with cache | 2.64s |
https://github.com/parcel-bundler/parcel#benchmarks
Parcel — Small to medium sized projects (<15k lines of code) Webpack — Large to enterprise sized projects. Rollup — For NPM packages.
Reference from
- https://medium.freecodecamp.org/all-you-need-to-know-about-parcel-dbe151b70082
- https://github.com/parcel-bundler/parcel
Task runners
Gulp
- Automate and enhance your workflow
- The streaming build system
install
$ npm install gulp-cli -g $ npm install gulp -D
how to use
$ ls gulpfile.js node_modules package-lock.json package.json $ cat package.json { "name": "gulp-sample", "version": "1.0.0", "description": "", "main": "gulpfile.js", "dependencies": {}, "devDependencies": { "gulp": "^3.9.1", "gulp-sass": "^3.1.0" }, "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC" }
$ npm install -D gulp gulp-sass
$ cat gulpfile.js const gulp = require('gulp'); const sass = require('gulp-sass'); gulp.task('default', function () { gulp.src('css/style.scss') .pipe(sass()) .pipe(gulp.dest('css')); });
$ npx gulp [16:42:47] Using gulpfile ~/src/local/frontend/gulp-sample/gulpfile.js [16:42:47] Starting 'default'... [16:42:47] Finished 'default' after 7.99 ms
onst gulp = require('gulp'); const sass = require('gulp-sass'); gulp.task('default', function () { gulp.watch('css/style.scss', function () { gulp.src('css/style.scss') .pipe(sass({ outputStyle: 'expanded' }) .on('error', sass.logError)) .pipe(gulp.dest('css')); }); });
$ npx gulp
Reference from
Grunt
- JavaScript Task Runner
install
$ npm install grunt -D $ npm install grunt-cli -D
how to use
$ ls Gruntfile.js node_modules package-lock.json package.json $ cat package.json { "name": "grunt-sample", "version": "1.0.0", "description": "", "main": "index.js", "dependencies": {}, "devDependencies": { "grunt": "^1.0.1", "grunt-cli": "^1.2.0", "grunt-contrib-cssmin": "^2.2.1", "grunt-contrib-watch": "^1.0.0", "grunt-init": "^0.3.2" }, "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC" } $ cat Gruntfile.js module.exports = function(grunt) { grunt.initConfig({ cssmin: { minify: { files: { 'css/style.min.css':'css/style.css' } } }, watch: { files: ['css/style.css'], tasks: ['cssmin'] } }); grunt.loadNpmTasks('grunt-contrib-cssmin'); grunt.loadNpmTasks('grunt-contrib-watch'); };
$ grunt watch Running "watch" task Waiting...
Reference from
Compiler
babel
- Babel is a JavaScript compiler.
install
ES2015 and beyond
$ npm install -D babel-cli babel-preset-env $ echo '{ "presets": ["env"] }' > .babelrc
Polyfill
$ npm install -D babel-polyfill
how to use
$ babel example.js --out-file compiled.js
import "babel-polyfill";
https://babeljs.io/docs/usage/polyfill/
Reference from
- https://github.com/babel/babel
- https://qiita.com/Sekky0905/items/4515203428d9715fde5f
- https://qiita.com/foursue/items/d80667eff2faed8613f2
まとめ
- 何よりやっているなのは、依存管理。package間、file間とかで依存管理をするtoolとかが多い。ということは依存管理というのはみんな苦労しているということか。
--- | github star count | stable version |
---|---|---|
npm | 14935 | 5.6.0 |
bower | 15286 | 1.8.2 |
yarn | 29386 | 1.3.2 |
component | 4635 | 1.1.0 |
duo | 3553 | 0.15.7 |
RequireJS | 11230 | 2.3.5 |
Browserify | 11635 | 14.5.0 |
Webpack | 35301 | 3.10.0 |
Parcel | 13451 | 1.3.1 |
Gulp | 28273 | CLI:2.0.0/Local version:3.9.1 |
Grunt | 11694 | CLI:1.2.0/Local version:1.0.1 |
Babel | 24910 | 6.26.0 |
golang/go | 35647 | 1.9.2 |
Reference from
いつも学校のreport書くときに迷うのでメモ、markdownをpdfに変換
$ markdown-pdf hoge.md $ ls hoge.md hoge.pdf
Reference from
rbenvによるrubyのバージョンを切り換え備忘録
$ ruby --version $ rbenv versions $ rbenv install -l $ rbenv install 2.5.0 $ rbenv global 2.5.0
global, local, shell
- global:
~/.rbenv/version
- local:
./.ruby-version
- shell:
RBENV_VERSION
- global:
インストールしたいrubyのバージョンがリストにない場合
$ brew update $ brew upgrade rbenv ruby-build
Reference from
headless-chromeとpuppeteerを使った、web操作の自動化とscraping
headless-chromeとpuppeteerを使った、web操作の自動化とscraping
puppeteerとは
Puppeteer is a Node library API that allows us to control headless Chrome.
$ npm i puppeteer
Headless Chromeとは
Headless Chrome is a way to run the Chrome Browser without actually running Chrome.
Taking a Screenshot
1 const puppeteer = require('puppeteer'); 2 3 async function getPic() { 4 const browser = await puppeteer.launch(); 5 const page = await browser.newPage(); 6 await page.goto('https://google.com'); 7 await page.screenshot({path: 'google.png'}); 8 9 await browser.close(); 10 } 11 12 getPic();
Something important to note is that our getPic() function is an async function and makes use of the new ES 2017 async/await features.
L4 We’re essentially launching an instance of Chrome and setting it equal to our newly created browser variable.
L5 Here we create a new page in our automated browser.
L6 In this example, we’re navigating to google. Our code will pause until the page has loaded.
L7 Now we’re telling Puppeteer to to take a screenshot of the current page
L9 we close down our browser
- const browser = await puppeteer.launch(); + const browser = await puppeteer.launch({headless: false});
you can actually watch Google Chrome work as it navigates through your code.
+ await page.setViewport({width: 1000, height: 500})
Scrape some Data
1 const puppeteer = require('puppeteer'); 2 3 let scrape = async () => { 4 const browser = await puppeteer.launch({headless: false}); 5 const page = await browser.newPage(); 6 7 await page.goto('http://books.toscrape.com/'); 8 await page.click('#default > div > div > div > div > section > div:nth-child(2) > ol > li:nth-child(1) > article > div.image_container > a > img'); 9 await page.waitFor(1000); 10 11 const result = await page.evaluate(() => { 12 let title = document.querySelector('h1').innerText; 13 let price = document.querySelector('.price_color').innerText; 14 15 return { 16 title, 17 price 18 } 19 20 }); 21 22 browser.close(); 23 return result; 24. }; 25 26 scrape().then((value) => { 27 console.log(value); // Success! 28 });
L8 We now have our selector copied and we can insert our click method into our program.
L11 In order to retrieve these values, we’ll use the page.evaluate() method. This method allows us to use built in DOM selectors like querySelector().
❯ node scrape.js { title: 'A Light in the Attic', price: '£51.77' }
Perfecting it
const page = await browser.newPage(); await page.goto('http://books.toscrape.com/'); - await page.click('#default > div > div > div > div > section > div:nth-child(2) > ol > li:nth-child(1) > article > div.image_container > a > img'); - await page.waitFor(1000); const result = await page.evaluate(() => { - let title = document.querySelector('h1').innerText; - let price = document.querySelector('.price_color').innerText; + let data = []; // Create an empty array that will store our data + let elements = document.querySelectorAll('.product_pod'); // Select all Products - return { - title, - price + for (var element of elements){ // Loop through each proudct + let title = element.childNodes[5].innerText; // Select the title + let price = element.childNodes[7].children[0].innerText; // Select the price + + data.push({title, price}); // Push an object with the data onto our array } + return data; // Return our data array }); browser.close();
感想
結構簡単なコードでいろいろ動かせるので、おもしろい。 ただ、今回なんとなくの理解だったES2017のasync/awaitは勉強したい。
https://github.com/tenshotanaka/scripts/pull/3/commits/51c934da451de50978401370f2bec908c97e47ad
Reference from
AltCSSについて雑多に書く。scss(sass), less, stylus
Sass
Summary
2014/3 version: 3.2.15 current release: 3.5.4
Sass can be used from the command line or as part of a web framework. The first step is to install the gem:
$ gem insatll sass
After you convert some CSS to Sass, you can run
$ sass style.scss
to compile it back to CSS. For more information on these commands, check out
自動コンパイル
$ sass --watch app/sass:public/stylesheets
option
$red:#FF3399; .red { color: $red; }
- nested - sassファイルのネストの深さが引き継がれます
$ sass style.scss:style.css --style nested
.red { color: #FF3399; } .red-.warning { font-weight: bold; }
- expanded - 典型的なCSSの記述スタイルにする
$ sass style.scss:style.css --style expanded
.red { color: #FF3399; } .red-.warning { font-weight: bold; }
- compact - セレクタと属性を1行で記述してくれます
$ sass style.scss:style.css --style compact
.red { color: #FF3399; } .red-.warning { font-weight: bold; }
- compressed - すごく圧縮してくれる方法。可読性は悪いが軽くなる
$ sass style.scss:style.css --style compressed
.red{color:#f39}.red-.warning{font-weight:bold}
Syntax
Variables
$font-stack: Helvetica, sans-serif $primary-color: #333 body font: 100% $font-stack color: $primary-color
Nesting
nav ul margin: 0 padding: 0 list-style: none li display: inline-block a display: block padding: 6px 12px text-decoration: none
Partials
You can create partial Sass files that contain little snippets of CSS that you can include in other Sass files.
You might name it something like _partial.scss.
Sass partials are used with the @import
directive.
// _reset.sass html, body, ul, ol margin: 0 padding: 0
// base.sass @import reset body font: 100% Helvetica, sans-serif background-color: #efefef
Mixins
=border-radius($radius) -webkit-border-radius: $radius -moz-border-radius: $radius -ms-border-radius: $radius border-radius: $radius .box +border-radius(10px)
When your CSS is generated it'll look like this:
.box { -webkit-border-radius: 10px; -moz-border-radius: 10px; -ms-border-radius: 10px; border-radius: 10px; }
Extend/Inheritance
.message border: 1px solid #ccc padding: 10px color: #333 .success @extend .message border-color: green .error @extend .message border-color: red .warning @extend .message border-color: yellow
This is what it looks like:
.message, .success, .error, .warning { border: 1px solid #cccccc; padding: 10px; color: #333; } .success { border-color: green; } .error { border-color: red; } .warning { border-color: yellow; }
Operators
.container width: 100% article[role="main"] float: left width: 600px / 960px * 100% aside[role="complementary"] float: right width: 300px / 960px * 100%
The generated CSS will look like:
.container { width: 100%; } article[role="main"] { float: left; width: 62.5%; } aside[role="complementary"] { float: right; width: 31.25%; }
scss(Sassy CSS)
Sass3.0からCSSちっくに書くことが出来るようになったsassの記法の一つ。
http://sass-lang.com/documentation/file.SCSS_FOR_SASS_USERS.html
Syntax
Variables
$font-stack: Helvetica, sans-serif; $primary-color: #333; body { font: 100% $font-stack; color: $primary-color; }
Nesting
nav { ul { margin: 0; padding: 0; list-style: none; } li { display: inline-block; } a { display: block; padding: 6px 12px; text-decoration: none; } }
Partials
You can create partial Sass files that contain little snippets of CSS that you can include in other Sass files.
You might name it something like _partial.scss.
Sass partials are used with the @import
directive.
// _reset.sass html, body, ul, ol margin: 0 padding: 0
// base.sass @import 'reset'; body { font: 100% Helvetica, sans-serif; background-color: #efefef; }
Mixins
@mixin border-radius($radius) { -webkit-border-radius: $radius; -moz-border-radius: $radius; -ms-border-radius: $radius; border-radius: $radius; } .box { @include border-radius(10px); }
When your CSS is generated it'll look like this:
.box { -webkit-border-radius: 10px; -moz-border-radius: 10px; -ms-border-radius: 10px; border-radius: 10px; }
Extend/Inheritance
.message { border: 1px solid #ccc; padding: 10px; color: #333; } .success { @extend .message; border-color: green; } .error { @extend .message; border-color: red; } .warning { @extend .message; border-color: yellow; }
This is what it looks like:
.message, .success, .error, .warning { border: 1px solid #cccccc; padding: 10px; color: #333; } .success { border-color: green; } .error { border-color: red; } .warning { border-color: yellow; }
Operators
.container { width: 100%; } article[role="main"] { float: left; width: 600px / 960px * 100%; } aside[role="complementary"] { float: right; width: 300px / 960px * 100%; }
The generated CSS will look like:
.container { width: 100%; } article[role="main"] { float: left; width: 62.5%; } aside[role="complementary"] { float: right; width: 31.25%; }
Less
2010/4/23 version: 1.0 current release: 2.7.3
Less. The dynamic stylesheet language.
$ npm install less -g or $ npm i less --save-dev
or
<script src="less.js"></script> <link rel="stylesheet/less" type="text/css" href="styles.less" />
https://github.com/less/less.js
compile
$ lessc bootstrap.less bootstrap.css
Syntax
Variables
// Variables @link-color: #428bca; // sea blue @link-color-hover: darken(@link-color, 10%); // Usage a, .link { color: @link-color; } a:hover { color: @link-color-hover; } .widget { color: #fff; background: @link-color; }
Variable Interpolation
// Variables @my-selector: banner; // Usage .@{my-selector} { font-weight: bold; line-height: 40px; margin: 0 auto; }
compiles to
.banner { font-weight: bold; line-height: 40px; margin: 0 auto; }
Nesting
#header { color: black; } #header .navigation { font-size: 12px; } #header .logo { width: 300px; }
In Less, we can also write it this way:
#header { color: black; .navigation { font-size: 12px; } .logo { width: 300px; } }
Partials
.foo { background: #900; } @import "this-is-valid.less";
@import statements may be treated differently by Less depending on the file extension:
@import "foo"; // foo.less is imported @import "foo.less"; // foo.less is imported @import "foo.php"; // foo.php imported as a Less file @import "foo.css"; // statement left in place, as-is
Mixins
.a, #b { color: red; } .mixin-class { .a(); } .mixin-id { #b(); }
outputs
.a, #b { color: red; } .mixin-class { color: red; } .mixin-id { color: red; }
Extend
nav ul { &:extend(.inline); background: blue; } .inline { color: red; }
outputs
nav ul { background: blue; } .inline, nav ul { color: red; }
Operators
// numbers are converted into the same units @conversion-1: 5cm + 10mm; // result is 6cm @conversion-2: 2 - 3cm - 5mm; // result is -1.5cm // conversion is impossible @incompatible-units: 2 + 5px - 3cm; // result is 4px // example with variables @base: 5%; @filler: @base * 2; // result is 10% @other: @base + @filler; // result is 15%
Stylus
2011/01/31 version: 0.0.1 current release: 0.54.5
https://github.com/stylus/stylus
Expressive, robust, feature-rich CSS language built for nodejs
$ npm install stylus -g
$ stylus -w style.styl -o style.css
Syntax
記法は、sassをさらに簡略化した感じ。でも、sass, scsss, less, css の書き方もできる。
#stylus background #eee padding 10px margin 0 0 10px h2 font-size 30px color blue .bikou font-size 0.8em &:before content "※"
Variables
font-size = 14px body font font-size Arial, sans-serif
Partials
@import "reset.css"
Along with @import, Stylus also has @require. It works almost in the same way, with the exception of importing any given file only once.
Mixins
border-radius(n) -webkit-border-radius n -moz-border-radius n border-radius n form input[type=button] border-radius(5px)
Compiles to:
form input[type=button] { -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; }
Extend
scss の@extendとほぼ一緒
.message { padding: 10px; border: 1px solid #eee; } .warning { @extend .message; color: #E2E21E; }
Operators
. [] ! ~ + - is defined ** * / % + - ... .. <= >= < > in == is != is not isnt is a && and || or ?: = := ?= += -= *= /= %= not if unless
結論
- それぞれ結構違うと思ったら、ほとんど変わらず、どの言語で作られているかの違いでしかなかった。だから書き方とはだいたい一緒なので、使うときも苦労しないと思う。
- ruby のprojectだったら、sass(scss)
- それ以外ならless, stylus みたいな区分でいいかな、まあパフォーマンスとか周辺ライブラリも考慮しつつ。
- lessは、コマンドのoption・仕様全体から言って、sassに比べて多機能な感じがする。でも書き方はscssに似てる。
- stylusは、書き方をかなり簡略化したい場合とかに、使えそう。
--- | sass(scss) | less | stylus | golang/go |
---|---|---|---|---|
github star count | 10843 | 15289 | 8708 | 35647 |
github watch count | 677 | 752 | 376 | 2604 |
github fork count | 1923 | 3458 | 1007 | 4874 |
made of | ruby | NodeJS | NodeJS | golang |
ベンダープレフィックスなどの記述をラクにするもの。
sass → compass less → nib