インストール
node -v && yarn -v
# v10.5.0
# 1.8.0
yarn add -D prettier
# └─ prettier@1.13.7
オプション
prettier
にはどのようなオプションがあり、それを設定すると、どうコードが整形されるかが分からなかったので、v1.13.7
現在のオプションと整形結果をざっと書いていきます。
デフォルト
{
"printWidth": 80,
"tabWidth": 2,
"useTabs": false,
"semi": true,
"singleQuote": false,
"trailingComma": "none",
"bracketSpacing": true,
"jsxBracketSameLine": false,
"arrowParens": "avoid",
"rangeStart": 0,
"rangeEnd": Infinity,
"parser": "babylon",
"filepath": undefined,
"requirePragma": false,
"insertPragma": false,
"proseWrap": "preserve"
}
上記がオプション指定無しの設定のようです。v1.13.7/docs/options
下記のプログラムを
// const code = `
describe('API',()=>{
it('black 10x10 rect',done =>{
let black= fs.readFileSync('test/10x10.png')
pixel.parse(black)
.then(images =>{
let svg= pixelToSvg.convert(images[0])
let $= cheerio.load(svg)
let {width,height}= $('svg').attr()
let colors= $('path').length
let underFileSize= svg.length < limitFileSize
equal(width,10)
equal(height,10)
equal(colors,1)
equal(underFileSize,true)
done()
})
})
})
// `
console.log(require('prettier').format(code, opts))
のように実行すると、以下のように整形されます。
describe("API", () => {
it("black 10x10 rect", done => {
let black = fs.readFileSync("test/10x10.png");
pixel.parse(black).then(images => {
let svg = pixelToSvg.convert(images[0]);
let $ = cheerio.load(svg);
let { width, height } = $("svg").attr();
let colors = $("path").length;
let underFileSize = svg.length < limitFileSize;
equal(width, 10);
equal(height, 10);
equal(colors, 1);
equal(underFileSize, true);
done();
});
});
});
printWidth
opts={printWidth:30}
とした場合
describe("API", () => {
it("black 10x10 rect", done => {
let black = fs.readFileSync(
"test/10x10.png"
);
pixel
.parse(black)
.then(images => {
let svg = pixelToSvg.convert(
/// ...
tabWidth
opts={tabWidth:8}
とした場合
describe("API", () => {
it("black 10x10 rect", done => {
let black = fs.readFileSync("test/10x10.png");
pixel.parse(black).then(images => {
let svg = pixelToSvg.convert(images[0]);
/// ...
useTabs
opts={useTabs:true}
とした場合
describe("API", () => {
it("black 10x10 rect", done => {
let black = fs.readFileSync("test/10x10.png");
pixel.parse(black).then(images => {
let svg = pixelToSvg.convert(images[0]);
///...
※ qiita上では半角スペースで表示されるようです
semi
opts={semi:false}
とした場合
describe("API", () => {
it("black 10x10 rect", done => {
let black = fs.readFileSync("test/10x10.png")
pixel.parse(black).then(images => {
let svg = pixelToSvg.convert(images[0])
///...
singleQuote (Quotes)
opts={singleQuote:true}
とした場合
describe('API', () => {
it('black 10x10 rect', done => {
let black = fs.readFileSync('test/10x10.png');
pixel.parse(black).then(images => {
let svg = pixelToSvg.convert(images[0]);
///...
trailingComma
opts={trailingComma:"es5",printWidth:30}
とした場合
///...
let $ = cheerio.load(
svg
);
let {
width,
height,
} = $("svg").attr();
///...
opts={trailingComma:"all",printWidth:30}
とした場合
///...
let $ = cheerio.load(
svg,
);
let {
width,
height,
} = $("svg").attr();
///...
bracketSpacing
opts={bracketSpacing:false}
とした場合
///...
let {width, height} = $("svg").attr();
///...
jsxBracketSameLine (JSX Brackets)
リンク先参照。
arrowParens (Arrow Function Parentheses)
opts={arrowParens:"always"}
とした場合
describe("API", () => {
it("black 10x10 rect", (done) => {
let black = fs.readFileSync("test/10x10.png");
pixel.parse(black).then((images) => {
///...
rangeStart
, rangeEnd
(Range)
リンク先参照。
parser
opts={parser:"markdown"}
とした場合、codeはmarkdownとしてマークダウン内のjsが整形されるようです。
filepath
リンク先参照。
insertPragma
opts={insertPragma:true}
とした場合
/** @format */
describe("API", () => {
///...
requirePragma
opts={requirePragma:true}
とした場合
describe('API',()=>{
it('black 10x10 rect',done =>{
let black= fs.readFileSync('test/10x10.png')
pixel.parse(black)
///...
code
内に既に/** @format */
が存在する場合のみ、整形されます
proseWrap
markdown用のオプションです。
opts={parser:"markdown",proseWrap:"never"}
とした場合、平文などが一行にまとめられます。
eslintと併用する
---
parser: babel-eslint
extends:
- plugin:prettier/recommended
rules:
prettier/prettier:
- error
-
printWidth: 80
tabWidth: 2
useTabs: false
semi: true
singleQuote: false
trailingComma: none
bracketSpacing: true
jsxBracketSameLine: false
arrowParens: avoid
prettier
に加え、いくつかのモジュールが必要になります。
yarn add -D babel-eslint eslint eslint-config-prettier eslint-plugin-prettier
# ├─ babel-eslint@8.2.5
# ├─ eslint-config-prettier@2.9.0
# ├─ eslint-plugin-prettier@2.6.1
# └─ eslint@5.0.1
整形対象がeslintのエラーとして表示されるようになり、--fix
でprettierの整形が行えるようになります。
npx eslint index.js
# 1:10 error Replace `'API',()=>` with `"API",·()·=>·` prettier/prettier
# 2:6 error Replace `'black·10x10·rect',done·=>` with `"black·10x10·rect",·done·=>·` prettier/prettier
# 3:14 error Replace `=·fs.readFileSync('test/10x10.png')` with `·=·fs.readFileSync("test/10x10.png");` prettier/prettier
# 4:23 error Replace `⏎····.then(images·=>` with `.then(images·=>·` prettier/prettier
# 6:14 error Replace `=·pixelToSvg.convert(images[0])` with `·=·pixelToSvg.convert(images[0]);` prettier/prettier
npx eslint index.js --fix
cat index.js
# describe("API", () => {
# it("black 10x10 rect", done => {
# let black = fs.readFileSync("test/10x10.png");
# pixel.parse(black).then(images => {
# ...
eslint-config-vue + standardと併用する
eslint-config-vue
と併用する場合は、下記のように追記します。
# parser: babel-eslint
parserOptions:
parser: babel-eslint
ecmaVersion: 2017
sourceType: module
env:
browser: true
extends:
- standard
- plugin:vue/recommended
- plugin:prettier/recommended
# ...
yarn add -D eslint-config-standard
# └─ eslint-config-standard@11.0.0
yarn add -D eslint-plugin-standard eslint-plugin-import eslint-plugin-node eslint-plugin-promise
# ├─ eslint-plugin-import@2.13.0
# ├─ eslint-plugin-node@6.0.1
# ├─ eslint-plugin-promise@3.8.0
# └─ eslint-plugin-standard@3.1.0
yarn add -D eslint-plugin-vue@next
# └─ eslint-plugin-vue@4.0.0
<template>
<div>
<ul>
<li v-for="tweet in tweets" :key="tweet.id_str">
{{tweet.id}}{{tweet.name}}
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
tweets: []
}
}
}
</script>
<style scoped>
p{font-weight:bold}
li{font-family:monospace}
</style>
npx eslint src --ext vue --fix
<template>
<div>
<ul>
<li v-for="tweet in tweets" :key="tweet.id_str">
{{ tweet.id }}{{ tweet.name }}
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
tweets: []
}
}
}
</script>
<style scoped>
p {
font-weight: bold;
}
li {
font-family: monospace;
}
</style>
Atomで.vue
を--fix
する場合、linter-eslintの設定を修正する必要があります。
eslint-config-airbnbと併用する(react用)
eslint-config-airbnb
と併用する場合は、下記のように追記します。
# ...
extends:
- airbnb
- plugin:react/recommended
- plugin:prettier/recommended
- prettier/react
# ...
yarn add -D eslint-config-airbnb
# eslint-config-airbnb@17.0.0" has incorrect peer dependency "eslint@^4.19.1".
# eslint-config-airbnb@17.0.0" has unmet peer dependency "eslint-plugin-import@^2.12.0".
# eslint-config-airbnb@17.0.0" has unmet peer dependency "eslint-plugin-jsx-a11y@^6.0.3".
# eslint-config-airbnb@17.0.0" has unmet peer dependency "eslint-plugin-react@^7.9.1".
# └─ eslint-config-airbnb@17.0.0
yarn add -D eslint-plugin-import eslint-plugin-jsx-a11y eslint-plugin-react
# ├─ eslint-plugin-import@2.13.0
# ├─ eslint-plugin-jsx-a11y@6.0.3
# └─ eslint-plugin-react@7.10.0
import React from 'react'
import {render} from 'react-dom'
render(
<h1>Hello, world!</h1>,
document.getElementById('root')
);
npx eslint main.jsx --fix
# /Users/59naga/Downloads/REPOS/prettier-cheat/index.js
# 1:19 error Unable to resolve path to module 'react' import/no-unresolved
# 2:24 error Unable to resolve path to module 'react-dom' import/no-unresolved
# 4:32 error 'document' is not defined
import React from "react";
import { render } from "react-dom";
render(<h1>Hello, world!</h1>, document.getElementById("root"));
# (node:9942) [ESLINT_LEGACY_OBJECT_REST_SPREAD] DeprecationWarning: The 'parserOptions.ecmaFeatures.experimentalObjectRestSpread' option is deprecated. Use 'parserOptions.ecmaVersion' instead. (found in "node_modules/eslint-config-airbnb-base/index.js")
eslint-config-airbnb@17.0.0
現在、eslint@5.0.1
との互換性が保証されていませんので、eslint@4
の使用を推奨します。
eslint-config-flowtypeと併用する
eslint-config-flowtype
と併用する場合は、下記のように追記します。
# ...
extends:
- airbnb
- plugin:flowtype/recommended
- plugin:prettier/recommended
- prettier/react
plugins:
- flowtype
settings:
flowtype:
onlyFilesWithFlowAnnotation: true
# ...
yarn add -D eslint-plugin-flowtype
# └─ eslint-plugin-flowtype@2.49.3
// @flow
import React from "react";
import { render } from "react-dom";
type Props = { label?: string };
type State = { count: number };
class MyComponent extends React.Component<Props, State> {
// static defaultProps = {
// label: "Count"
// };
state = {
count: 0
};
componentDidMount() {
setInterval(() => {
this.setState(prevState => ({
count: prevState.count + 1
}));
}, 1000);
}
render() {
const { count } = this.state;
const { label } = this.props;
return (
<div>
<p>
{label} {count}
</p>
</div>
);
}
}
render(<MyComponent label="Count" />, document.getElementById("root"));
npx eslint main.jsx
# /Users/59naga/Downloads/REPOS/prettier-cheat/main.jsx
# 5:16 error propType "label" is not required, but has no corresponding defaultProp declaration react/require-default-props
# ...
flowの警告は、--fix
を使わず手動で直すものが殆どと思います。(上記はstatic
部分のコメントを戻すと警告は消えます)
必要に応じて、IDEからも警告を出したり、--fix
できると使いやすいです。(自分はATOMのlinter-eslint
,linter-flow
を使っています)