diff --git a/.codeclimate.yml b/.codeclimate.yml index b1b2114..1b449f2 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -4,3 +4,5 @@ engines: ratings: paths: - "**.rb" +exclude_paths: + - spec/**/* diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..6583489 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,41 @@ +Style/StringLiterals: + Enabled: false + +Style/Documentation: + Enabled: false + +Metrics/LineLength: + Enabled: false + +Style/TrailingComma: + Enabled: false + +Style/FileName: + Exclude: + - 'bin/**/*' + +Style/ClassAndModuleChildren: + Exclude: + - 'spec/**/*' + +Metrics/ModuleLength: + Exclude: + - 'spec/**/*' + +Style/GuardClause: + Enabled: false + +Style/IfUnlessModifier: + Enabled: false + +Style/DotPosition: + Enabled: false + +Style/SignalException: + Enabled: false + +Metrics/AbcSize: + Enabled: false + +Rails/TimeZone: + Enabled: false diff --git a/lib/cc/engine/csslint.rb b/lib/cc/engine/csslint.rb index 0eecfc4..9517c96 100644 --- a/lib/cc/engine/csslint.rb +++ b/lib/cc/engine/csslint.rb @@ -48,14 +48,31 @@ def results @results ||= Nokogiri::XML(csslint_xml) end + def build_files_with_exclusions(exclusions) + files = Dir.glob("**/*.css") + files.reject { |f| exclusions.include?(f) } + end + + def build_files_with_inclusions(inclusions) + inclusions.map do |include_path| + if include_path =~ %r{/$} + Dir.glob("#{include_path}/**/*.css") + else + include_path + end + end.flatten + end + def csslint_xml - exclusions = @engine_config['exclude_paths'] || [] - final_files = files.reject { |f| exclusions.include?(f) } - `csslint --format=checkstyle-xml #{final_files.join(" ")}` + `csslint --format=checkstyle-xml #{files_to_inspect.join(" ")}` end - def files - Dir.glob("**/*.css") + def files_to_inspect + if @engine_config["include_paths"] + build_files_with_inclusions(@engine_config["include_paths"]) + else + build_files_with_exclusions(@engine_config["exclude_paths"] || []) + end end end end diff --git a/spec/cc/engine/csslint_spec.rb b/spec/cc/engine/csslint_spec.rb index 730b8e9..7daee33 100644 --- a/spec/cc/engine/csslint_spec.rb +++ b/spec/cc/engine/csslint_spec.rb @@ -5,24 +5,81 @@ module CC module Engine describe CSSlint do let(:code) { Dir.mktmpdir } - let(:lint) { CSSlint.new(directory: code, io: nil, engine_config: {}) } - let(:content) { '#id { color: red; }' } + let(:engine_config) { {} } + let(:lint) do + CSSlint.new(directory: code, io: nil, engine_config: engine_config) + end + let(:id_selector_content) { '#id { color: red; }' } describe '#run' do it 'analyzes *.css files' do - create_source_file('foo.css', content) + create_source_file('foo.css', id_selector_content) expect{ lint.run }.to output(/Don't use IDs in selectors./).to_stdout end it "doesn't analyze *.scss files" do - create_source_file('foo.scss', content) + create_source_file('foo.scss', id_selector_content) expect{ lint.run }.to_not output.to_stdout end - def create_source_file(path, content) - File.write(File.join(code, path), content) + describe "with exclude_paths" do + let(:engine_config) { {"exclude_paths" => %w(excluded.css)} } + + before do + create_source_file("not_excluded.css", "p { margin: 5px }") + create_source_file("excluded.css", id_selector_content) + end + + it "excludes all matching paths" do + expect{ lint.run }.not_to \ + output(/Don't use IDs in selectors./).to_stdout + end + end + + describe "with include_paths" do + let(:engine_config) { + {"include_paths" => %w(included.css included_dir/)} + } + + before do + create_source_file("included.css", id_selector_content) + create_source_file( + "included_dir/file.css", "p { color: blue !important; }" + ) + create_source_file( + "included_dir/sub/sub/subdir/file.css", "img { }" + ) + create_source_file("not_included.css", "a { outline: none; }") + end + + it "includes all mentioned files" do + expect{ lint.run }.to \ + output(/Don't use IDs in selectors./).to_stdout + end + + it "expands directories" do + expect{ lint.run }.to output(/Use of !important/).to_stdout + expect{ lint.run }.to output(/Rule is empty/).to_stdout + end + + it "excludes any unmentioned files" do + expect{ lint.run }.not_to \ + output(/Outlines should only be modified using :focus/).to_stdout + end + + it "shouldn't call a top-level Dir.glob ever" do + expect(Dir).not_to receive(:glob).with("**/*.css") + expect{ lint.run }.to \ + output(/Don't use IDs in selectors./).to_stdout + end end end + + def create_source_file(path, content) + abs_path = File.join(code, path) + FileUtils.mkdir_p(File.dirname(abs_path)) + File.write(abs_path, content) + end end end end