勉強日記

チラ裏

vue-mode導入、eslint連携等

動機

今まではVue SFCの編集にはweb-modeを使っていたが、vueの名の付くモードを使ってみようかなと

導入

  1. M-x package-list-packages RET
  2. vue-mode探して入れる

設定

vue-mode

;; ========================================
;;  Vue SFCの設定
;; ========================================
(add-to-list 'auto-mode-alist '("\\.vue\\'" . vue-mode))

;; vue-mode時、node_modulesのパスを登録
(add-hook 'vue-mode-hook 'add-node-modules-path)

;; eslintによるflycheck
(require 'flycheck)
(flycheck-add-mode 'javascript-eslint 'vue-mode)
(flycheck-add-mode 'javascript-eslint 'vue-html-mode)
(flycheck-add-mode 'javascript-eslint 'css-mode)

;; tern-mode有効
(add-hook 'vue-mode-hook 'tern-mode)

;; vue-modeでflycheck有効にしたら、
;; 保存時にfixする
(add-hook 'vue-mode-hook
          (lambda ()
            (add-hook 'flycheck-mode-hook
                      (lambda()
                        (add-hook 'after-save-hook #'eslint-fix)))))

(provide 'vue-config)
  • flycheck-mode-hookの設定はクソ適当
    • after-save-hookでfixするのも乱暴な気がするのでたぶん将来外す

js-mode

;;;========================================
;;; JavaScript系の設定
;;;========================================

;; 拡張子jsのファイルを開いたときjs-modeに
(add-to-list 'auto-mode-alist '("\\.js$" . js-mode))

;; ========================================
;;  補完の設定
;;  company-tern
;; ========================================

;; depth絡みの不具合への対策
;; override
(defun company-tern-depth (candidate)
  "Return depth attribute for CANDIDATE. 'nil' entries are treated as 0."
  (let ((depth (get-text-property 0 'depth candidate)))
    (if (eq depth nil) 0 depth)))

(defun js-company-tern-hook ()
  (when (locate-library "tern")
    ;; .tern-port を作らない
    (setq tern-command '("tern" "--no-port-file"))
    (tern-mode t)))

(add-hook 'js-mode-hook 'js-company-tern-hook)

;; backend追加
(add-to-list 'company-backends 'company-tern)
;; company-dabbrev-codeは現在開いているバッファからワードを拾ってくる
;; (add-to-list 'company-backends '(company-tern :with company-dabbrev-code))

;; ========================================
;; jsdocコメント
;; C-ciにバインド
;; ========================================

(defun js-jsdoc-hook ()
  (local-set-key "\C-ci" 'js-doc-insert-function-doc)
  (local-set-key "@" 'js-doc-insert-tag))

(add-hook 'js-mode-hook 'js-jsdoc-hook)

;; ========================================
;; node_modulesのパスを通す
;; ========================================
(add-hook 'js-mode-hook 'add-node-modules-path)

(provide 'js-config)
  • vue-modemmm-modeを使用している
    • 1つのバッファの中で複数のモードを切り替えるやつ
  • vue-modeにおいて、<script>タグ内はjs-modeなので、js-mode-hookが発火する
    • 今まで使っていたjs2-modemmm-mode非対応なので使えない
      • 未定義変数を怒ってくれたりする
    • このさいlintはeslintに、formattingはprettierに任せることを決意。今までありがとうjs2-mode
  • jsdocコメントの付与はうまく動かないので何か対策を講じないといけない
    • <template>タグ上についちゃう

eslint側設定

  ...
  "devDependencies": {
    ...
    "eslint": "^5.15.1",
    "eslint-plugin-vue": "^5.2.2",
    ...
  },
  ...
  • .eslintrc
{
  "extends": [
      "eslint:recommended",
      "plugin:vue/recommended"
  ],
  "plugins": [
      "vue"
  ],
  "parserOptions": {
    "ecmaVersion": 6,
    "sourceType": "module"
  },
  "env": {
    "browser": true,
    "amd": true
  }
}
  • 今まではjs2-modeがlintしてくれていた
  • 今後はeslintにやってもらう
  • <template><script>を含むファイルをパースするためにプラグインが必要
  • ほか、requireを認識させている(env.amd = true)

補完・定義ジャンプの設定

.tern-project

{
  "ecmaVersion": 6,
  "libs": [
    "browser"
  ],
  "dontLoad": [
      "**/*.prod.js"
  ],
  "plugins": {
    "requirejs": {},
    "node": {},
    "modules": {},
    "es_modules": {}
  }
}
  • JS補完のバックエンドternの設定
    • 実行時にしかわからなそうな情報も拾ってくれるスゴい奴
  • 定義ジャンプしたら難読化後コードで無事死亡したので*.prod.jsを除外