80
80

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

JavaScript、HTML、CSSを簡単にLintできる開発環境を作った

Last updated at Posted at 2016-05-22

はじめに

FrontEndのフレームワークに依存せず、JavaScriptとHTML、CSSに対してLintを行い、Visual Studio CodeとJenkinsでLint結果を確認できる開発環境を作ったので、その使い方を書きます。

コンセプト

  • JavaScriptのLintにはESLintを使う
  • HTMLのLintにはHTMLHintを使う
  • CSSのLintにはCSSLintを使う
  • 開発環境はVisual Studio Codeを使う
  • CIツールはJenkinsを使う
  • Jenkinsからは、手間がかからないようにLint結果のレポート形式をCheckStyle形式で統一する
  • Visual Studio Codeの設定を合わせるため、EditorConfigの設定も含める

seedプロジェクト

frontend-lint-seedとしてGitHub上に公開しています。

開発環境のセットアップ

  • Visual Studio Codeをインストールする。バージョンは1.0以上。
  • 次のVisual Studio Code Extensionをインストールする。
    • ext install EditorConfig
    • ext install ESLint
    • ext install HTMLHint
    • ext install CSSLint
  • プロジェクトをgit cloneし、npm install を行う。

使い方

セットアップが完了すればVisual Studio Code上でJavaScript、HTML、CSSのLintエラーが表示される。Jenkins用にCheckStyle形式のレポートを生成するには次のコマンドを実行する。Lintレポートはreports以下に生成される。

$ npm run lint

プロジェクト構成

app以下はサンプルです。Lintエラーが出るようにルールに違反したコードになっています。

.
├── .csslintrc
├── .editorconfig
├── .eslintrc
├── .htmlhintrc
├── .vscode
│   ├── settings.json
│   └── tasks.json
├── app
│   ├── index.html
│   ├── main.html
│   ├── scripts
│   │   ├── index.js
│   │   └── main.js
│   └── styles
│       ├── index.css
│       └── main.css
├── gulpfile.js
├── package.json
└── reports
    ├── csslint-checkstyle.xml
    ├── eslint-checkstyle.xml
    └── htmlhint-checkstyle.xml

.vscode/settings.json

内容はほぼデフォルトのままですが、フォントをMac用には"Monaco"、Windows用には"Consolas"を指定しています。

.vscode/settings.json
{
    // Controls the font family.
    "editor.fontFamily": "Monaco, Consolas",
    // Controls visibility of line numbers
    "editor.lineNumbers": true,
    // Controls the rendering size of tabs in characters. Accepted values: "auto", 2, 4, 6, etc. If set to "auto", the value will be guessed when a file is opened.
    "editor.tabSize": 2,
    // Controls if the editor will insert spaces for tabs. Accepted values:  "auto", true, false. If set to "auto", the value will be guessed when a file is opened.
    "editor.insertSpaces": true,
    // Controls after how many characters the editor will wrap to the next line. Setting this to 0 turns on viewport width wrapping
    "editor.wrappingColumn": 200,
    // Controls whether the editor should render whitespace characters
    "editor.renderWhitespace": true,
    //-------- Files configuration --------
    // Configure glob patterns for excluding files and folders.
    "files.exclude": {
        "**/.git": true,
        "**/.svn": true,
        "**/.DS_Store": true
    },
    // The default character set encoding to use when reading and writing files.
    "files.encoding": "utf8",
    //-------- Search configuration --------
    // Configure glob patterns for excluding files and folders in searches. Inherits all glob patterns from the file.exclude setting.
    "search.exclude": {
        "**/node_modules": true,
        "**/bower_components": true
    }
}

.editorconfig

やろうと思えばJS、HTML、CSSでindent_sizeを変えるなどできるが現状は統一しています。
EditorConfigの設定についてはこちらを参照。

.editorconfig
# http://editorconfig.org
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false

.eslintrc

ESLintルールのベースは"eslint:recommended"を使用している。必要に応じてカスタマイズすること。
ESLintのルールについてはこちらを参照。

.eslintrc
{
  "extends": "eslint:recommended",
  "env": {
    "node": true,
    "browser": true
  },
  "rules": {
    "semi": 2,
    "quotes": [2, "single", "avoid-escape"]
  },
  "globals": {}
}

.htmlhintrc

HTMLHintルールはデフォルトから"doctype-first"をfalseに。Component用のHTMLテンプレートを書くことがあるため。
HTMLHintのルールについてはこちらを参照。

