From 91cd154138df2aaeb76b67bba4f62426ce243165 Mon Sep 17 00:00:00 2001 From: Denis Defreyne Date: Sat, 18 May 2019 09:48:01 +0200 Subject: [PATCH] Allow specifying excluded files across all checks This allows specifying files to exclude across all checks. Previously, each check had its own way to specify files to exclude. To exclude certain files, list then under the `exclude_files` property, under the `all` property of `checks`, e.g. ``` checks: all: exclude_files: - bad.html - worse.html ``` Closes nanoc/features#51. --- .../lib/nanoc/core/configuration-schema.json | 12 ++ .../spec/nanoc/core/configuration_spec.rb | 20 +++ nanoc/lib/nanoc/checking/check.rb | 16 +++ nanoc/spec/nanoc/checking/check_spec.rb | 116 ++++++++++++++++-- 4 files changed, 157 insertions(+), 7 deletions(-) diff --git a/nanoc-core/lib/nanoc/core/configuration-schema.json b/nanoc-core/lib/nanoc/core/configuration-schema.json index d157e0509f..e74cf05723 100644 --- a/nanoc-core/lib/nanoc/core/configuration-schema.json +++ b/nanoc-core/lib/nanoc/core/configuration-schema.json @@ -78,6 +78,18 @@ "checks": { "type": "object", "properties": { + "all": { + "type": "object", + "additionalProperties": false, + "properties": { + "exclude_files": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, "internal_links": { "type": "object", "additionalProperties": false, diff --git a/nanoc-core/spec/nanoc/core/configuration_spec.rb b/nanoc-core/spec/nanoc/core/configuration_spec.rb index 2756d25e46..f68e643530 100644 --- a/nanoc-core/spec/nanoc/core/configuration_spec.rb +++ b/nanoc-core/spec/nanoc/core/configuration_spec.rb @@ -647,6 +647,26 @@ end end + context 'invalid checks (all has invalid type)' do + let(:hash) do + { checks: { all: 123 } } + end + + it 'passes' do + expect { subject }.to raise_error(JsonSchema::Error) + end + end + + context 'invalid checks (all.exclude_files has invalid type)' do + let(:hash) do + { checks: { all: { exclude_files: 'everything' } } } + end + + it 'passes' do + expect { subject }.to raise_error(JsonSchema::Error) + end + end + context 'invalid checks (internal_links has invalid type)' do let(:hash) do { checks: { internal_links: 123 } } diff --git a/nanoc/lib/nanoc/checking/check.rb b/nanoc/lib/nanoc/checking/check.rb index 8e95f5a56f..b38bbeffe9 100644 --- a/nanoc/lib/nanoc/checking/check.rb +++ b/nanoc/lib/nanoc/checking/check.rb @@ -12,6 +12,8 @@ def initialize(directory_path) class Check < Nanoc::Core::Context extend DDPlugin::Plugin + DDMemoize.activate(self) + attr_reader :issues def self.define(ident, &block) @@ -66,6 +68,20 @@ def add_issue(desc, subject: nil) @issues << Issue.new(desc, subject, self.class) end + # @private + def output_filenames + super.reject { |f| excluded_patterns.any? { |pat| pat.match?(f) } } + end + + # @private + memoized def excluded_patterns + @config + .fetch(:checks, {}) + .fetch(:all, {}) + .fetch(:exclude_files, []) + .map { |pattern| Regexp.new(pattern) } + end + # @private def output_html_filenames output_filenames.select { |f| File.extname(f) =~ /\A\.x?html?\z/ } diff --git a/nanoc/spec/nanoc/checking/check_spec.rb b/nanoc/spec/nanoc/checking/check_spec.rb index 71574f7685..6e4c1a3cd2 100644 --- a/nanoc/spec/nanoc/checking/check_spec.rb +++ b/nanoc/spec/nanoc/checking/check_spec.rb @@ -54,11 +54,97 @@ end end + describe '#output_filenames' do + subject { check.output_filenames } + + let(:check) do + described_class.new( + output_filenames: output_filenames, + config: Nanoc::ConfigView.new(config, view_context), + ) + end + + let(:config) do + Nanoc::Core::Configuration.new( + dir: Dir.getwd, + hash: config_hash, + ) + end + + let(:config_hash) { {} } + + let(:view_context) do + double(:view_context, dependency_tracker: dependency_tracker) + end + + let(:dependency_tracker) do + double(:dependency_tracker).tap do |dt| + allow(dt).to receive(:bounce) + end + end + + let(:output_filenames) do + [ + 'output/foo.html', + 'output/foo.htm', + 'output/foo.xhtml', + 'output/foo.txt', + 'output/foo.htmlx', + 'output/foo.yhtml', + ] + end + + context 'when exclude_files is unset' do + it { is_expected.to include('output/foo.htm') } + it { is_expected.to include('output/foo.html') } + it { is_expected.to include('output/foo.htmlx') } + it { is_expected.to include('output/foo.txt') } + it { is_expected.to include('output/foo.xhtml') } + it { is_expected.to include('output/foo.yhtml') } + end + + context 'when exclude_files is set' do + let(:config_hash) do + { checks: { all: { exclude_files: ['foo.xhtml'] } } } + end + + it { is_expected.to include('output/foo.htm') } + it { is_expected.to include('output/foo.html') } + it { is_expected.to include('output/foo.htmlx') } + it { is_expected.to include('output/foo.txt') } + it { is_expected.to include('output/foo.yhtml') } + + it { is_expected.not_to include('output/foo.xhtml') } + end + end + describe '#output_html_filenames' do subject { check.output_html_filenames } let(:check) do - described_class.new(output_filenames: output_filenames) + described_class.new( + output_filenames: output_filenames, + config: Nanoc::ConfigView.new(config, view_context), + ) + end + + let(:config) do + Nanoc::Core::Configuration.new( + dir: Dir.getwd, + hash: config_hash, + ) + end + + let(:config_hash) { {} } + + let(:view_context) do + double(:view_context, dependency_tracker: dependency_tracker) + end + + let(:dependency_tracker) do + double(:dependency_tracker).tap do |dt| + allow(dt).to receive(:bounce) + end end let(:output_filenames) do @@ -72,12 +158,28 @@ ] end - it { is_expected.to include('output/foo.html') } - it { is_expected.to include('output/foo.htm') } - it { is_expected.to include('output/foo.xhtml') } + context 'when exclude_files is unset' do + it { is_expected.to include('output/foo.html') } + it { is_expected.to include('output/foo.htm') } + it { is_expected.to include('output/foo.xhtml') } - it { is_expected.not_to include('output/foo.txt') } - it { is_expected.not_to include('output/foo.htmlx') } - it { is_expected.not_to include('output/foo.yhtml') } + it { is_expected.not_to include('output/foo.txt') } + it { is_expected.not_to include('output/foo.htmlx') } + it { is_expected.not_to include('output/foo.yhtml') } + end + + context 'when exclude_files is set' do + let(:config_hash) do + { checks: { all: { exclude_files: ['foo.xhtml'] } } } + end + + it { is_expected.to include('output/foo.html') } + it { is_expected.to include('output/foo.htm') } + + it { is_expected.not_to include('output/foo.xhtml') } + it { is_expected.not_to include('output/foo.txt') } + it { is_expected.not_to include('output/foo.htmlx') } + it { is_expected.not_to include('output/foo.yhtml') } + end end end