From 1cafcecc38955c766393dd04646bc16a43d1ea07 Mon Sep 17 00:00:00 2001 From: Dennis Paagman Date: Fri, 2 Oct 2020 08:49:38 +0200 Subject: [PATCH] Add pre commit hook for erblint --- config/default.yml | 7 +++ lib/overcommit/hook/pre_commit/erb_lint.rb | 20 +++++++++ .../hook/pre_commit/erb_lint_spec.rb | 45 +++++++++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 lib/overcommit/hook/pre_commit/erb_lint.rb create mode 100644 spec/overcommit/hook/pre_commit/erb_lint_spec.rb diff --git a/config/default.yml b/config/default.yml index 27794ffe..748476e8 100644 --- a/config/default.yml +++ b/config/default.yml @@ -275,6 +275,13 @@ PreCommit: - '**/*.ex' - '**/*.exs' + ErbLint: + enabled: false + description: 'Analyze with ERB Lint' + required_executable: 'erblint' + install_command: 'bundle install erb_lint' + include: '**/*.html.erb' + EsLint: enabled: false description: 'Analyze with ESLint' diff --git a/lib/overcommit/hook/pre_commit/erb_lint.rb b/lib/overcommit/hook/pre_commit/erb_lint.rb new file mode 100644 index 00000000..2073538c --- /dev/null +++ b/lib/overcommit/hook/pre_commit/erb_lint.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +module Overcommit::Hook::PreCommit + # Runs `erblint` against any modified ERB files. + # + # @see https://github.com/Shopify/erb-lint + class ErbLint < Base + MESSAGE_REGEX = /(?.+)\nIn file: (?.+):(?\d+)/ + + def run + result = execute(command, args: applicable_files) + return :pass if result.success? + + extract_messages( + result.stdout.split("\n\n")[1..-1], + MESSAGE_REGEX + ) + end + end +end diff --git a/spec/overcommit/hook/pre_commit/erb_lint_spec.rb b/spec/overcommit/hook/pre_commit/erb_lint_spec.rb new file mode 100644 index 00000000..fcb17199 --- /dev/null +++ b/spec/overcommit/hook/pre_commit/erb_lint_spec.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Overcommit::Hook::PreCommit::ErbLint do + let(:config) { Overcommit::ConfigurationLoader.default_configuration } + let(:context) { double('context') } + subject { described_class.new(config, context) } + + before do + subject.stub(:applicable_files).and_return(%w[file1.html.erb file2.html.erb]) + end + + context 'when erblint exits successfully' do + before do + result = double('result') + result.stub(:success?).and_return(true) + subject.stub(:execute).and_return(result) + end + + it { should pass } + end + + context 'when erblint exits unsucessfully' do + let(:result) { double('result') } + + before do + result.stub(:success?).and_return(false) + subject.stub(:execute).and_return(result) + end + + context 'and it reports an error' do + before do + result.stub(:stdout).and_return(<<-MSG) +Linting 1 files with 14 linters... + +erb interpolation with '<%= (...).html_safe %>' in this context is never safe +In file: app/views/posts/show.html.erb:10 +MSG + end + + it { should fail_hook } + end + end +end