.htmlhintrc
{
  "tagname-lowercase": true,
  "attr-lowercase": true,
  "attr-value-double-quotes": true,
  "doctype-first": false,
  "tag-pair": true,
  "tag-self-close": true,
  "spec-char-escape": true,
  "id-unique": true,
  "src-not-empty": true,
  "attr-no-duplication": true,
  "title-require": true,
  "doctype-html5": true,
  "space-tab-mixed-disabled": "space"
}

.csslintrc

CSSLintルールはひとまずの仮決めです。今後運用してカスタマイズする。
CSSLintのルールについてはこちらを参照。

.csslintrc
{
  "adjoining-classes": true,
  "box-model": true,
  "box-sizing": true,
  "bulletproof-font-face": false,
  "compatible-vendor-prefixes": true,
  "display-property-grouping": true,
  "duplicate-background-images": true,
  "duplicate-properties": true,
  "empty-rules": true,
  "fallback-colors": true,
  "floats": false,
  "font-faces": true,
  "font-sizes": true,
  "gradients": true,
  "ids": false,
  "import": false,
  "important": true,
  "known-properties": true,
  "non-link-hover": true,
  "outline-none": true,
  "overqualified-elements": false,
  "qualified-headings": true,
  "regex-selectors": false,
  "shorthand": false,
  "star-property-hack": true,
  "text-indent": false,
  "underscore-property-hack": true,
  "vendor-prefix": true,
  "unique-headings": false,
  "universal-selector": true,
  "unqualified-attributes": false,
  "zero-units": false
}

gulpfile.js

Lintの実行にはgulpを使っています。htmlhintの部分はゴリゴリでスマートさに欠けるが、まずは期待する結果を出すことを優先した。

gulpfile.js
var gulp = require('gulp');
var gulpLoadPlugins = require('gulp-load-plugins');
var $ = gulpLoadPlugins();
var del = require('del');
var vinylPaths = require('vinyl-paths');

var REPORT_DIR = 'reports/';
var ESLINT_FILE_NAME = 'eslint-checkstyle.xml';
var CSSLINT_FILE_NAME = 'csslint-checkstyle.xml';
var HTMLHINT_FILE_NAME = 'htmlhint-checkstyle.xml';

gulp.task('eslint', function () {
  var fs = require('fs');
  gulp.src('app/scripts/**/*.js')
    .pipe($.eslint('.eslintrc'))
    .pipe($.eslint.format('checkstyle', fs.createWriteStream(REPORT_DIR + ESLINT_FILE_NAME)));
});

gulp.task('csslint',
  $.shell.task('csslint --format=checkstyle-xml app/styles > ' + REPORT_DIR + CSSLINT_FILE_NAME)
);

process.env.HTMLHINT_CHECKSTYLE_FILE = REPORT_DIR + HTMLHINT_FILE_NAME;
gulp.task('htmlhint', function () {
  gulp.src('app/**/*.html')
    .pipe($.htmlhint('.htmlhintrc'))
    .pipe($.htmlhint.reporter('gulp-htmlhint-checkstyle-file-reporter'))
    .pipe(gulp.dest(REPORT_DIR + '.tmp'))
    .on('end', function () {
      gulp.src(REPORT_DIR + '*.tmp.*')
        .pipe(vinylPaths(del))
        .pipe($.concat(HTMLHINT_FILE_NAME))
        .pipe($.header('<?xml version="1.0" encoding="utf-8"?>\n<checkstyle version="4.3">\n'))
        .pipe($.footer('\n</checkstyle>'))
        .pipe(gulp.dest(REPORT_DIR))
        .on('end', function () {
          del([REPORT_DIR + '.tmp']);
        });
    });
});

gulp.task('lint', ['eslint', 'csslint', 'htmlhint'], function () {
  gulp.src(REPORT_DIR + '*.xml')
    .pipe($.prettyData({ type: 'prettify' }))
    .pipe(gulp.dest(REPORT_DIR));
});

gulp.task('lint:clean', function () {
  return del([REPORT_DIR + '*.*']);
});

gulp.task('default', ['lint:clean'], function () {
  gulp.start('lint');
});

終わりに

  • 各種ルールの設定は今後運用しながらカスタマイズする。
  • Vidual Studio Codeで開発する際とCIツールで確認する際で同じルールでチェックできるのは便利。
  • 一からこのような環境を作ると、各種Lintツール、gulp、Jenkinsとの連携などぞれぞれの要素ではまることになるので、その手間をなくして、本質的な開発に集中したい。
  • よりよいやり方があったらぜひコメントやPRをもらえるとありがたいです。
80
80
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
80
80

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?